Agents are built on a shared AgentBase class that manages tools (both FunctionTool and MCP tools), validates tool names to prevent collisions, and handles model-specific defaults and handoff snapshots. Agent execution can be paused at specific tools via StopAtTools, directed to a final output via ToolsToFinalOutputResult, or streamed as AgentToolStreamEvents that capture tool calls and their nested agent runs. MCP (Model Context Protocol) is a standard interface for connecting agents to external tool servers; agents discover and invoke tools exposed by mcp_servers instances at runtime, separately from locally defined FunctionTools.
AgentBase in src/agents/agent.py is the shared base class for both Agent and RealtimeAgent, providing name, handoff_description, tools, mcp_servers, and mcp_config fields, as well as MCP tool retrieval and tool-enable logic.[1]
AgentBase.get_all_tools in src/agents/agent.py evaluates each FunctionTool's is_enabled attribute — which may be a bool or a callable returning MaybeAwaitable[bool] — concurrently via gather_with_cancel, then appends the enabled tools to MCP tools and calls prune_orphaned_tool_search_tools.[1] _validate_codex_tool_name_collisions in src/agents/agent.py raises UserError if any Codex tool (a FunctionTool with _is_codex_tool=True) shares its name with another tool in the list; the error message names the duplicate tools and instructs the caller to provide a unique codex_tool(name=...) per instance.[1]
AgentBase._use_mcp_handoff_snapshot in src/agents/agent.py is a context manager that stores a snapshot of enabled handoffs in the _mcp_handoff_snapshot ContextVar, so that reserved-name generation uses a single consistent set of handoffs for the duration of the context.[1]
_initial_model_settings_for_model in src/agents/agent.py returns model-specific defaults via get_default_model_settings(model_str) when a string model name is provided, per-model defaults when None, and an empty ModelSettings() when a Model object is passed directly.[1]
ToolsToFinalOutputResult in src/agents/agent.py carries two fields: is_final_output (bool) and final_output (Any, defaults to None). When is_final_output is False the LLM runs again with the tool output; when True, final_output must match the agent's output_type.[1] StopAtTools (TypedDict) in src/agents/agent.py contains a single key stop_at_tool_names: list[str]; any tool whose name appears in that list halts further agent execution.[1] AgentToolStreamEvent (TypedDict) in src/agents/agent.py carries three fields: event (the StreamEvent from the nested run), agent (the nested Agent), and tool_call (the originating ResponseFunctionToolCall, or None).[1]
Sources