mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-08 23:58:34 +00:00
Some checks failed
Update Test Durations / update-durations (3.10) (push) Has been cancelled
Update Test Durations / update-durations (3.11) (push) Has been cancelled
Update Test Durations / update-durations (3.12) (push) Has been cancelled
Update Test Durations / update-durations (3.13) (push) Has been cancelled
Notify Downstream / notify-downstream (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
243 lines
8.1 KiB
Python
243 lines
8.1 KiB
Python
"""OpenAI agents adapter for CrewAI integration.
|
|
|
|
This module contains the OpenAIAgentAdapter class that integrates OpenAI Assistants
|
|
with CrewAI's agent system, providing tool integration and structured output support.
|
|
"""
|
|
|
|
from typing import Any, cast
|
|
|
|
from pydantic import ConfigDict, Field, PrivateAttr
|
|
from typing_extensions import Unpack
|
|
|
|
from crewai.agents.agent_adapters.base_agent_adapter import BaseAgentAdapter
|
|
from crewai.agents.agent_adapters.openai_agents.openai_agent_tool_adapter import (
|
|
OpenAIAgentToolAdapter,
|
|
)
|
|
from crewai.agents.agent_adapters.openai_agents.protocols import (
|
|
AgentKwargs,
|
|
OpenAIAgentsModule,
|
|
)
|
|
from crewai.agents.agent_adapters.openai_agents.protocols import (
|
|
OpenAIAgent as OpenAIAgentProtocol,
|
|
)
|
|
from crewai.agents.agent_adapters.openai_agents.structured_output_converter import (
|
|
OpenAIConverterAdapter,
|
|
)
|
|
from crewai.agents.agent_builder.base_agent import BaseAgent
|
|
from crewai.events.event_bus import crewai_event_bus
|
|
from crewai.events.types.agent_events import (
|
|
AgentExecutionCompletedEvent,
|
|
AgentExecutionErrorEvent,
|
|
AgentExecutionStartedEvent,
|
|
)
|
|
from crewai.tools import BaseTool
|
|
from crewai.tools.agent_tools.agent_tools import AgentTools
|
|
from crewai.utilities import Logger
|
|
from crewai.utilities.import_utils import require
|
|
|
|
openai_agents_module = cast(
|
|
OpenAIAgentsModule,
|
|
require(
|
|
"agents",
|
|
purpose="OpenAI agents functionality",
|
|
),
|
|
)
|
|
OpenAIAgent = openai_agents_module.Agent
|
|
Runner = openai_agents_module.Runner
|
|
enable_verbose_stdout_logging = openai_agents_module.enable_verbose_stdout_logging
|
|
|
|
|
|
class OpenAIAgentAdapter(BaseAgentAdapter):
|
|
"""Adapter for OpenAI Assistants.
|
|
|
|
Integrates OpenAI Assistants API with CrewAI's agent system, providing
|
|
tool configuration, structured output handling, and task execution.
|
|
"""
|
|
|
|
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
|
|
_openai_agent: OpenAIAgentProtocol = PrivateAttr()
|
|
_logger: Logger = PrivateAttr(default_factory=Logger)
|
|
_active_thread: str | None = PrivateAttr(default=None)
|
|
function_calling_llm: Any = Field(default=None)
|
|
step_callback: Any = Field(default=None)
|
|
_tool_adapter: OpenAIAgentToolAdapter = PrivateAttr()
|
|
_converter_adapter: OpenAIConverterAdapter = PrivateAttr()
|
|
|
|
def __init__(
|
|
self,
|
|
**kwargs: Unpack[AgentKwargs],
|
|
) -> None:
|
|
"""Initialize the OpenAI agent adapter.
|
|
|
|
Args:
|
|
**kwargs: All initialization arguments including role, goal, backstory,
|
|
model, tools, and agent_config.
|
|
|
|
Raises:
|
|
ImportError: If OpenAI agent dependencies are not installed.
|
|
"""
|
|
self.llm = kwargs.pop("model", "gpt-4o-mini")
|
|
super().__init__(**kwargs)
|
|
self._tool_adapter = OpenAIAgentToolAdapter(tools=kwargs.get("tools"))
|
|
self._converter_adapter = OpenAIConverterAdapter(agent_adapter=self)
|
|
|
|
def _build_system_prompt(self) -> str:
|
|
"""Build a system prompt for the OpenAI agent.
|
|
|
|
Creates a prompt containing the agent's role, goal, and backstory,
|
|
then enhances it with structured output instructions if needed.
|
|
|
|
Returns:
|
|
The complete system prompt string.
|
|
"""
|
|
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: str | None = None,
|
|
tools: list[BaseTool] | None = None,
|
|
) -> str:
|
|
"""Execute a task using the OpenAI Assistant.
|
|
|
|
Configures the assistant, processes the task, and handles event emission
|
|
for execution tracking.
|
|
|
|
Args:
|
|
task: The task object to execute.
|
|
context: Optional context information for the task.
|
|
tools: Optional additional tools for this execution.
|
|
|
|
Returns:
|
|
The final answer from the task execution.
|
|
|
|
Raises:
|
|
Exception: If task execution fails.
|
|
"""
|
|
self._converter_adapter.configure_structured_output(task)
|
|
self.create_agent_executor(tools)
|
|
|
|
if self.verbose:
|
|
enable_verbose_stdout_logging()
|
|
|
|
try:
|
|
task_prompt: str = task.prompt()
|
|
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,
|
|
),
|
|
)
|
|
result: Any = self.agent_executor.run_sync(self._openai_agent, task_prompt)
|
|
final_answer: str = self.handle_execution_result(result)
|
|
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 OpenAI task: {e!s}")
|
|
crewai_event_bus.emit(
|
|
self,
|
|
event=AgentExecutionErrorEvent(
|
|
agent=self,
|
|
task=task,
|
|
error=str(e),
|
|
),
|
|
)
|
|
raise
|
|
|
|
def create_agent_executor(self, tools: list[BaseTool] | None = None) -> None:
|
|
"""Configure the OpenAI agent for execution.
|
|
|
|
While OpenAI handles execution differently through Runner,
|
|
this method sets up tools and agent configuration.
|
|
|
|
Args:
|
|
tools: Optional tools to configure for the agent.
|
|
|
|
Notes:
|
|
TODO: Properly type agent_executor in BaseAgent to avoid type issues
|
|
when assigning Runner class to this attribute.
|
|
"""
|
|
all_tools: list[BaseTool] = list(self.tools or []) + list(tools or [])
|
|
|
|
instructions: str = self._build_system_prompt()
|
|
self._openai_agent = OpenAIAgent(
|
|
name=self.role,
|
|
instructions=instructions,
|
|
model=self.llm,
|
|
**self._agent_config or {},
|
|
)
|
|
|
|
if all_tools:
|
|
self.configure_tools(all_tools)
|
|
|
|
self.agent_executor = Runner
|
|
|
|
def configure_tools(self, tools: list[BaseTool] | None = None) -> None:
|
|
"""Configure tools for the OpenAI Assistant.
|
|
|
|
Args:
|
|
tools: Optional tools to configure for the assistant.
|
|
"""
|
|
if tools:
|
|
self._tool_adapter.configure_tools(tools)
|
|
if self._tool_adapter.converted_tools:
|
|
self._openai_agent.tools = self._tool_adapter.converted_tools
|
|
|
|
def handle_execution_result(self, result: Any) -> str:
|
|
"""Process OpenAI Assistant execution result.
|
|
|
|
Converts any structured output to a string through the converter adapter.
|
|
|
|
Args:
|
|
result: The execution result from the OpenAI assistant.
|
|
|
|
Returns:
|
|
Processed result as a string.
|
|
"""
|
|
return self._converter_adapter.post_process_result(result.final_output)
|
|
|
|
def get_delegation_tools(self, agents: list[BaseAgent]) -> list[BaseTool]:
|
|
"""Implement delegation tools support.
|
|
|
|
Creates delegation tools that allow this agent to delegate tasks to other agents.
|
|
|
|
Args:
|
|
agents: List of agents available for delegation.
|
|
|
|
Returns:
|
|
List of delegation tools.
|
|
"""
|
|
agent_tools: AgentTools = AgentTools(agents=agents)
|
|
return agent_tools.tools()
|
|
|
|
def configure_structured_output(self, task: Any) -> None:
|
|
"""Configure the structured output for the specific agent implementation.
|
|
|
|
Args:
|
|
task: The task object containing output format specifications.
|
|
"""
|
|
self._converter_adapter.configure_structured_output(task)
|