You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
result = agent.run_sync('What tools are available?', toolsets=[weather_toolset])
@@ -110,7 +113,8 @@ print([t.name for t in test_model.last_model_request_parameters.function_tools])
110
113
#> ['now']
111
114
```
112
115
113
-
1. We're using [`TestModel`][pydantic_ai.models.test.TestModel] here because it makes it easy to see which tools were available on each run.
116
+
1.`FunctionToolset` supports an optional `id` argument that can help to identify the toolset in error messages. A toolset also needs to have an ID in order to be used in a durable execution environment like Temporal, in which case the ID will be used to identify the toolset's activities within the workflow.
117
+
2. We're using [`TestModel`][pydantic_ai.models.test.TestModel] here because it makes it easy to see which tools were available on each run.
114
118
115
119
_(This example is complete, it can be run "as is")_
116
120
@@ -609,7 +613,7 @@ from pydantic_ai.ext.langchain import LangChainToolset
"""Runs an MCP server in a subprocess and communicates with it over stdin/stdout.
300
328
@@ -378,11 +406,61 @@ async def main():
378
406
allow_sampling: bool=True
379
407
"""Whether to allow MCP sampling through this client."""
380
408
409
+
sampling_model: models.Model|None=None
410
+
"""The model to use for sampling."""
411
+
381
412
max_retries: int=1
382
413
"""The maximum number of times to retry a tool call."""
383
414
384
-
sampling_model: models.Model|None=None
385
-
"""The model to use for sampling."""
415
+
def__init__(
416
+
self,
417
+
command: str,
418
+
args: Sequence[str],
419
+
env: dict[str, str] |None=None,
420
+
cwd: str|Path|None=None,
421
+
id: str|None=None,
422
+
tool_prefix: str|None=None,
423
+
log_level: mcp_types.LoggingLevel|None=None,
424
+
log_handler: LoggingFnT|None=None,
425
+
timeout: float=5,
426
+
process_tool_call: ProcessToolCallback|None=None,
427
+
allow_sampling: bool=True,
428
+
sampling_model: models.Model|None=None,
429
+
max_retries: int=1,
430
+
):
431
+
"""Build a new MCP server.
432
+
433
+
Args:
434
+
command: The command to run.
435
+
args: The arguments to pass to the command.
436
+
env: The environment variables to set in the subprocess.
437
+
cwd: The working directory to use when spawning the process.
438
+
id: An optional unique ID for the MCP server. An MCP server needs to have an ID in order to be used in a durable execution environment like Temporal, in which case the ID will be used to identify the server's activities within the workflow.
439
+
tool_prefix: A prefix to add to all tools that are registered with the server.
440
+
log_level: The log level to set when connecting to the server, if any.
441
+
log_handler: A handler for logging messages from the server.
442
+
timeout: The timeout in seconds to wait for the client to initialize.
443
+
process_tool_call: Hook to customize tool calling and optionally pass extra metadata.
444
+
allow_sampling: Whether to allow MCP sampling through this client.
445
+
sampling_model: The model to use for sampling.
446
+
max_retries: The maximum number of times to retry a tool call.
@@ -479,11 +560,61 @@ class _MCPServerHTTP(MCPServer):
479
560
allow_sampling: bool=True
480
561
"""Whether to allow MCP sampling through this client."""
481
562
563
+
sampling_model: models.Model|None=None
564
+
"""The model to use for sampling."""
565
+
482
566
max_retries: int=1
483
567
"""The maximum number of times to retry a tool call."""
484
568
485
-
sampling_model: models.Model|None=None
486
-
"""The model to use for sampling."""
569
+
def__init__(
570
+
self,
571
+
url: str,
572
+
headers: dict[str, Any] |None=None,
573
+
http_client: httpx.AsyncClient|None=None,
574
+
sse_read_timeout: float=5*60,
575
+
id: str|None=None,
576
+
tool_prefix: str|None=None,
577
+
log_level: mcp_types.LoggingLevel|None=None,
578
+
log_handler: LoggingFnT|None=None,
579
+
timeout: float=5,
580
+
process_tool_call: ProcessToolCallback|None=None,
581
+
allow_sampling: bool=True,
582
+
sampling_model: models.Model|None=None,
583
+
max_retries: int=1,
584
+
):
585
+
"""Build a new MCP server.
586
+
587
+
Args:
588
+
url: The URL of the endpoint on the MCP server.
589
+
headers: Optional HTTP headers to be sent with each request to the endpoint.
590
+
http_client: An `httpx.AsyncClient` to use with the endpoint.
591
+
sse_read_timeout: Maximum time in seconds to wait for new SSE messages before timing out.
592
+
id: An optional unique ID for the MCP server. An MCP server needs to have an ID in order to be used in a durable execution environment like Temporal, in which case the ID will be used to identify the server's activities within the workflow.
593
+
tool_prefix: A prefix to add to all tools that are registered with the server.
594
+
log_level: The log level to set when connecting to the server, if any.
595
+
log_handler: A handler for logging messages from the server.
596
+
timeout: The timeout in seconds to wait for the client to initialize.
597
+
process_tool_call: Hook to customize tool calling and optionally pass extra metadata.
598
+
allow_sampling: Whether to allow MCP sampling through this client.
599
+
sampling_model: The model to use for sampling.
600
+
max_retries: The maximum number of times to retry a tool call.
Copy file name to clipboardExpand all lines: pydantic_ai_slim/pydantic_ai/toolsets/abstract.py
+16-2Lines changed: 16 additions & 2 deletions
Original file line number
Diff line number
Diff line change
@@ -70,9 +70,23 @@ class AbstractToolset(ABC, Generic[AgentDepsT]):
70
70
"""
71
71
72
72
@property
73
-
defname(self) ->str:
73
+
@abstractmethod
74
+
defid(self) ->str|None:
75
+
"""An ID for the toolset that is unique among all toolsets registered with the same agent.
76
+
77
+
If you're implementing a concrete implementation that users can instantiate more than once, you should let them optionally pass a custom ID to the constructor and return that here.
78
+
79
+
A toolset needs to have an ID in order to be used in a durable execution environment like Temporal, in which case the ID will be used to identify the toolset's activities within the workflow.
80
+
"""
81
+
raiseNotImplementedError()
82
+
83
+
@property
84
+
deflabel(self) ->str:
74
85
"""The name of the toolset for use in error messages."""
f'{toolset.name} defines a tool whose name conflicts with existing tool from {existing_tools.toolset.name}: {name!r}. {toolset.tool_name_conflict_hint}'
75
+
f'{toolset.label} defines a tool whose name conflicts with existing tool from {existing_tools.toolset.label}: {name!r}. {toolset.tool_name_conflict_hint}'
0 commit comments