@@ -67,7 +67,63 @@ class MCPConfig(TypedDict):
67
67
68
68
69
69
@dataclass
70
- class Agent (Generic [TContext ]):
70
+ class AgentBase :
71
+ """Base class for `Agent` and `RealtimeAgent`."""
72
+
73
+ name : str
74
+ """The name of the agent."""
75
+
76
+ handoff_description : str | None = None
77
+ """A description of the agent. This is used when the agent is used as a handoff, so that an
78
+ LLM knows what it does and when to invoke it.
79
+ """
80
+
81
+ tools : list [Tool ] = field (default_factory = list )
82
+ """A list of tools that the agent can use."""
83
+
84
+ mcp_servers : list [MCPServer ] = field (default_factory = list )
85
+ """A list of [Model Context Protocol](https://modelcontextprotocol.io/) servers that
86
+ the agent can use. Every time the agent runs, it will include tools from these servers in the
87
+ list of available tools.
88
+
89
+ NOTE: You are expected to manage the lifecycle of these servers. Specifically, you must call
90
+ `server.connect()` before passing it to the agent, and `server.cleanup()` when the server is no
91
+ longer needed.
92
+ """
93
+
94
+ mcp_config : MCPConfig = field (default_factory = lambda : MCPConfig ())
95
+ """Configuration for MCP servers."""
96
+
97
+ async def get_mcp_tools (self , run_context : RunContextWrapper [TContext ]) -> list [Tool ]:
98
+ """Fetches the available tools from the MCP servers."""
99
+ convert_schemas_to_strict = self .mcp_config .get ("convert_schemas_to_strict" , False )
100
+ return await MCPUtil .get_all_function_tools (
101
+ self .mcp_servers , convert_schemas_to_strict , run_context , self
102
+ )
103
+
104
+ async def get_all_tools (self , run_context : RunContextWrapper [Any ]) -> list [Tool ]:
105
+ """All agent tools, including MCP tools and function tools."""
106
+ mcp_tools = await self .get_mcp_tools (run_context )
107
+
108
+ async def _check_tool_enabled (tool : Tool ) -> bool :
109
+ if not isinstance (tool , FunctionTool ):
110
+ return True
111
+
112
+ attr = tool .is_enabled
113
+ if isinstance (attr , bool ):
114
+ return attr
115
+ res = attr (run_context , self )
116
+ if inspect .isawaitable (res ):
117
+ return bool (await res )
118
+ return bool (res )
119
+
120
+ results = await asyncio .gather (* (_check_tool_enabled (t ) for t in self .tools ))
121
+ enabled : list [Tool ] = [t for t , ok in zip (self .tools , results ) if ok ]
122
+ return [* mcp_tools , * enabled ]
123
+
124
+
125
+ @dataclass
126
+ class Agent (AgentBase , Generic [TContext ]):
71
127
"""An agent is an AI model configured with instructions, tools, guardrails, handoffs and more.
72
128
73
129
We strongly recommend passing `instructions`, which is the "system prompt" for the agent. In
@@ -76,10 +132,9 @@ class Agent(Generic[TContext]):
76
132
77
133
Agents are generic on the context type. The context is a (mutable) object you create. It is
78
134
passed to tool functions, handoffs, guardrails, etc.
79
- """
80
135
81
- name : str
82
- """The name of the agent."""
136
+ See `AgentBase` for base parameters that are shared with `RealtimeAgent`s.
137
+ """
83
138
84
139
instructions : (
85
140
str
@@ -103,11 +158,6 @@ class Agent(Generic[TContext]):
103
158
usable with OpenAI models, using the Responses API.
104
159
"""
105
160
106
- handoff_description : str | None = None
107
- """A description of the agent. This is used when the agent is used as a handoff, so that an
108
- LLM knows what it does and when to invoke it.
109
- """
110
-
111
161
handoffs : list [Agent [Any ] | Handoff [TContext ]] = field (default_factory = list )
112
162
"""Handoffs are sub-agents that the agent can delegate to. You can provide a list of handoffs,
113
163
and the agent can choose to delegate to them if relevant. Allows for separation of concerns and
@@ -125,22 +175,6 @@ class Agent(Generic[TContext]):
125
175
"""Configures model-specific tuning parameters (e.g. temperature, top_p).
126
176
"""
127
177
128
- tools : list [Tool ] = field (default_factory = list )
129
- """A list of tools that the agent can use."""
130
-
131
- mcp_servers : list [MCPServer ] = field (default_factory = list )
132
- """A list of [Model Context Protocol](https://modelcontextprotocol.io/) servers that
133
- the agent can use. Every time the agent runs, it will include tools from these servers in the
134
- list of available tools.
135
-
136
- NOTE: You are expected to manage the lifecycle of these servers. Specifically, you must call
137
- `server.connect()` before passing it to the agent, and `server.cleanup()` when the server is no
138
- longer needed.
139
- """
140
-
141
- mcp_config : MCPConfig = field (default_factory = lambda : MCPConfig ())
142
- """Configuration for MCP servers."""
143
-
144
178
input_guardrails : list [InputGuardrail [TContext ]] = field (default_factory = list )
145
179
"""A list of checks that run in parallel to the agent's execution, before generating a
146
180
response. Runs only if the agent is the first agent in the chain.
@@ -255,32 +289,3 @@ async def get_prompt(
255
289
) -> ResponsePromptParam | None :
256
290
"""Get the prompt for the agent."""
257
291
return await PromptUtil .to_model_input (self .prompt , run_context , self )
258
-
259
- async def get_mcp_tools (
260
- self , run_context : RunContextWrapper [TContext ]
261
- ) -> list [Tool ]:
262
- """Fetches the available tools from the MCP servers."""
263
- convert_schemas_to_strict = self .mcp_config .get ("convert_schemas_to_strict" , False )
264
- return await MCPUtil .get_all_function_tools (
265
- self .mcp_servers , convert_schemas_to_strict , run_context , self
266
- )
267
-
268
- async def get_all_tools (self , run_context : RunContextWrapper [Any ]) -> list [Tool ]:
269
- """All agent tools, including MCP tools and function tools."""
270
- mcp_tools = await self .get_mcp_tools (run_context )
271
-
272
- async def _check_tool_enabled (tool : Tool ) -> bool :
273
- if not isinstance (tool , FunctionTool ):
274
- return True
275
-
276
- attr = tool .is_enabled
277
- if isinstance (attr , bool ):
278
- return attr
279
- res = attr (run_context , self )
280
- if inspect .isawaitable (res ):
281
- return bool (await res )
282
- return bool (res )
283
-
284
- results = await asyncio .gather (* (_check_tool_enabled (t ) for t in self .tools ))
285
- enabled : list [Tool ] = [t for t , ok in zip (self .tools , results ) if ok ]
286
- return [* mcp_tools , * enabled ]
0 commit comments