pydantic-ai-slim 1.0.6__py3-none-any.whl → 1.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pydantic-ai-slim might be problematic. Click here for more details.
- pydantic_ai/_agent_graph.py +208 -127
- pydantic_ai/ag_ui.py +44 -33
- pydantic_ai/agent/__init__.py +38 -46
- pydantic_ai/agent/abstract.py +7 -7
- pydantic_ai/agent/wrapper.py +0 -1
- pydantic_ai/durable_exec/dbos/_agent.py +14 -10
- pydantic_ai/durable_exec/dbos/_mcp_server.py +4 -2
- pydantic_ai/durable_exec/temporal/_agent.py +0 -1
- pydantic_ai/durable_exec/temporal/_logfire.py +15 -3
- pydantic_ai/durable_exec/temporal/_toolset.py +17 -12
- pydantic_ai/mcp.py +5 -0
- pydantic_ai/run.py +0 -2
- pydantic_ai/tools.py +11 -0
- pydantic_ai/toolsets/function.py +50 -9
- {pydantic_ai_slim-1.0.6.dist-info → pydantic_ai_slim-1.0.7.dist-info}/METADATA +3 -3
- {pydantic_ai_slim-1.0.6.dist-info → pydantic_ai_slim-1.0.7.dist-info}/RECORD +19 -19
- {pydantic_ai_slim-1.0.6.dist-info → pydantic_ai_slim-1.0.7.dist-info}/WHEEL +0 -0
- {pydantic_ai_slim-1.0.6.dist-info → pydantic_ai_slim-1.0.7.dist-info}/entry_points.txt +0 -0
- {pydantic_ai_slim-1.0.6.dist-info → pydantic_ai_slim-1.0.7.dist-info}/licenses/LICENSE +0 -0
pydantic_ai/agent/__init__.py
CHANGED
|
@@ -45,15 +45,11 @@ from ..run import AgentRun, AgentRunResult
|
|
|
45
45
|
from ..settings import ModelSettings, merge_model_settings
|
|
46
46
|
from ..tools import (
|
|
47
47
|
AgentDepsT,
|
|
48
|
-
DeferredToolCallResult,
|
|
49
|
-
DeferredToolResult,
|
|
50
48
|
DeferredToolResults,
|
|
51
49
|
DocstringFormat,
|
|
52
50
|
GenerateToolJsonSchema,
|
|
53
51
|
RunContext,
|
|
54
52
|
Tool,
|
|
55
|
-
ToolApproved,
|
|
56
|
-
ToolDenied,
|
|
57
53
|
ToolFuncContext,
|
|
58
54
|
ToolFuncEither,
|
|
59
55
|
ToolFuncPlain,
|
|
@@ -462,7 +458,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
462
458
|
) -> AbstractAsyncContextManager[AgentRun[AgentDepsT, RunOutputDataT]]: ...
|
|
463
459
|
|
|
464
460
|
@asynccontextmanager
|
|
465
|
-
async def iter(
|
|
461
|
+
async def iter(
|
|
466
462
|
self,
|
|
467
463
|
user_prompt: str | Sequence[_messages.UserContent] | None = None,
|
|
468
464
|
*,
|
|
@@ -505,7 +501,6 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
505
501
|
[
|
|
506
502
|
UserPromptNode(
|
|
507
503
|
user_prompt='What is the capital of France?',
|
|
508
|
-
instructions=None,
|
|
509
504
|
instructions_functions=[],
|
|
510
505
|
system_prompts=(),
|
|
511
506
|
system_prompt_functions=[],
|
|
@@ -559,7 +554,6 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
559
554
|
del model
|
|
560
555
|
|
|
561
556
|
deps = self._get_deps(deps)
|
|
562
|
-
new_message_index = len(message_history) if message_history else 0
|
|
563
557
|
output_schema = self._prepare_output_schema(output_type, model_used.profile)
|
|
564
558
|
|
|
565
559
|
output_type_ = output_type or self.output_type
|
|
@@ -620,27 +614,12 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
620
614
|
instrumentation_settings = None
|
|
621
615
|
tracer = NoOpTracer()
|
|
622
616
|
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
for tool_call_id, approval in deferred_tool_results.approvals.items():
|
|
627
|
-
if approval is True:
|
|
628
|
-
approval = ToolApproved()
|
|
629
|
-
elif approval is False:
|
|
630
|
-
approval = ToolDenied()
|
|
631
|
-
tool_call_results[tool_call_id] = approval
|
|
632
|
-
|
|
633
|
-
if calls := deferred_tool_results.calls:
|
|
634
|
-
call_result_types = _utils.get_union_args(DeferredToolCallResult)
|
|
635
|
-
for tool_call_id, result in calls.items():
|
|
636
|
-
if not isinstance(result, call_result_types):
|
|
637
|
-
result = _messages.ToolReturn(result)
|
|
638
|
-
tool_call_results[tool_call_id] = result
|
|
639
|
-
|
|
640
|
-
graph_deps = _agent_graph.GraphAgentDeps[AgentDepsT, RunOutputDataT](
|
|
617
|
+
graph_deps = _agent_graph.GraphAgentDeps[
|
|
618
|
+
AgentDepsT, RunOutputDataT
|
|
619
|
+
](
|
|
641
620
|
user_deps=deps,
|
|
642
621
|
prompt=user_prompt,
|
|
643
|
-
new_message_index=
|
|
622
|
+
new_message_index=0, # This will be set in `UserPromptNode` based on the length of the cleaned message history
|
|
644
623
|
model=model_used,
|
|
645
624
|
model_settings=model_settings,
|
|
646
625
|
usage_limits=usage_limits,
|
|
@@ -651,13 +630,13 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
651
630
|
history_processors=self.history_processors,
|
|
652
631
|
builtin_tools=list(self._builtin_tools),
|
|
653
632
|
tool_manager=tool_manager,
|
|
654
|
-
tool_call_results=tool_call_results,
|
|
655
633
|
tracer=tracer,
|
|
656
634
|
get_instructions=get_instructions,
|
|
657
635
|
instrumentation_settings=instrumentation_settings,
|
|
658
636
|
)
|
|
659
637
|
start_node = _agent_graph.UserPromptNode[AgentDepsT](
|
|
660
638
|
user_prompt=user_prompt,
|
|
639
|
+
deferred_tool_results=deferred_tool_results,
|
|
661
640
|
instructions=self._instructions,
|
|
662
641
|
instructions_functions=self._instructions_functions,
|
|
663
642
|
system_prompts=self._system_prompts,
|
|
@@ -1005,7 +984,9 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1005
984
|
require_parameter_descriptions: bool = False,
|
|
1006
985
|
schema_generator: type[GenerateJsonSchema] = GenerateToolJsonSchema,
|
|
1007
986
|
strict: bool | None = None,
|
|
987
|
+
sequential: bool = False,
|
|
1008
988
|
requires_approval: bool = False,
|
|
989
|
+
metadata: dict[str, Any] | None = None,
|
|
1009
990
|
) -> Callable[[ToolFuncContext[AgentDepsT, ToolParams]], ToolFuncContext[AgentDepsT, ToolParams]]: ...
|
|
1010
991
|
|
|
1011
992
|
def tool(
|
|
@@ -1020,7 +1001,9 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1020
1001
|
require_parameter_descriptions: bool = False,
|
|
1021
1002
|
schema_generator: type[GenerateJsonSchema] = GenerateToolJsonSchema,
|
|
1022
1003
|
strict: bool | None = None,
|
|
1004
|
+
sequential: bool = False,
|
|
1023
1005
|
requires_approval: bool = False,
|
|
1006
|
+
metadata: dict[str, Any] | None = None,
|
|
1024
1007
|
) -> Any:
|
|
1025
1008
|
"""Decorator to register a tool function which takes [`RunContext`][pydantic_ai.tools.RunContext] as its first argument.
|
|
1026
1009
|
|
|
@@ -1065,8 +1048,10 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1065
1048
|
schema_generator: The JSON schema generator class to use for this tool. Defaults to `GenerateToolJsonSchema`.
|
|
1066
1049
|
strict: Whether to enforce JSON schema compliance (only affects OpenAI).
|
|
1067
1050
|
See [`ToolDefinition`][pydantic_ai.tools.ToolDefinition] for more info.
|
|
1051
|
+
sequential: Whether the function requires a sequential/serial execution environment. Defaults to False.
|
|
1068
1052
|
requires_approval: Whether this tool requires human-in-the-loop approval. Defaults to False.
|
|
1069
1053
|
See the [tools documentation](../deferred-tools.md#human-in-the-loop-tool-approval) for more info.
|
|
1054
|
+
metadata: Optional metadata for the tool. This is not sent to the model but can be used for filtering and tool behavior customization.
|
|
1070
1055
|
"""
|
|
1071
1056
|
|
|
1072
1057
|
def tool_decorator(
|
|
@@ -1075,15 +1060,17 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1075
1060
|
# noinspection PyTypeChecker
|
|
1076
1061
|
self._function_toolset.add_function(
|
|
1077
1062
|
func_,
|
|
1078
|
-
True,
|
|
1079
|
-
name,
|
|
1080
|
-
retries,
|
|
1081
|
-
prepare,
|
|
1082
|
-
docstring_format,
|
|
1083
|
-
require_parameter_descriptions,
|
|
1084
|
-
schema_generator,
|
|
1085
|
-
strict,
|
|
1086
|
-
|
|
1063
|
+
takes_ctx=True,
|
|
1064
|
+
name=name,
|
|
1065
|
+
retries=retries,
|
|
1066
|
+
prepare=prepare,
|
|
1067
|
+
docstring_format=docstring_format,
|
|
1068
|
+
require_parameter_descriptions=require_parameter_descriptions,
|
|
1069
|
+
schema_generator=schema_generator,
|
|
1070
|
+
strict=strict,
|
|
1071
|
+
sequential=sequential,
|
|
1072
|
+
requires_approval=requires_approval,
|
|
1073
|
+
metadata=metadata,
|
|
1087
1074
|
)
|
|
1088
1075
|
return func_
|
|
1089
1076
|
|
|
@@ -1104,7 +1091,9 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1104
1091
|
require_parameter_descriptions: bool = False,
|
|
1105
1092
|
schema_generator: type[GenerateJsonSchema] = GenerateToolJsonSchema,
|
|
1106
1093
|
strict: bool | None = None,
|
|
1094
|
+
sequential: bool = False,
|
|
1107
1095
|
requires_approval: bool = False,
|
|
1096
|
+
metadata: dict[str, Any] | None = None,
|
|
1108
1097
|
) -> Callable[[ToolFuncPlain[ToolParams]], ToolFuncPlain[ToolParams]]: ...
|
|
1109
1098
|
|
|
1110
1099
|
def tool_plain(
|
|
@@ -1121,6 +1110,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1121
1110
|
strict: bool | None = None,
|
|
1122
1111
|
sequential: bool = False,
|
|
1123
1112
|
requires_approval: bool = False,
|
|
1113
|
+
metadata: dict[str, Any] | None = None,
|
|
1124
1114
|
) -> Any:
|
|
1125
1115
|
"""Decorator to register a tool function which DOES NOT take `RunContext` as an argument.
|
|
1126
1116
|
|
|
@@ -1168,22 +1158,24 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1168
1158
|
sequential: Whether the function requires a sequential/serial execution environment. Defaults to False.
|
|
1169
1159
|
requires_approval: Whether this tool requires human-in-the-loop approval. Defaults to False.
|
|
1170
1160
|
See the [tools documentation](../deferred-tools.md#human-in-the-loop-tool-approval) for more info.
|
|
1161
|
+
metadata: Optional metadata for the tool. This is not sent to the model but can be used for filtering and tool behavior customization.
|
|
1171
1162
|
"""
|
|
1172
1163
|
|
|
1173
1164
|
def tool_decorator(func_: ToolFuncPlain[ToolParams]) -> ToolFuncPlain[ToolParams]:
|
|
1174
1165
|
# noinspection PyTypeChecker
|
|
1175
1166
|
self._function_toolset.add_function(
|
|
1176
1167
|
func_,
|
|
1177
|
-
False,
|
|
1178
|
-
name,
|
|
1179
|
-
retries,
|
|
1180
|
-
prepare,
|
|
1181
|
-
docstring_format,
|
|
1182
|
-
require_parameter_descriptions,
|
|
1183
|
-
schema_generator,
|
|
1184
|
-
strict,
|
|
1185
|
-
sequential,
|
|
1186
|
-
requires_approval,
|
|
1168
|
+
takes_ctx=False,
|
|
1169
|
+
name=name,
|
|
1170
|
+
retries=retries,
|
|
1171
|
+
prepare=prepare,
|
|
1172
|
+
docstring_format=docstring_format,
|
|
1173
|
+
require_parameter_descriptions=require_parameter_descriptions,
|
|
1174
|
+
schema_generator=schema_generator,
|
|
1175
|
+
strict=strict,
|
|
1176
|
+
sequential=sequential,
|
|
1177
|
+
requires_approval=requires_approval,
|
|
1178
|
+
metadata=metadata,
|
|
1187
1179
|
)
|
|
1188
1180
|
return func_
|
|
1189
1181
|
|
pydantic_ai/agent/abstract.py
CHANGED
|
@@ -499,12 +499,13 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
|
|
|
499
499
|
]
|
|
500
500
|
|
|
501
501
|
parts: list[_messages.ModelRequestPart] = []
|
|
502
|
-
async for _event in _agent_graph.
|
|
503
|
-
graph_ctx.deps.tool_manager,
|
|
504
|
-
tool_calls,
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
502
|
+
async for _event in _agent_graph.process_tool_calls(
|
|
503
|
+
tool_manager=graph_ctx.deps.tool_manager,
|
|
504
|
+
tool_calls=tool_calls,
|
|
505
|
+
tool_call_results=None,
|
|
506
|
+
final_result=final_result,
|
|
507
|
+
ctx=graph_ctx,
|
|
508
|
+
output_parts=parts,
|
|
508
509
|
):
|
|
509
510
|
pass
|
|
510
511
|
if parts:
|
|
@@ -621,7 +622,6 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
|
|
|
621
622
|
[
|
|
622
623
|
UserPromptNode(
|
|
623
624
|
user_prompt='What is the capital of France?',
|
|
624
|
-
instructions=None,
|
|
625
625
|
instructions_functions=[],
|
|
626
626
|
system_prompts=(),
|
|
627
627
|
system_prompt_functions=[],
|
pydantic_ai/agent/wrapper.py
CHANGED
|
@@ -15,7 +15,6 @@ from pydantic_ai import (
|
|
|
15
15
|
)
|
|
16
16
|
from pydantic_ai.agent import AbstractAgent, AgentRun, AgentRunResult, EventStreamHandler, RunOutputDataT, WrapperAgent
|
|
17
17
|
from pydantic_ai.exceptions import UserError
|
|
18
|
-
from pydantic_ai.mcp import MCPServer
|
|
19
18
|
from pydantic_ai.models import Model
|
|
20
19
|
from pydantic_ai.output import OutputDataT, OutputSpec
|
|
21
20
|
from pydantic_ai.result import StreamedRunResult
|
|
@@ -29,7 +28,6 @@ from pydantic_ai.tools import (
|
|
|
29
28
|
)
|
|
30
29
|
from pydantic_ai.toolsets import AbstractToolset
|
|
31
30
|
|
|
32
|
-
from ._mcp_server import DBOSMCPServer
|
|
33
31
|
from ._model import DBOSModel
|
|
34
32
|
from ._utils import StepConfig
|
|
35
33
|
|
|
@@ -86,14 +84,21 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
|
|
|
86
84
|
|
|
87
85
|
def dbosify_toolset(toolset: AbstractToolset[AgentDepsT]) -> AbstractToolset[AgentDepsT]:
|
|
88
86
|
# Replace MCPServer with DBOSMCPServer
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
try:
|
|
88
|
+
from pydantic_ai.mcp import MCPServer
|
|
89
|
+
|
|
90
|
+
from ._mcp_server import DBOSMCPServer
|
|
91
|
+
except ImportError:
|
|
92
|
+
pass
|
|
95
93
|
else:
|
|
96
|
-
|
|
94
|
+
if isinstance(toolset, MCPServer):
|
|
95
|
+
return DBOSMCPServer(
|
|
96
|
+
wrapped=toolset,
|
|
97
|
+
step_name_prefix=dbosagent_name,
|
|
98
|
+
step_config=self._mcp_step_config,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return toolset
|
|
97
102
|
|
|
98
103
|
dbos_toolsets = [toolset.visit_and_replace(dbosify_toolset) for toolset in wrapped.toolsets]
|
|
99
104
|
self._toolsets = dbos_toolsets
|
|
@@ -622,7 +627,6 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
|
|
|
622
627
|
[
|
|
623
628
|
UserPromptNode(
|
|
624
629
|
user_prompt='What is the capital of France?',
|
|
625
|
-
instructions=None,
|
|
626
630
|
instructions_functions=[],
|
|
627
631
|
system_prompts=(),
|
|
628
632
|
system_prompt_functions=[],
|
|
@@ -2,18 +2,20 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from abc import ABC
|
|
4
4
|
from collections.abc import Callable
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
6
|
|
|
7
7
|
from dbos import DBOS
|
|
8
8
|
from typing_extensions import Self
|
|
9
9
|
|
|
10
|
-
from pydantic_ai.mcp import MCPServer, ToolResult
|
|
11
10
|
from pydantic_ai.tools import AgentDepsT, RunContext
|
|
12
11
|
from pydantic_ai.toolsets.abstract import AbstractToolset, ToolsetTool
|
|
13
12
|
from pydantic_ai.toolsets.wrapper import WrapperToolset
|
|
14
13
|
|
|
15
14
|
from ._utils import StepConfig
|
|
16
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from pydantic_ai.mcp import MCPServer, ToolResult
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
class DBOSMCPServer(WrapperToolset[AgentDepsT], ABC):
|
|
19
21
|
"""A wrapper for MCPServer that integrates with DBOS, turning call_tool and get_tools to DBOS steps."""
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from collections.abc import Callable
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
4
5
|
|
|
5
|
-
from logfire import Logfire
|
|
6
|
-
from opentelemetry.trace import get_tracer
|
|
7
6
|
from temporalio.client import ClientConfig, Plugin as ClientPlugin
|
|
8
|
-
from temporalio.contrib.opentelemetry import TracingInterceptor
|
|
9
7
|
from temporalio.runtime import OpenTelemetryConfig, Runtime, TelemetryConfig
|
|
10
8
|
from temporalio.service import ConnectConfig, ServiceClient
|
|
11
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from logfire import Logfire
|
|
12
|
+
|
|
12
13
|
|
|
13
14
|
def _default_setup_logfire() -> Logfire:
|
|
14
15
|
import logfire
|
|
@@ -22,6 +23,14 @@ class LogfirePlugin(ClientPlugin):
|
|
|
22
23
|
"""Temporal client plugin for Logfire."""
|
|
23
24
|
|
|
24
25
|
def __init__(self, setup_logfire: Callable[[], Logfire] = _default_setup_logfire, *, metrics: bool = True):
|
|
26
|
+
try:
|
|
27
|
+
import logfire # noqa: F401 # pyright: ignore[reportUnusedImport]
|
|
28
|
+
except ImportError as _import_error:
|
|
29
|
+
raise ImportError(
|
|
30
|
+
'Please install the `logfire` package to use the Logfire plugin, '
|
|
31
|
+
'you can use the `logfire` optional group — `pip install "pydantic-ai-slim[logfire]"`'
|
|
32
|
+
) from _import_error
|
|
33
|
+
|
|
25
34
|
self.setup_logfire = setup_logfire
|
|
26
35
|
self.metrics = metrics
|
|
27
36
|
|
|
@@ -29,6 +38,9 @@ class LogfirePlugin(ClientPlugin):
|
|
|
29
38
|
self.next_client_plugin = next
|
|
30
39
|
|
|
31
40
|
def configure_client(self, config: ClientConfig) -> ClientConfig:
|
|
41
|
+
from opentelemetry.trace import get_tracer
|
|
42
|
+
from temporalio.contrib.opentelemetry import TracingInterceptor
|
|
43
|
+
|
|
32
44
|
interceptors = config.get('interceptors', [])
|
|
33
45
|
config['interceptors'] = [*interceptors, TracingInterceptor(get_tracer('temporalio'))]
|
|
34
46
|
return self.next_client_plugin.configure_client(config)
|
|
@@ -6,7 +6,6 @@ from typing import Any, Literal
|
|
|
6
6
|
|
|
7
7
|
from temporalio.workflow import ActivityConfig
|
|
8
8
|
|
|
9
|
-
from pydantic_ai.mcp import MCPServer
|
|
10
9
|
from pydantic_ai.tools import AgentDepsT
|
|
11
10
|
from pydantic_ai.toolsets.abstract import AbstractToolset
|
|
12
11
|
from pydantic_ai.toolsets.function import FunctionToolset
|
|
@@ -63,16 +62,22 @@ def temporalize_toolset(
|
|
|
63
62
|
deps_type=deps_type,
|
|
64
63
|
run_context_type=run_context_type,
|
|
65
64
|
)
|
|
66
|
-
elif isinstance(toolset, MCPServer):
|
|
67
|
-
from ._mcp_server import TemporalMCPServer
|
|
68
65
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
run_context_type=run_context_type,
|
|
76
|
-
)
|
|
66
|
+
try:
|
|
67
|
+
from pydantic_ai.mcp import MCPServer
|
|
68
|
+
|
|
69
|
+
from ._mcp_server import TemporalMCPServer
|
|
70
|
+
except ImportError:
|
|
71
|
+
pass
|
|
77
72
|
else:
|
|
78
|
-
|
|
73
|
+
if isinstance(toolset, MCPServer):
|
|
74
|
+
return TemporalMCPServer(
|
|
75
|
+
toolset,
|
|
76
|
+
activity_name_prefix=activity_name_prefix,
|
|
77
|
+
activity_config=activity_config,
|
|
78
|
+
tool_activity_config=tool_activity_config,
|
|
79
|
+
deps_type=deps_type,
|
|
80
|
+
run_context_type=run_context_type,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return toolset
|
pydantic_ai/mcp.py
CHANGED
|
@@ -256,6 +256,11 @@ class MCPServer(AbstractToolset[Any], ABC):
|
|
|
256
256
|
name=name,
|
|
257
257
|
description=mcp_tool.description,
|
|
258
258
|
parameters_json_schema=mcp_tool.inputSchema,
|
|
259
|
+
metadata={
|
|
260
|
+
'meta': mcp_tool.meta,
|
|
261
|
+
'annotations': mcp_tool.annotations.model_dump() if mcp_tool.annotations else None,
|
|
262
|
+
'output_schema': mcp_tool.outputSchema or None,
|
|
263
|
+
},
|
|
259
264
|
),
|
|
260
265
|
)
|
|
261
266
|
for mcp_tool in await self.list_tools()
|
pydantic_ai/run.py
CHANGED
|
@@ -48,7 +48,6 @@ class AgentRun(Generic[AgentDepsT, OutputDataT]):
|
|
|
48
48
|
[
|
|
49
49
|
UserPromptNode(
|
|
50
50
|
user_prompt='What is the capital of France?',
|
|
51
|
-
instructions=None,
|
|
52
51
|
instructions_functions=[],
|
|
53
52
|
system_prompts=(),
|
|
54
53
|
system_prompt_functions=[],
|
|
@@ -183,7 +182,6 @@ class AgentRun(Generic[AgentDepsT, OutputDataT]):
|
|
|
183
182
|
[
|
|
184
183
|
UserPromptNode(
|
|
185
184
|
user_prompt='What is the capital of France?',
|
|
186
|
-
instructions=None,
|
|
187
185
|
instructions_functions=[],
|
|
188
186
|
system_prompts=(),
|
|
189
187
|
system_prompt_functions=[],
|
pydantic_ai/tools.py
CHANGED
|
@@ -255,6 +255,7 @@ class Tool(Generic[AgentDepsT]):
|
|
|
255
255
|
strict: bool | None
|
|
256
256
|
sequential: bool
|
|
257
257
|
requires_approval: bool
|
|
258
|
+
metadata: dict[str, Any] | None
|
|
258
259
|
function_schema: _function_schema.FunctionSchema
|
|
259
260
|
"""
|
|
260
261
|
The base JSON schema for the tool's parameters.
|
|
@@ -277,6 +278,7 @@ class Tool(Generic[AgentDepsT]):
|
|
|
277
278
|
strict: bool | None = None,
|
|
278
279
|
sequential: bool = False,
|
|
279
280
|
requires_approval: bool = False,
|
|
281
|
+
metadata: dict[str, Any] | None = None,
|
|
280
282
|
function_schema: _function_schema.FunctionSchema | None = None,
|
|
281
283
|
):
|
|
282
284
|
"""Create a new tool instance.
|
|
@@ -332,6 +334,7 @@ class Tool(Generic[AgentDepsT]):
|
|
|
332
334
|
sequential: Whether the function requires a sequential/serial execution environment. Defaults to False.
|
|
333
335
|
requires_approval: Whether this tool requires human-in-the-loop approval. Defaults to False.
|
|
334
336
|
See the [tools documentation](../deferred-tools.md#human-in-the-loop-tool-approval) for more info.
|
|
337
|
+
metadata: Optional metadata for the tool. This is not sent to the model but can be used for filtering and tool behavior customization.
|
|
335
338
|
function_schema: The function schema to use for the tool. If not provided, it will be generated.
|
|
336
339
|
"""
|
|
337
340
|
self.function = function
|
|
@@ -352,6 +355,7 @@ class Tool(Generic[AgentDepsT]):
|
|
|
352
355
|
self.strict = strict
|
|
353
356
|
self.sequential = sequential
|
|
354
357
|
self.requires_approval = requires_approval
|
|
358
|
+
self.metadata = metadata
|
|
355
359
|
|
|
356
360
|
@classmethod
|
|
357
361
|
def from_schema(
|
|
@@ -406,6 +410,7 @@ class Tool(Generic[AgentDepsT]):
|
|
|
406
410
|
parameters_json_schema=self.function_schema.json_schema,
|
|
407
411
|
strict=self.strict,
|
|
408
412
|
sequential=self.sequential,
|
|
413
|
+
metadata=self.metadata,
|
|
409
414
|
)
|
|
410
415
|
|
|
411
416
|
async def prepare_tool_def(self, ctx: RunContext[AgentDepsT]) -> ToolDefinition | None:
|
|
@@ -488,6 +493,12 @@ class ToolDefinition:
|
|
|
488
493
|
See the [tools documentation](../deferred-tools.md#human-in-the-loop-tool-approval) for more info.
|
|
489
494
|
"""
|
|
490
495
|
|
|
496
|
+
metadata: dict[str, Any] | None = None
|
|
497
|
+
"""Tool metadata that can be set by the toolset this tool came from. It is not sent to the model, but can be used for filtering and tool behavior customization.
|
|
498
|
+
|
|
499
|
+
For MCP tools, this contains the `meta`, `annotations`, and `output_schema` fields from the tool definition.
|
|
500
|
+
"""
|
|
501
|
+
|
|
491
502
|
@property
|
|
492
503
|
def defer(self) -> bool:
|
|
493
504
|
"""Whether calls to this tool will be deferred.
|
pydantic_ai/toolsets/function.py
CHANGED
|
@@ -45,18 +45,21 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
45
45
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] = [],
|
|
46
46
|
*,
|
|
47
47
|
max_retries: int = 1,
|
|
48
|
-
id: str | None = None,
|
|
49
48
|
docstring_format: DocstringFormat = 'auto',
|
|
50
49
|
require_parameter_descriptions: bool = False,
|
|
51
50
|
schema_generator: type[GenerateJsonSchema] = GenerateToolJsonSchema,
|
|
51
|
+
strict: bool | None = None,
|
|
52
|
+
sequential: bool = False,
|
|
53
|
+
requires_approval: bool = False,
|
|
54
|
+
metadata: dict[str, Any] | None = None,
|
|
55
|
+
id: str | None = None,
|
|
52
56
|
):
|
|
53
57
|
"""Build a new function toolset.
|
|
54
58
|
|
|
55
59
|
Args:
|
|
56
60
|
tools: The tools to add to the toolset.
|
|
57
61
|
max_retries: The maximum number of retries for each tool during a run.
|
|
58
|
-
|
|
59
|
-
in which case the ID will be used to identify the toolset's activities within the workflow.
|
|
62
|
+
Applies to all tools, unless overridden when adding a tool.
|
|
60
63
|
docstring_format: Format of tool docstring, see [`DocstringFormat`][pydantic_ai.tools.DocstringFormat].
|
|
61
64
|
Defaults to `'auto'`, such that the format is inferred from the structure of the docstring.
|
|
62
65
|
Applies to all tools, unless overridden when adding a tool.
|
|
@@ -64,12 +67,27 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
64
67
|
Applies to all tools, unless overridden when adding a tool.
|
|
65
68
|
schema_generator: The JSON schema generator class to use for this tool. Defaults to `GenerateToolJsonSchema`.
|
|
66
69
|
Applies to all tools, unless overridden when adding a tool.
|
|
70
|
+
strict: Whether to enforce JSON schema compliance (only affects OpenAI).
|
|
71
|
+
See [`ToolDefinition`][pydantic_ai.tools.ToolDefinition] for more info.
|
|
72
|
+
sequential: Whether the function requires a sequential/serial execution environment. Defaults to False.
|
|
73
|
+
Applies to all tools, unless overridden when adding a tool.
|
|
74
|
+
requires_approval: Whether this tool requires human-in-the-loop approval. Defaults to False.
|
|
75
|
+
See the [tools documentation](../deferred-tools.md#human-in-the-loop-tool-approval) for more info.
|
|
76
|
+
Applies to all tools, unless overridden when adding a tool.
|
|
77
|
+
metadata: Optional metadata for the tool. This is not sent to the model but can be used for filtering and tool behavior customization.
|
|
78
|
+
Applies to all tools, unless overridden when adding a tool, which will be merged with the toolset's metadata.
|
|
79
|
+
id: An optional unique ID for the toolset. A toolset needs to have an ID in order to be used in a durable execution environment like Temporal,
|
|
80
|
+
in which case the ID will be used to identify the toolset's activities within the workflow.
|
|
67
81
|
"""
|
|
68
82
|
self.max_retries = max_retries
|
|
69
83
|
self._id = id
|
|
70
84
|
self.docstring_format = docstring_format
|
|
71
85
|
self.require_parameter_descriptions = require_parameter_descriptions
|
|
72
86
|
self.schema_generator = schema_generator
|
|
87
|
+
self.strict = strict
|
|
88
|
+
self.sequential = sequential
|
|
89
|
+
self.requires_approval = requires_approval
|
|
90
|
+
self.metadata = metadata
|
|
73
91
|
|
|
74
92
|
self.tools = {}
|
|
75
93
|
for tool in tools:
|
|
@@ -97,8 +115,9 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
97
115
|
require_parameter_descriptions: bool | None = None,
|
|
98
116
|
schema_generator: type[GenerateJsonSchema] | None = None,
|
|
99
117
|
strict: bool | None = None,
|
|
100
|
-
sequential: bool =
|
|
101
|
-
requires_approval: bool =
|
|
118
|
+
sequential: bool | None = None,
|
|
119
|
+
requires_approval: bool | None = None,
|
|
120
|
+
metadata: dict[str, Any] | None = None,
|
|
102
121
|
) -> Callable[[ToolFuncEither[AgentDepsT, ToolParams]], ToolFuncEither[AgentDepsT, ToolParams]]: ...
|
|
103
122
|
|
|
104
123
|
def tool(
|
|
@@ -113,8 +132,9 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
113
132
|
require_parameter_descriptions: bool | None = None,
|
|
114
133
|
schema_generator: type[GenerateJsonSchema] | None = None,
|
|
115
134
|
strict: bool | None = None,
|
|
116
|
-
sequential: bool =
|
|
117
|
-
requires_approval: bool =
|
|
135
|
+
sequential: bool | None = None,
|
|
136
|
+
requires_approval: bool | None = None,
|
|
137
|
+
metadata: dict[str, Any] | None = None,
|
|
118
138
|
) -> Any:
|
|
119
139
|
"""Decorator to register a tool function which takes [`RunContext`][pydantic_ai.tools.RunContext] as its first argument.
|
|
120
140
|
|
|
@@ -163,9 +183,14 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
163
183
|
If `None`, the default value is determined by the toolset.
|
|
164
184
|
strict: Whether to enforce JSON schema compliance (only affects OpenAI).
|
|
165
185
|
See [`ToolDefinition`][pydantic_ai.tools.ToolDefinition] for more info.
|
|
186
|
+
If `None`, the default value is determined by the toolset.
|
|
166
187
|
sequential: Whether the function requires a sequential/serial execution environment. Defaults to False.
|
|
188
|
+
If `None`, the default value is determined by the toolset.
|
|
167
189
|
requires_approval: Whether this tool requires human-in-the-loop approval. Defaults to False.
|
|
168
190
|
See the [tools documentation](../deferred-tools.md#human-in-the-loop-tool-approval) for more info.
|
|
191
|
+
If `None`, the default value is determined by the toolset.
|
|
192
|
+
metadata: Optional metadata for the tool. This is not sent to the model but can be used for filtering and tool behavior customization.
|
|
193
|
+
If `None`, the default value is determined by the toolset. If provided, it will be merged with the toolset's metadata.
|
|
169
194
|
"""
|
|
170
195
|
|
|
171
196
|
def tool_decorator(
|
|
@@ -184,6 +209,7 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
184
209
|
strict,
|
|
185
210
|
sequential,
|
|
186
211
|
requires_approval,
|
|
212
|
+
metadata,
|
|
187
213
|
)
|
|
188
214
|
return func_
|
|
189
215
|
|
|
@@ -200,8 +226,9 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
200
226
|
require_parameter_descriptions: bool | None = None,
|
|
201
227
|
schema_generator: type[GenerateJsonSchema] | None = None,
|
|
202
228
|
strict: bool | None = None,
|
|
203
|
-
sequential: bool =
|
|
204
|
-
requires_approval: bool =
|
|
229
|
+
sequential: bool | None = None,
|
|
230
|
+
requires_approval: bool | None = None,
|
|
231
|
+
metadata: dict[str, Any] | None = None,
|
|
205
232
|
) -> None:
|
|
206
233
|
"""Add a function as a tool to the toolset.
|
|
207
234
|
|
|
@@ -227,9 +254,14 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
227
254
|
If `None`, the default value is determined by the toolset.
|
|
228
255
|
strict: Whether to enforce JSON schema compliance (only affects OpenAI).
|
|
229
256
|
See [`ToolDefinition`][pydantic_ai.tools.ToolDefinition] for more info.
|
|
257
|
+
If `None`, the default value is determined by the toolset.
|
|
230
258
|
sequential: Whether the function requires a sequential/serial execution environment. Defaults to False.
|
|
259
|
+
If `None`, the default value is determined by the toolset.
|
|
231
260
|
requires_approval: Whether this tool requires human-in-the-loop approval. Defaults to False.
|
|
232
261
|
See the [tools documentation](../deferred-tools.md#human-in-the-loop-tool-approval) for more info.
|
|
262
|
+
If `None`, the default value is determined by the toolset.
|
|
263
|
+
metadata: Optional metadata for the tool. This is not sent to the model but can be used for filtering and tool behavior customization.
|
|
264
|
+
If `None`, the default value is determined by the toolset. If provided, it will be merged with the toolset's metadata.
|
|
233
265
|
"""
|
|
234
266
|
if docstring_format is None:
|
|
235
267
|
docstring_format = self.docstring_format
|
|
@@ -237,6 +269,12 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
237
269
|
require_parameter_descriptions = self.require_parameter_descriptions
|
|
238
270
|
if schema_generator is None:
|
|
239
271
|
schema_generator = self.schema_generator
|
|
272
|
+
if strict is None:
|
|
273
|
+
strict = self.strict
|
|
274
|
+
if sequential is None:
|
|
275
|
+
sequential = self.sequential
|
|
276
|
+
if requires_approval is None:
|
|
277
|
+
requires_approval = self.requires_approval
|
|
240
278
|
|
|
241
279
|
tool = Tool[AgentDepsT](
|
|
242
280
|
func,
|
|
@@ -250,6 +288,7 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
250
288
|
strict=strict,
|
|
251
289
|
sequential=sequential,
|
|
252
290
|
requires_approval=requires_approval,
|
|
291
|
+
metadata=metadata,
|
|
253
292
|
)
|
|
254
293
|
self.add_tool(tool)
|
|
255
294
|
|
|
@@ -263,6 +302,8 @@ class FunctionToolset(AbstractToolset[AgentDepsT]):
|
|
|
263
302
|
raise UserError(f'Tool name conflicts with existing tool: {tool.name!r}')
|
|
264
303
|
if tool.max_retries is None:
|
|
265
304
|
tool.max_retries = self.max_retries
|
|
305
|
+
if self.metadata is not None:
|
|
306
|
+
tool.metadata = self.metadata | (tool.metadata or {})
|
|
266
307
|
self.tools[tool.name] = tool
|
|
267
308
|
|
|
268
309
|
async def get_tools(self, ctx: RunContext[AgentDepsT]) -> dict[str, ToolsetTool[AgentDepsT]]:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pydantic-ai-slim
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.7
|
|
4
4
|
Summary: Agent Framework / shim to use Pydantic with LLMs, slim package
|
|
5
5
|
Project-URL: Homepage, https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim
|
|
6
6
|
Project-URL: Source, https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim
|
|
@@ -33,7 +33,7 @@ Requires-Dist: genai-prices>=0.0.23
|
|
|
33
33
|
Requires-Dist: griffe>=1.3.2
|
|
34
34
|
Requires-Dist: httpx>=0.27
|
|
35
35
|
Requires-Dist: opentelemetry-api>=1.28.0
|
|
36
|
-
Requires-Dist: pydantic-graph==1.0.
|
|
36
|
+
Requires-Dist: pydantic-graph==1.0.7
|
|
37
37
|
Requires-Dist: pydantic>=2.10
|
|
38
38
|
Requires-Dist: typing-inspection>=0.4.0
|
|
39
39
|
Provides-Extra: a2a
|
|
@@ -57,7 +57,7 @@ Requires-Dist: dbos>=1.13.0; extra == 'dbos'
|
|
|
57
57
|
Provides-Extra: duckduckgo
|
|
58
58
|
Requires-Dist: ddgs>=9.0.0; extra == 'duckduckgo'
|
|
59
59
|
Provides-Extra: evals
|
|
60
|
-
Requires-Dist: pydantic-evals==1.0.
|
|
60
|
+
Requires-Dist: pydantic-evals==1.0.7; extra == 'evals'
|
|
61
61
|
Provides-Extra: google
|
|
62
62
|
Requires-Dist: google-genai>=1.31.0; extra == 'google'
|
|
63
63
|
Provides-Extra: groq
|