Skip to content

Conversation

@XiuShenAl
Copy link
Collaborator

Description

Support CrewAI

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactoring

Component(s) Affected

  • Engine
  • Sandbox
  • Tools
  • Common
  • Documentation
  • Tests
  • CI/CD

Checklist

  • Pre-commit hooks pass
  • Tests pass locally
  • Documentation updated (if needed)
  • Ready for review

@XiuShenAl XiuShenAl requested a review from a team December 31, 2025 07:47
@XiuShenAl XiuShenAl force-pushed the feat/crewai-adapter branch from bc4acbb to e9e510c Compare January 4, 2026 03:30
@XiuShenAl XiuShenAl force-pushed the feat/crewai-adapter branch from e9e510c to bca1c50 Compare January 4, 2026 03:48
@rayrayraykk
Copy link
Member

Due to incompatibility between the current crewAI version and the latest OpenAI release, the integration with our existing components is currently non-functional. We recommend postponing changes depending on crewAI until an official fix is provided.

Reference issue: crewAIInc/crewAI#4079

As for the incompatibility with Otel, we should separate ms-agent-framework and crewAI into two optional installation groups to reduce coupling and minimize potential conflicts.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive CrewAI framework adapter support to AgentScope Runtime, enabling developers to build collaborative autonomous agents with multi-turn conversations, session memory, and streaming responses.

Key Changes:

  • Adds CrewAI adapter implementation with message conversion, streaming, memory, and tool adapters
  • Integrates CrewAI as a supported framework in the engine (runner, constants, and app registration)
  • Includes comprehensive integration tests and bilingual documentation

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/integrated/test_crewai_agent_app.py Integration tests for CrewAI adapter with streaming, OpenAI-compatible mode, and multi-turn conversation tests
src/agentscope_runtime/engine/runner.py Adds CrewAI message stream adapter integration in the streaming query handler
src/agentscope_runtime/engine/constant.py Registers "crewai" as a supported framework
src/agentscope_runtime/engine/app/agent_app.py Adds "crewai" to allowed frameworks in query decorator
src/agentscope_runtime/adapters/crewai/message.py Converts AgentScope runtime messages to CrewAI-compatible format
src/agentscope_runtime/adapters/crewai/stream.py Adapts CrewAI streaming chunks to runtime message format with reasoning/message mode parsing
src/agentscope_runtime/adapters/crewai/memory/_external_memory_adapter.py CrewAI external memory adapter using SessionHistoryService for persistence
src/agentscope_runtime/adapters/crewai/tool/tool.py Tool adapter converting runtime tools to CrewAI BaseTool format
cookbook/en/crewai_guidelines.md English documentation guide for CrewAI integration
cookbook/zh/crewai_guidelines.md Chinese documentation guide for CrewAI integration
pyproject.toml Adds crewai>=1.6.1 dependency to ext optional dependencies
README.md / README_zh.md Updates framework support table with CrewAI entry
cookbook/_toc.yml Adds CrewAI guidelines to documentation table of contents

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -0,0 +1,280 @@
# -*- coding: utf-8 -*-
# tests/api/test_crewai_agent_app.py
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file path comment is incorrect. It states "tests/api/test_crewai_agent_app.py" but the actual file is located at "tests/integrated/test_crewai_agent_app.py". This should be updated to match the actual file location.

Suggested change
# tests/api/test_crewai_agent_app.py
# tests/integrated/test_crewai_agent_app.py

Copilot uses AI. Check for mistakes.
f"Investigate the following user query: '{user_question}'"
),
expected_output=(
"A comprehensive yet easy-to-read answer"
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space in the concatenated string. The expected output should have a space between "answer" and "that" for readability.

Suggested change
"A comprehensive yet easy-to-read answer"
"A comprehensive yet easy-to-read answer "

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +20
agno_message = await formatter.format(as_msgs)

return agno_message if raw_list else agno_message[0]
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name "agno_message" is misleading. This is a CrewAI adapter, not an Agno adapter, so the variable should be named "crewai_message" or a more generic name like "formatted_message" to accurately reflect its purpose.

Suggested change
agno_message = await formatter.format(as_msgs)
return agno_message if raw_list else agno_message[0]
crewai_message = await formatter.format(as_msgs)
return crewai_message if raw_list else crewai_message[0]

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +20
agno_message = await formatter.format(as_msgs)

return agno_message if raw_list else agno_message[0]
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name "agno_message" is misleading. This is a CrewAI adapter, not an Agno adapter, so the variable should be named "crewai_message" or a more generic name like "formatted_message" to accurately reflect its purpose.

Suggested change
agno_message = await formatter.format(as_msgs)
return agno_message if raw_list else agno_message[0]
crewai_message = await formatter.format(as_msgs)
return crewai_message if raw_list else crewai_message[0]

Copilot uses AI. Check for mistakes.

break
# elif event.chunk_type == StreamChunkType.TOOL_CALL:
# Not support now
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammatical error in the comment. "Not support now" should be "Not supported now" for correct grammar.

Suggested change
# Not support now
# Not supported now

Copilot uses AI. Check for mistakes.

async def message_to_crewai_message(
messages: Union[Message, List[Message]],
) -> Union[dict, List[dict]]:
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing docstring for the function. Based on similar adapters (e.g., the Agno adapter), this function should include a docstring that explains what the function does, its arguments, and return values. For example: "Convert AgentScope runtime Message(s) to CrewAI Message(s)."

Suggested change
) -> Union[dict, List[dict]]:
) -> Union[dict, List[dict]]:
"""
Convert AgentScope runtime Message(s) to CrewAI-compatible message dict(s).
This function first converts the given AgentScope runtime ``Message`` or list
of ``Message`` objects into AgentScope messages, and then uses
``OpenAIChatFormatter`` to produce CrewAI-compatible message dictionaries.
Args:
messages: A single ``Message`` instance or a list of ``Message`` instances
from the AgentScope runtime.
Returns:
A single dictionary if ``messages`` is a single ``Message``; otherwise a
list of dictionaries, each representing a CrewAI-compatible message.
"""

Copilot uses AI. Check for mistakes.
obs_json = json.loads(obs_text)
if isinstance(obs_json, dict) and "request_id" in obs_json:
call_id = obs_json["request_id"]
except (json.JSONDecodeError, TypeError):
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'except' clause does nothing but pass and there is no explanatory comment.

Suggested change
except (json.JSONDecodeError, TypeError):
except (json.JSONDecodeError, TypeError):
# If the observation text is not valid JSON or does not have the
# expected structure, we ignore the error and fall back to
# generating a new call_id below.

Copilot uses AI. Check for mistakes.
].lower()
if "alice" in text_content:
found_name = True
except Exception:
Copy link

Copilot AI Jan 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'except' clause does nothing but pass and there is no explanatory comment.

Suggested change
except Exception:
except Exception:
# Ignore malformed or unexpected output chunks; only well-formed
# responses should contribute to found_name in this streaming test.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants