mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-08 15:48:29 +00:00
Some checks are pending
Notify Downstream / notify-downstream (push) Waiting to run
* feat: add OpenAI agent adapter implementation - Introduced OpenAIAgentAdapter class to facilitate interaction with OpenAI Assistants. - Implemented methods for task execution, tool configuration, and response processing. - Added support for converting CrewAI tools to OpenAI format and handling delegation tools. * created an adapter for the delegate and ask_question tools * delegate and ask_questions work and it delegates to crewai agents* * refactor: introduce OpenAIAgentToolAdapter for tool management - Created OpenAIAgentToolAdapter class to encapsulate tool configuration and conversion for OpenAI Assistant. - Removed tool configuration logic from OpenAIAgentAdapter and integrated it into the new adapter. - Enhanced the tool conversion process to ensure compatibility with OpenAI's requirements. * feat: implement BaseAgentAdapter for agent integration - Introduced BaseAgentAdapter as an abstract base class for agent adapters in CrewAI. - Defined common interface and methods for configuring tools and structured output. - Updated OpenAIAgentAdapter to inherit from BaseAgentAdapter, enhancing its structure and functionality. * feat: add LangGraph agent and tool adapter for CrewAI integration - Introduced LangGraphAgentAdapter to facilitate interaction with LangGraph agents. - Implemented methods for task execution, context handling, and tool configuration. - Created LangGraphToolAdapter to convert CrewAI tools into LangGraph-compatible format. - Enhanced error handling and logging for task execution and streaming processes. * feat: enhance LangGraphToolAdapter and improve conversion instructions - Added type hints for better clarity and type checking in LangGraphToolAdapter. - Updated conversion instructions to ensure compatibility with optional LLM checks. * feat: integrate structured output handling in LangGraph and OpenAI agents - Added LangGraphConverterAdapter for managing structured output in LangGraph agents. - Enhanced LangGraphAgentAdapter to utilize the new converter for system prompt and task execution. - Updated LangGraphToolAdapter to use StructuredTool for better compatibility. - Introduced OpenAIConverterAdapter for structured output management in OpenAI agents. - Improved task execution flow in OpenAIAgentAdapter to incorporate structured output configuration and post-processing. * feat: implement BaseToolAdapter for tool integration - Introduced BaseToolAdapter as an abstract base class for tool adapters in CrewAI. - Updated LangGraphToolAdapter and OpenAIAgentToolAdapter to inherit from BaseToolAdapter, enhancing their structure and functionality. - Improved tool configuration methods to support better integration with various frameworks. - Added type hints and documentation for clarity and maintainability. * feat: enhance OpenAIAgentAdapter with configurable agent properties - Refactored OpenAIAgentAdapter to accept agent configuration as an argument. - Introduced a method to build a system prompt for the OpenAI agent, improving task execution context. - Updated initialization to utilize role, goal, and backstory from kwargs, enhancing flexibility in agent setup. - Improved tool handling and integration within the adapter. * feat: enhance agent adapters with structured output support - Introduced BaseConverterAdapter as an abstract class for structured output handling. - Implemented LangGraphConverterAdapter and OpenAIConverterAdapter to manage structured output in their respective agents. - Updated BaseAgentAdapter to accept an agent configuration dictionary during initialization. - Enhanced LangGraphAgentAdapter to utilize the new converter and improved tool handling. - Added methods for configuring structured output and enhancing system prompts in converter adapters. * refactor: remove _parse_tools method from OpenAIAgentAdapter and BaseAgent - Eliminated the _parse_tools method from OpenAIAgentAdapter and its abstract declaration in BaseAgent. - Cleaned up related test code in MockAgent to reflect the removal of the method. * also removed _parse_tools here as not used * feat: add dynamic import handling for LangGraph dependencies - Implemented conditional imports for LangGraph components to handle ImportError gracefully. - Updated LangGraphAgentAdapter initialization to check for LangGraph availability and raise an informative error if dependencies are missing. - Enhanced the agent adapter's robustness by ensuring it only initializes components when the required libraries are present. * fix: improve error handling for agent adapters - Updated LangGraphAgentAdapter to raise an ImportError with a clear message if LangGraph dependencies are not installed. - Refactored OpenAIAgentAdapter to include a similar check for OpenAI dependencies, ensuring robust initialization and user guidance for missing libraries. - Enhanced overall error handling in agent adapters to prevent runtime issues when dependencies are unavailable. * refactor: enhance tool handling in agent adapters - Updated BaseToolAdapter to initialize original and converted tools in the constructor. - Renamed method `all_tools` to `tools` for clarity in BaseToolAdapter. - Added `sanitize_tool_name` method to ensure tool names are API compatible. - Modified LangGraphAgentAdapter to utilize the updated tool handling and ensure proper tool configuration. - Refactored LangGraphToolAdapter to streamline tool conversion and ensure consistent naming conventions. * feat: emit AgentExecutionCompletedEvent in agent adapters - Added emission of AgentExecutionCompletedEvent in both LangGraphAgentAdapter and OpenAIAgentAdapter to signal task completion. - Enhanced event handling to include agent, task, and output details for better tracking of execution results. * docs: Enhance BaseConverterAdapter documentation - Added a detailed docstring to the BaseConverterAdapter class, outlining its purpose and the expected functionality for all converter adapters. - Updated the post_process_result method's docstring to specify the expected format of the result as a string. * docs: Add comprehensive guide for bringing custom agents into CrewAI - Introduced a new documentation file detailing the process of integrating custom agents using the BaseAgentAdapter, BaseToolAdapter, and BaseConverter. - Included step-by-step instructions for creating custom adapters, configuring tools, and handling structured output. - Provided examples for implementing adapters for various frameworks, enhancing the usability of CrewAI for developers. * feat: Introduce adapted_agent flag in BaseAgent and update BaseAgentAdapter initialization - Added an `adapted_agent` boolean field to the BaseAgent class to indicate if the agent is adapted. - Updated the BaseAgentAdapter's constructor to pass `adapted_agent=True` to the superclass, ensuring proper initialization of the new field. * feat: Enhance LangGraphAgentAdapter to support optional agent configuration - Updated LangGraphAgentAdapter to conditionally apply agent configuration when creating the agent graph, allowing for more flexible initialization. - Modified LangGraphToolAdapter to ensure only instances of BaseTool are converted, improving tool compatibility and handling. * feat: Introduce OpenAIConverterAdapter for structured output handling - Added OpenAIConverterAdapter to manage structured output conversion for OpenAI agents, enhancing their ability to process and format results. - Updated OpenAIAgentAdapter to utilize the new converter for configuring structured output and post-processing results. - Removed the deprecated get_output_converter method from OpenAIAgentAdapter. - Added unit tests for BaseAgentAdapter and BaseToolAdapter to ensure proper functionality and integration of new features. * feat: Enhance tool adapters to support asynchronous execution - Updated LangGraphToolAdapter and OpenAIAgentToolAdapter to handle asynchronous tool execution by checking if the output is awaitable. - Introduced `inspect` import to facilitate the awaitability check. - Refactored tool wrapper functions to ensure proper handling of both synchronous and asynchronous tool results. * fix: Correct method definition syntax and enhance tool adapter implementation - Updated the method definition for `configure_structured_output` to include the `def` keyword for clarity. - Added an asynchronous tool wrapper to ensure tools can operate in both synchronous and asynchronous contexts. - Modified the constructor of the custom converter adapter to directly assign the agent adapter, improving clarity and functionality. * linted * refactor: Improve tool processing logic in BaseAgent - Added a check to return an empty list if no tools are provided. - Simplified the tool attribute validation by using a list of required attributes. - Removed commented-out abstract method definition for clarity. * refactor: Simplify tool handling in agent adapters - Changed default value of `tools` parameter in LangGraphAgentAdapter to None for better handling of empty tool lists. - Updated tool initialization in both LangGraphAgentAdapter and OpenAIAgentAdapter to directly pass the `tools` parameter, removing unnecessary list handling. - Cleaned up commented-out code in OpenAIConverterAdapter to improve readability. * refactor: Remove unused stream_task method from LangGraphAgentAdapter - Deleted the `stream_task` method from LangGraphAgentAdapter to streamline the code and eliminate unnecessary complexity. - This change enhances maintainability by focusing on essential functionalities within the agent adapter.
227 lines
7.7 KiB
Python
227 lines
7.7 KiB
Python
from typing import Any, AsyncIterable, Dict, List, Optional
|
|
|
|
from pydantic import Field, PrivateAttr
|
|
|
|
from crewai.agents.agent_adapters.base_agent_adapter import BaseAgentAdapter
|
|
from crewai.agents.agent_adapters.langgraph.langgraph_tool_adapter import (
|
|
LangGraphToolAdapter,
|
|
)
|
|
from crewai.agents.agent_adapters.langgraph.structured_output_converter import (
|
|
LangGraphConverterAdapter,
|
|
)
|
|
from crewai.agents.agent_builder.base_agent import BaseAgent
|
|
from crewai.tools.agent_tools.agent_tools import AgentTools
|
|
from crewai.tools.base_tool import BaseTool
|
|
from crewai.utilities import Logger
|
|
from crewai.utilities.converter import Converter
|
|
from crewai.utilities.events import crewai_event_bus
|
|
from crewai.utilities.events.agent_events import (
|
|
AgentExecutionCompletedEvent,
|
|
AgentExecutionErrorEvent,
|
|
AgentExecutionStartedEvent,
|
|
)
|
|
|
|
try:
|
|
from langchain_core.messages import ToolMessage
|
|
from langgraph.checkpoint.memory import MemorySaver
|
|
from langgraph.prebuilt import create_react_agent
|
|
|
|
LANGGRAPH_AVAILABLE = True
|
|
except ImportError:
|
|
LANGGRAPH_AVAILABLE = False
|
|
|
|
|
|
class LangGraphAgentAdapter(BaseAgentAdapter):
|
|
"""Adapter for LangGraph agents to work with CrewAI."""
|
|
|
|
model_config = {"arbitrary_types_allowed": True}
|
|
|
|
_logger: Logger = PrivateAttr(default_factory=lambda: Logger())
|
|
_tool_adapter: LangGraphToolAdapter = PrivateAttr()
|
|
_graph: Any = PrivateAttr(default=None)
|
|
_memory: Any = PrivateAttr(default=None)
|
|
_max_iterations: int = PrivateAttr(default=10)
|
|
function_calling_llm: Any = Field(default=None)
|
|
step_callback: Any = Field(default=None)
|
|
|
|
model: str = Field(default="gpt-4o")
|
|
verbose: bool = Field(default=False)
|
|
|
|
def __init__(
|
|
self,
|
|
role: str,
|
|
goal: str,
|
|
backstory: str,
|
|
tools: Optional[List[BaseTool]] = None,
|
|
llm: Any = None,
|
|
max_iterations: int = 10,
|
|
agent_config: Optional[Dict[str, Any]] = None,
|
|
**kwargs,
|
|
):
|
|
"""Initialize the LangGraph agent adapter."""
|
|
if not LANGGRAPH_AVAILABLE:
|
|
raise ImportError(
|
|
"LangGraph Agent Dependencies are not installed. Please install it using `uv add langchain-core langgraph`"
|
|
)
|
|
super().__init__(
|
|
role=role,
|
|
goal=goal,
|
|
backstory=backstory,
|
|
tools=tools,
|
|
llm=llm or self.model,
|
|
agent_config=agent_config,
|
|
**kwargs,
|
|
)
|
|
self._tool_adapter = LangGraphToolAdapter(tools=tools)
|
|
self._converter_adapter = LangGraphConverterAdapter(self)
|
|
self._max_iterations = max_iterations
|
|
self._setup_graph()
|
|
|
|
def _setup_graph(self) -> None:
|
|
"""Set up the LangGraph workflow graph."""
|
|
try:
|
|
self._memory = MemorySaver()
|
|
|
|
converted_tools: List[Any] = self._tool_adapter.tools()
|
|
if self._agent_config:
|
|
self._graph = create_react_agent(
|
|
model=self.llm,
|
|
tools=converted_tools,
|
|
checkpointer=self._memory,
|
|
debug=self.verbose,
|
|
**self._agent_config,
|
|
)
|
|
else:
|
|
self._graph = create_react_agent(
|
|
model=self.llm,
|
|
tools=converted_tools or [],
|
|
checkpointer=self._memory,
|
|
debug=self.verbose,
|
|
)
|
|
|
|
except ImportError as e:
|
|
self._logger.log(
|
|
"error", f"Failed to import LangGraph dependencies: {str(e)}"
|
|
)
|
|
raise
|
|
except Exception as e:
|
|
self._logger.log("error", f"Error setting up LangGraph agent: {str(e)}")
|
|
raise
|
|
|
|
def _build_system_prompt(self) -> str:
|
|
"""Build a system prompt for the LangGraph agent."""
|
|
base_prompt = f"""
|
|
You are {self.role}.
|
|
|
|
Your goal is: {self.goal}
|
|
|
|
Your backstory: {self.backstory}
|
|
|
|
When working on tasks, think step-by-step and use the available tools when necessary.
|
|
"""
|
|
return self._converter_adapter.enhance_system_prompt(base_prompt)
|
|
|
|
def execute_task(
|
|
self,
|
|
task: Any,
|
|
context: Optional[str] = None,
|
|
tools: Optional[List[BaseTool]] = None,
|
|
) -> str:
|
|
"""Execute a task using the LangGraph workflow."""
|
|
self.create_agent_executor(tools)
|
|
|
|
self.configure_structured_output(task)
|
|
|
|
try:
|
|
task_prompt = task.prompt() if hasattr(task, "prompt") else str(task)
|
|
|
|
if context:
|
|
task_prompt = self.i18n.slice("task_with_context").format(
|
|
task=task_prompt, context=context
|
|
)
|
|
|
|
crewai_event_bus.emit(
|
|
self,
|
|
event=AgentExecutionStartedEvent(
|
|
agent=self,
|
|
tools=self.tools,
|
|
task_prompt=task_prompt,
|
|
task=task,
|
|
),
|
|
)
|
|
|
|
session_id = f"task_{id(task)}"
|
|
|
|
config = {"configurable": {"thread_id": session_id}}
|
|
|
|
result = self._graph.invoke(
|
|
{
|
|
"messages": [
|
|
("system", self._build_system_prompt()),
|
|
("user", task_prompt),
|
|
]
|
|
},
|
|
config,
|
|
)
|
|
|
|
messages = result.get("messages", [])
|
|
last_message = messages[-1] if messages else None
|
|
|
|
final_answer = ""
|
|
if isinstance(last_message, dict):
|
|
final_answer = last_message.get("content", "")
|
|
elif hasattr(last_message, "content"):
|
|
final_answer = getattr(last_message, "content", "")
|
|
|
|
final_answer = (
|
|
self._converter_adapter.post_process_result(final_answer)
|
|
or "Task execution completed but no clear answer was provided."
|
|
)
|
|
crewai_event_bus.emit(
|
|
self,
|
|
event=AgentExecutionCompletedEvent(
|
|
agent=self, task=task, output=final_answer
|
|
),
|
|
)
|
|
|
|
return final_answer
|
|
|
|
except Exception as e:
|
|
self._logger.log("error", f"Error executing LangGraph task: {str(e)}")
|
|
crewai_event_bus.emit(
|
|
self,
|
|
event=AgentExecutionErrorEvent(
|
|
agent=self,
|
|
task=task,
|
|
error=str(e),
|
|
),
|
|
)
|
|
raise
|
|
|
|
def create_agent_executor(self, tools: Optional[List[BaseTool]] = None) -> None:
|
|
"""Configure the LangGraph agent for execution."""
|
|
self.configure_tools(tools)
|
|
|
|
def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None:
|
|
"""Configure tools for the LangGraph agent."""
|
|
if tools:
|
|
all_tools = list(self.tools or []) + list(tools or [])
|
|
self._tool_adapter.configure_tools(all_tools)
|
|
available_tools = self._tool_adapter.tools()
|
|
self._graph.tools = available_tools
|
|
|
|
def get_delegation_tools(self, agents: List[BaseAgent]) -> List[BaseTool]:
|
|
"""Implement delegation tools support for LangGraph."""
|
|
agent_tools = AgentTools(agents=agents)
|
|
return agent_tools.tools()
|
|
|
|
def get_output_converter(
|
|
self, llm: Any, text: str, model: Any, instructions: str
|
|
) -> Any:
|
|
"""Convert output format if needed."""
|
|
return Converter(llm=llm, text=text, model=model, instructions=instructions)
|
|
|
|
def configure_structured_output(self, task) -> None:
|
|
"""Configure the structured output for LangGraph."""
|
|
self._converter_adapter.configure_structured_output(task)
|