pydantic-ai-slim 1.0.11__py3-none-any.whl → 1.0.13__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/__init__.py +134 -4
- pydantic_ai/_a2a.py +1 -1
- pydantic_ai/_agent_graph.py +4 -0
- pydantic_ai/_instrumentation.py +95 -0
- pydantic_ai/{profiles/_json_schema.py → _json_schema.py} +5 -3
- pydantic_ai/_output.py +26 -12
- pydantic_ai/_run_context.py +4 -0
- pydantic_ai/_thinking_part.py +1 -1
- pydantic_ai/_tool_manager.py +15 -7
- pydantic_ai/_utils.py +24 -7
- pydantic_ai/agent/__init__.py +68 -36
- pydantic_ai/agent/abstract.py +12 -1
- pydantic_ai/agent/wrapper.py +11 -3
- pydantic_ai/builtin_tools.py +20 -1
- pydantic_ai/common_tools/duckduckgo.py +2 -2
- pydantic_ai/common_tools/tavily.py +2 -2
- pydantic_ai/direct.py +6 -6
- pydantic_ai/durable_exec/dbos/_agent.py +12 -3
- pydantic_ai/durable_exec/dbos/_mcp_server.py +1 -2
- pydantic_ai/durable_exec/dbos/_model.py +2 -2
- pydantic_ai/durable_exec/temporal/_agent.py +13 -4
- pydantic_ai/durable_exec/temporal/_function_toolset.py +1 -1
- pydantic_ai/durable_exec/temporal/_mcp_server.py +1 -1
- pydantic_ai/durable_exec/temporal/_model.py +3 -3
- pydantic_ai/durable_exec/temporal/_toolset.py +1 -3
- pydantic_ai/ext/aci.py +1 -1
- pydantic_ai/ext/langchain.py +1 -1
- pydantic_ai/mcp.py +32 -8
- pydantic_ai/messages.py +14 -11
- pydantic_ai/models/__init__.py +19 -2
- pydantic_ai/models/anthropic.py +29 -14
- pydantic_ai/models/bedrock.py +14 -5
- pydantic_ai/models/cohere.py +4 -0
- pydantic_ai/models/fallback.py +2 -9
- pydantic_ai/models/function.py +8 -0
- pydantic_ai/models/gemini.py +8 -0
- pydantic_ai/models/google.py +14 -2
- pydantic_ai/models/groq.py +8 -0
- pydantic_ai/models/huggingface.py +8 -2
- pydantic_ai/models/instrumented.py +16 -6
- pydantic_ai/models/mcp_sampling.py +2 -0
- pydantic_ai/models/mistral.py +8 -0
- pydantic_ai/models/openai.py +95 -29
- pydantic_ai/models/test.py +8 -0
- pydantic_ai/models/wrapper.py +7 -0
- pydantic_ai/output.py +11 -1
- pydantic_ai/profiles/__init__.py +1 -1
- pydantic_ai/profiles/google.py +1 -1
- pydantic_ai/profiles/openai.py +1 -1
- pydantic_ai/providers/__init__.py +1 -1
- pydantic_ai/providers/anthropic.py +1 -1
- pydantic_ai/providers/azure.py +1 -1
- pydantic_ai/providers/bedrock.py +1 -1
- pydantic_ai/providers/cerebras.py +1 -1
- pydantic_ai/providers/cohere.py +1 -1
- pydantic_ai/providers/deepseek.py +1 -1
- pydantic_ai/providers/fireworks.py +1 -1
- pydantic_ai/providers/github.py +1 -1
- pydantic_ai/providers/google.py +1 -1
- pydantic_ai/providers/google_gla.py +1 -1
- pydantic_ai/providers/google_vertex.py +1 -1
- pydantic_ai/providers/grok.py +1 -1
- pydantic_ai/providers/groq.py +1 -1
- pydantic_ai/providers/heroku.py +1 -1
- pydantic_ai/providers/huggingface.py +1 -1
- pydantic_ai/providers/litellm.py +1 -1
- pydantic_ai/providers/mistral.py +1 -1
- pydantic_ai/providers/moonshotai.py +1 -1
- pydantic_ai/providers/ollama.py +1 -1
- pydantic_ai/providers/openai.py +1 -1
- pydantic_ai/providers/openrouter.py +1 -1
- pydantic_ai/providers/together.py +1 -1
- pydantic_ai/providers/vercel.py +1 -1
- pydantic_ai/toolsets/function.py +1 -2
- {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.13.dist-info}/METADATA +3 -3
- pydantic_ai_slim-1.0.13.dist-info/RECORD +128 -0
- pydantic_ai_slim-1.0.11.dist-info/RECORD +0 -127
- {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.13.dist-info}/WHEEL +0 -0
- {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.13.dist-info}/entry_points.txt +0 -0
- {pydantic_ai_slim-1.0.11.dist-info → pydantic_ai_slim-1.0.13.dist-info}/licenses/LICENSE +0 -0
pydantic_ai/agent/__init__.py
CHANGED
|
@@ -14,6 +14,7 @@ from opentelemetry.trace import NoOpTracer, use_span
|
|
|
14
14
|
from pydantic.json_schema import GenerateJsonSchema
|
|
15
15
|
from typing_extensions import Self, TypeVar, deprecated
|
|
16
16
|
|
|
17
|
+
from pydantic_ai._instrumentation import DEFAULT_INSTRUMENTATION_VERSION, InstrumentationNames
|
|
17
18
|
from pydantic_graph import Graph
|
|
18
19
|
|
|
19
20
|
from .. import (
|
|
@@ -65,7 +66,7 @@ from ..toolsets._dynamic import (
|
|
|
65
66
|
from ..toolsets.combined import CombinedToolset
|
|
66
67
|
from ..toolsets.function import FunctionToolset
|
|
67
68
|
from ..toolsets.prepared import PreparedToolset
|
|
68
|
-
from .abstract import AbstractAgent, EventStreamHandler, RunOutputDataT
|
|
69
|
+
from .abstract import AbstractAgent, EventStreamHandler, Instructions, RunOutputDataT
|
|
69
70
|
from .wrapper import WrapperAgent
|
|
70
71
|
|
|
71
72
|
if TYPE_CHECKING:
|
|
@@ -136,8 +137,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
136
137
|
_deps_type: type[AgentDepsT] = dataclasses.field(repr=False)
|
|
137
138
|
_output_schema: _output.BaseOutputSchema[OutputDataT] = dataclasses.field(repr=False)
|
|
138
139
|
_output_validators: list[_output.OutputValidator[AgentDepsT, OutputDataT]] = dataclasses.field(repr=False)
|
|
139
|
-
_instructions: str |
|
|
140
|
-
_instructions_functions: list[_system_prompt.SystemPromptRunner[AgentDepsT]] = dataclasses.field(repr=False)
|
|
140
|
+
_instructions: list[str | _system_prompt.SystemPromptFunc[AgentDepsT]] = dataclasses.field(repr=False)
|
|
141
141
|
_system_prompts: tuple[str, ...] = dataclasses.field(repr=False)
|
|
142
142
|
_system_prompt_functions: list[_system_prompt.SystemPromptRunner[AgentDepsT]] = dataclasses.field(repr=False)
|
|
143
143
|
_system_prompt_dynamic_functions: dict[str, _system_prompt.SystemPromptRunner[AgentDepsT]] = dataclasses.field(
|
|
@@ -163,10 +163,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
163
163
|
model: models.Model | models.KnownModelName | str | None = None,
|
|
164
164
|
*,
|
|
165
165
|
output_type: OutputSpec[OutputDataT] = str,
|
|
166
|
-
instructions:
|
|
167
|
-
| _system_prompt.SystemPromptFunc[AgentDepsT]
|
|
168
|
-
| Sequence[str | _system_prompt.SystemPromptFunc[AgentDepsT]]
|
|
169
|
-
| None = None,
|
|
166
|
+
instructions: Instructions[AgentDepsT] = None,
|
|
170
167
|
system_prompt: str | Sequence[str] = (),
|
|
171
168
|
deps_type: type[AgentDepsT] = NoneType,
|
|
172
169
|
name: str | None = None,
|
|
@@ -192,10 +189,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
192
189
|
model: models.Model | models.KnownModelName | str | None = None,
|
|
193
190
|
*,
|
|
194
191
|
output_type: OutputSpec[OutputDataT] = str,
|
|
195
|
-
instructions:
|
|
196
|
-
| _system_prompt.SystemPromptFunc[AgentDepsT]
|
|
197
|
-
| Sequence[str | _system_prompt.SystemPromptFunc[AgentDepsT]]
|
|
198
|
-
| None = None,
|
|
192
|
+
instructions: Instructions[AgentDepsT] = None,
|
|
199
193
|
system_prompt: str | Sequence[str] = (),
|
|
200
194
|
deps_type: type[AgentDepsT] = NoneType,
|
|
201
195
|
name: str | None = None,
|
|
@@ -219,10 +213,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
219
213
|
model: models.Model | models.KnownModelName | str | None = None,
|
|
220
214
|
*,
|
|
221
215
|
output_type: OutputSpec[OutputDataT] = str,
|
|
222
|
-
instructions:
|
|
223
|
-
| _system_prompt.SystemPromptFunc[AgentDepsT]
|
|
224
|
-
| Sequence[str | _system_prompt.SystemPromptFunc[AgentDepsT]]
|
|
225
|
-
| None = None,
|
|
216
|
+
instructions: Instructions[AgentDepsT] = None,
|
|
226
217
|
system_prompt: str | Sequence[str] = (),
|
|
227
218
|
deps_type: type[AgentDepsT] = NoneType,
|
|
228
219
|
name: str | None = None,
|
|
@@ -321,16 +312,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
321
312
|
self._output_schema = _output.OutputSchema[OutputDataT].build(output_type, default_mode=default_output_mode)
|
|
322
313
|
self._output_validators = []
|
|
323
314
|
|
|
324
|
-
self._instructions =
|
|
325
|
-
self._instructions_functions = []
|
|
326
|
-
if isinstance(instructions, str | Callable):
|
|
327
|
-
instructions = [instructions]
|
|
328
|
-
for instruction in instructions or []:
|
|
329
|
-
if isinstance(instruction, str):
|
|
330
|
-
self._instructions += instruction + '\n'
|
|
331
|
-
else:
|
|
332
|
-
self._instructions_functions.append(_system_prompt.SystemPromptRunner(instruction))
|
|
333
|
-
self._instructions = self._instructions.strip() or None
|
|
315
|
+
self._instructions = self._normalize_instructions(instructions)
|
|
334
316
|
|
|
335
317
|
self._system_prompts = (system_prompt,) if isinstance(system_prompt, str) else tuple(system_prompt)
|
|
336
318
|
self._system_prompt_functions = []
|
|
@@ -370,6 +352,9 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
370
352
|
self._override_tools: ContextVar[
|
|
371
353
|
_utils.Option[Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]]]
|
|
372
354
|
] = ContextVar('_override_tools', default=None)
|
|
355
|
+
self._override_instructions: ContextVar[
|
|
356
|
+
_utils.Option[list[str | _system_prompt.SystemPromptFunc[AgentDepsT]]]
|
|
357
|
+
] = ContextVar('_override_instructions', default=None)
|
|
373
358
|
|
|
374
359
|
self._enter_lock = Lock()
|
|
375
360
|
self._entered_count = 0
|
|
@@ -592,10 +577,12 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
592
577
|
model_settings = merge_model_settings(merged_settings, model_settings)
|
|
593
578
|
usage_limits = usage_limits or _usage.UsageLimits()
|
|
594
579
|
|
|
580
|
+
instructions_literal, instructions_functions = self._get_instructions()
|
|
581
|
+
|
|
595
582
|
async def get_instructions(run_context: RunContext[AgentDepsT]) -> str | None:
|
|
596
583
|
parts = [
|
|
597
|
-
|
|
598
|
-
*[await func.run(run_context) for func in
|
|
584
|
+
instructions_literal,
|
|
585
|
+
*[await func.run(run_context) for func in instructions_functions],
|
|
599
586
|
]
|
|
600
587
|
|
|
601
588
|
model_profile = model_used.profile
|
|
@@ -633,22 +620,28 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
633
620
|
get_instructions=get_instructions,
|
|
634
621
|
instrumentation_settings=instrumentation_settings,
|
|
635
622
|
)
|
|
623
|
+
|
|
636
624
|
start_node = _agent_graph.UserPromptNode[AgentDepsT](
|
|
637
625
|
user_prompt=user_prompt,
|
|
638
626
|
deferred_tool_results=deferred_tool_results,
|
|
639
|
-
instructions=
|
|
640
|
-
instructions_functions=
|
|
627
|
+
instructions=instructions_literal,
|
|
628
|
+
instructions_functions=instructions_functions,
|
|
641
629
|
system_prompts=self._system_prompts,
|
|
642
630
|
system_prompt_functions=self._system_prompt_functions,
|
|
643
631
|
system_prompt_dynamic_functions=self._system_prompt_dynamic_functions,
|
|
644
632
|
)
|
|
645
633
|
|
|
646
634
|
agent_name = self.name or 'agent'
|
|
635
|
+
instrumentation_names = InstrumentationNames.for_version(
|
|
636
|
+
instrumentation_settings.version if instrumentation_settings else DEFAULT_INSTRUMENTATION_VERSION
|
|
637
|
+
)
|
|
638
|
+
|
|
647
639
|
run_span = tracer.start_span(
|
|
648
|
-
|
|
640
|
+
instrumentation_names.get_agent_run_span_name(agent_name),
|
|
649
641
|
attributes={
|
|
650
642
|
'model_name': model_used.model_name if model_used else 'no-model',
|
|
651
643
|
'agent_name': agent_name,
|
|
644
|
+
'gen_ai.agent.name': agent_name,
|
|
652
645
|
'logfire.msg': f'{agent_name} run',
|
|
653
646
|
},
|
|
654
647
|
)
|
|
@@ -684,6 +677,8 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
684
677
|
def _run_span_end_attributes(
|
|
685
678
|
self, state: _agent_graph.GraphAgentState, usage: _usage.RunUsage, settings: InstrumentationSettings
|
|
686
679
|
):
|
|
680
|
+
literal_instructions, _ = self._get_instructions()
|
|
681
|
+
|
|
687
682
|
if settings.version == 1:
|
|
688
683
|
attrs = {
|
|
689
684
|
'all_messages_events': json.dumps(
|
|
@@ -696,7 +691,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
696
691
|
else:
|
|
697
692
|
attrs = {
|
|
698
693
|
'pydantic_ai.all_messages': json.dumps(settings.messages_to_otel_messages(state.message_history)),
|
|
699
|
-
**settings.system_instructions_attributes(
|
|
694
|
+
**settings.system_instructions_attributes(literal_instructions),
|
|
700
695
|
}
|
|
701
696
|
|
|
702
697
|
return {
|
|
@@ -721,8 +716,9 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
721
716
|
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
|
|
722
717
|
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
|
|
723
718
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
|
|
719
|
+
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
|
|
724
720
|
) -> Iterator[None]:
|
|
725
|
-
"""Context manager to temporarily override agent dependencies, model, toolsets, or
|
|
721
|
+
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
|
|
726
722
|
|
|
727
723
|
This is particularly useful when testing.
|
|
728
724
|
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
|
|
@@ -732,6 +728,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
732
728
|
model: The model to use instead of the model passed to the agent run.
|
|
733
729
|
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
|
|
734
730
|
tools: The tools to use instead of the tools registered with the agent.
|
|
731
|
+
instructions: The instructions to use instead of the instructions registered with the agent.
|
|
735
732
|
"""
|
|
736
733
|
if _utils.is_set(deps):
|
|
737
734
|
deps_token = self._override_deps.set(_utils.Some(deps))
|
|
@@ -753,6 +750,12 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
753
750
|
else:
|
|
754
751
|
tools_token = None
|
|
755
752
|
|
|
753
|
+
if _utils.is_set(instructions):
|
|
754
|
+
normalized_instructions = self._normalize_instructions(instructions)
|
|
755
|
+
instructions_token = self._override_instructions.set(_utils.Some(normalized_instructions))
|
|
756
|
+
else:
|
|
757
|
+
instructions_token = None
|
|
758
|
+
|
|
756
759
|
try:
|
|
757
760
|
yield
|
|
758
761
|
finally:
|
|
@@ -764,6 +767,8 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
764
767
|
self._override_toolsets.reset(toolsets_token)
|
|
765
768
|
if tools_token is not None:
|
|
766
769
|
self._override_tools.reset(tools_token)
|
|
770
|
+
if instructions_token is not None:
|
|
771
|
+
self._override_instructions.reset(instructions_token)
|
|
767
772
|
|
|
768
773
|
@overload
|
|
769
774
|
def instructions(
|
|
@@ -824,12 +829,12 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
824
829
|
def decorator(
|
|
825
830
|
func_: _system_prompt.SystemPromptFunc[AgentDepsT],
|
|
826
831
|
) -> _system_prompt.SystemPromptFunc[AgentDepsT]:
|
|
827
|
-
self.
|
|
832
|
+
self._instructions.append(func_)
|
|
828
833
|
return func_
|
|
829
834
|
|
|
830
835
|
return decorator
|
|
831
836
|
else:
|
|
832
|
-
self.
|
|
837
|
+
self._instructions.append(func)
|
|
833
838
|
return func
|
|
834
839
|
|
|
835
840
|
@overload
|
|
@@ -1206,8 +1211,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1206
1211
|
|
|
1207
1212
|
Example:
|
|
1208
1213
|
```python
|
|
1209
|
-
from pydantic_ai import Agent, RunContext
|
|
1210
|
-
from pydantic_ai.toolsets import AbstractToolset, FunctionToolset
|
|
1214
|
+
from pydantic_ai import AbstractToolset, Agent, FunctionToolset, RunContext
|
|
1211
1215
|
|
|
1212
1216
|
agent = Agent('test', deps_type=str)
|
|
1213
1217
|
|
|
@@ -1271,6 +1275,34 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
1271
1275
|
else:
|
|
1272
1276
|
return deps
|
|
1273
1277
|
|
|
1278
|
+
def _normalize_instructions(
|
|
1279
|
+
self,
|
|
1280
|
+
instructions: Instructions[AgentDepsT],
|
|
1281
|
+
) -> list[str | _system_prompt.SystemPromptFunc[AgentDepsT]]:
|
|
1282
|
+
if instructions is None:
|
|
1283
|
+
return []
|
|
1284
|
+
if isinstance(instructions, str) or callable(instructions):
|
|
1285
|
+
return [instructions]
|
|
1286
|
+
return list(instructions)
|
|
1287
|
+
|
|
1288
|
+
def _get_instructions(
|
|
1289
|
+
self,
|
|
1290
|
+
) -> tuple[str | None, list[_system_prompt.SystemPromptRunner[AgentDepsT]]]:
|
|
1291
|
+
override_instructions = self._override_instructions.get()
|
|
1292
|
+
instructions = override_instructions.value if override_instructions else self._instructions
|
|
1293
|
+
|
|
1294
|
+
literal_parts: list[str] = []
|
|
1295
|
+
functions: list[_system_prompt.SystemPromptRunner[AgentDepsT]] = []
|
|
1296
|
+
|
|
1297
|
+
for instruction in instructions:
|
|
1298
|
+
if isinstance(instruction, str):
|
|
1299
|
+
literal_parts.append(instruction)
|
|
1300
|
+
else:
|
|
1301
|
+
functions.append(_system_prompt.SystemPromptRunner[AgentDepsT](instruction))
|
|
1302
|
+
|
|
1303
|
+
literal = '\n'.join(literal_parts).strip() or None
|
|
1304
|
+
return literal, functions
|
|
1305
|
+
|
|
1274
1306
|
def _get_toolset(
|
|
1275
1307
|
self,
|
|
1276
1308
|
output_toolset: AbstractToolset[AgentDepsT] | None | _utils.Unset = _utils.UNSET,
|
pydantic_ai/agent/abstract.py
CHANGED
|
@@ -14,6 +14,7 @@ from pydantic_graph._utils import get_event_loop
|
|
|
14
14
|
|
|
15
15
|
from .. import (
|
|
16
16
|
_agent_graph,
|
|
17
|
+
_system_prompt,
|
|
17
18
|
_utils,
|
|
18
19
|
exceptions,
|
|
19
20
|
messages as _messages,
|
|
@@ -60,6 +61,14 @@ EventStreamHandler: TypeAlias = Callable[
|
|
|
60
61
|
"""A function that receives agent [`RunContext`][pydantic_ai.tools.RunContext] and an async iterable of events from the model's streaming response and the agent's execution of tools."""
|
|
61
62
|
|
|
62
63
|
|
|
64
|
+
Instructions = (
|
|
65
|
+
str
|
|
66
|
+
| _system_prompt.SystemPromptFunc[AgentDepsT]
|
|
67
|
+
| Sequence[str | _system_prompt.SystemPromptFunc[AgentDepsT]]
|
|
68
|
+
| None
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
63
72
|
class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
|
|
64
73
|
"""Abstract superclass for [`Agent`][pydantic_ai.agent.Agent], [`WrapperAgent`][pydantic_ai.agent.WrapperAgent], and your own custom agent implementations."""
|
|
65
74
|
|
|
@@ -681,8 +690,9 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
|
|
|
681
690
|
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
|
|
682
691
|
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
|
|
683
692
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
|
|
693
|
+
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
|
|
684
694
|
) -> Iterator[None]:
|
|
685
|
-
"""Context manager to temporarily override agent dependencies, model, toolsets, or
|
|
695
|
+
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
|
|
686
696
|
|
|
687
697
|
This is particularly useful when testing.
|
|
688
698
|
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
|
|
@@ -692,6 +702,7 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
|
|
|
692
702
|
model: The model to use instead of the model passed to the agent run.
|
|
693
703
|
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
|
|
694
704
|
tools: The tools to use instead of the tools registered with the agent.
|
|
705
|
+
instructions: The instructions to use instead of the instructions registered with the agent.
|
|
695
706
|
"""
|
|
696
707
|
raise NotImplementedError
|
|
697
708
|
yield
|
pydantic_ai/agent/wrapper.py
CHANGED
|
@@ -20,7 +20,7 @@ from ..tools import (
|
|
|
20
20
|
ToolFuncEither,
|
|
21
21
|
)
|
|
22
22
|
from ..toolsets import AbstractToolset
|
|
23
|
-
from .abstract import AbstractAgent, EventStreamHandler, RunOutputDataT
|
|
23
|
+
from .abstract import AbstractAgent, EventStreamHandler, Instructions, RunOutputDataT
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class WrapperAgent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
@@ -214,8 +214,9 @@ class WrapperAgent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
214
214
|
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
|
|
215
215
|
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
|
|
216
216
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
|
|
217
|
+
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
|
|
217
218
|
) -> Iterator[None]:
|
|
218
|
-
"""Context manager to temporarily override agent dependencies, model, toolsets, or
|
|
219
|
+
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
|
|
219
220
|
|
|
220
221
|
This is particularly useful when testing.
|
|
221
222
|
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
|
|
@@ -225,6 +226,13 @@ class WrapperAgent(AbstractAgent[AgentDepsT, OutputDataT]):
|
|
|
225
226
|
model: The model to use instead of the model passed to the agent run.
|
|
226
227
|
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
|
|
227
228
|
tools: The tools to use instead of the tools registered with the agent.
|
|
229
|
+
instructions: The instructions to use instead of the instructions registered with the agent.
|
|
228
230
|
"""
|
|
229
|
-
with self.wrapped.override(
|
|
231
|
+
with self.wrapped.override(
|
|
232
|
+
deps=deps,
|
|
233
|
+
model=model,
|
|
234
|
+
toolsets=toolsets,
|
|
235
|
+
tools=tools,
|
|
236
|
+
instructions=instructions,
|
|
237
|
+
):
|
|
230
238
|
yield
|
pydantic_ai/builtin_tools.py
CHANGED
|
@@ -6,7 +6,14 @@ from typing import Literal
|
|
|
6
6
|
|
|
7
7
|
from typing_extensions import TypedDict
|
|
8
8
|
|
|
9
|
-
__all__ = (
|
|
9
|
+
__all__ = (
|
|
10
|
+
'AbstractBuiltinTool',
|
|
11
|
+
'WebSearchTool',
|
|
12
|
+
'WebSearchUserLocation',
|
|
13
|
+
'CodeExecutionTool',
|
|
14
|
+
'UrlContextTool',
|
|
15
|
+
'MemoryTool',
|
|
16
|
+
)
|
|
10
17
|
|
|
11
18
|
|
|
12
19
|
@dataclass(kw_only=True)
|
|
@@ -133,3 +140,15 @@ class UrlContextTool(AbstractBuiltinTool):
|
|
|
133
140
|
|
|
134
141
|
kind: str = 'url_context'
|
|
135
142
|
"""The kind of tool."""
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class MemoryTool(AbstractBuiltinTool):
|
|
146
|
+
"""A builtin tool that allows your agent to use memory.
|
|
147
|
+
|
|
148
|
+
Supported by:
|
|
149
|
+
|
|
150
|
+
* Anthropic
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
kind: str = 'memory'
|
|
154
|
+
"""The kind of tool."""
|
|
@@ -4,7 +4,7 @@ from dataclasses import KW_ONLY, dataclass
|
|
|
4
4
|
import anyio
|
|
5
5
|
import anyio.to_thread
|
|
6
6
|
from pydantic import TypeAdapter
|
|
7
|
-
from typing_extensions import TypedDict
|
|
7
|
+
from typing_extensions import Any, TypedDict
|
|
8
8
|
|
|
9
9
|
from pydantic_ai.tools import Tool
|
|
10
10
|
|
|
@@ -69,7 +69,7 @@ def duckduckgo_search_tool(duckduckgo_client: DDGS | None = None, max_results: i
|
|
|
69
69
|
duckduckgo_client: The DuckDuckGo search client.
|
|
70
70
|
max_results: The maximum number of results. If None, returns results only from the first response.
|
|
71
71
|
"""
|
|
72
|
-
return Tool(
|
|
72
|
+
return Tool[Any](
|
|
73
73
|
DuckDuckGoSearchTool(client=duckduckgo_client or DDGS(), max_results=max_results).__call__,
|
|
74
74
|
name='duckduckgo_search',
|
|
75
75
|
description='Searches DuckDuckGo for the given query and returns the results.',
|
|
@@ -2,7 +2,7 @@ from dataclasses import dataclass
|
|
|
2
2
|
from typing import Literal
|
|
3
3
|
|
|
4
4
|
from pydantic import TypeAdapter
|
|
5
|
-
from typing_extensions import TypedDict
|
|
5
|
+
from typing_extensions import Any, TypedDict
|
|
6
6
|
|
|
7
7
|
from pydantic_ai.tools import Tool
|
|
8
8
|
|
|
@@ -74,7 +74,7 @@ def tavily_search_tool(api_key: str):
|
|
|
74
74
|
|
|
75
75
|
You can get one by signing up at [https://app.tavily.com/home](https://app.tavily.com/home).
|
|
76
76
|
"""
|
|
77
|
-
return Tool(
|
|
77
|
+
return Tool[Any](
|
|
78
78
|
TavilySearchTool(client=AsyncTavilyClient(api_key)).__call__,
|
|
79
79
|
name='tavily_search',
|
|
80
80
|
description='Searches Tavily for the given query and returns the results.',
|
pydantic_ai/direct.py
CHANGED
|
@@ -44,8 +44,8 @@ async def model_request(
|
|
|
44
44
|
"""Make a non-streamed request to a model.
|
|
45
45
|
|
|
46
46
|
```py title="model_request_example.py"
|
|
47
|
+
from pydantic_ai import ModelRequest
|
|
47
48
|
from pydantic_ai.direct import model_request
|
|
48
|
-
from pydantic_ai.messages import ModelRequest
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
async def main():
|
|
@@ -81,7 +81,7 @@ async def model_request(
|
|
|
81
81
|
return await model_instance.request(
|
|
82
82
|
messages,
|
|
83
83
|
model_settings,
|
|
84
|
-
|
|
84
|
+
model_request_parameters or models.ModelRequestParameters(),
|
|
85
85
|
)
|
|
86
86
|
|
|
87
87
|
|
|
@@ -99,8 +99,8 @@ def model_request_sync(
|
|
|
99
99
|
`loop.run_until_complete(...)`. You therefore can't use this method inside async code or if there's an active event loop.
|
|
100
100
|
|
|
101
101
|
```py title="model_request_sync_example.py"
|
|
102
|
+
from pydantic_ai import ModelRequest
|
|
102
103
|
from pydantic_ai.direct import model_request_sync
|
|
103
|
-
from pydantic_ai.messages import ModelRequest
|
|
104
104
|
|
|
105
105
|
model_response = model_request_sync(
|
|
106
106
|
'anthropic:claude-3-5-haiku-latest',
|
|
@@ -153,8 +153,8 @@ def model_request_stream(
|
|
|
153
153
|
|
|
154
154
|
```py {title="model_request_stream_example.py"}
|
|
155
155
|
|
|
156
|
+
from pydantic_ai import ModelRequest
|
|
156
157
|
from pydantic_ai.direct import model_request_stream
|
|
157
|
-
from pydantic_ai.messages import ModelRequest
|
|
158
158
|
|
|
159
159
|
|
|
160
160
|
async def main():
|
|
@@ -193,7 +193,7 @@ def model_request_stream(
|
|
|
193
193
|
return model_instance.request_stream(
|
|
194
194
|
messages,
|
|
195
195
|
model_settings,
|
|
196
|
-
|
|
196
|
+
model_request_parameters or models.ModelRequestParameters(),
|
|
197
197
|
)
|
|
198
198
|
|
|
199
199
|
|
|
@@ -212,8 +212,8 @@ def model_request_stream_sync(
|
|
|
212
212
|
|
|
213
213
|
```py {title="model_request_stream_sync_example.py"}
|
|
214
214
|
|
|
215
|
+
from pydantic_ai import ModelRequest
|
|
215
216
|
from pydantic_ai.direct import model_request_stream_sync
|
|
216
|
-
from pydantic_ai.messages import ModelRequest
|
|
217
217
|
|
|
218
218
|
messages = [ModelRequest.user_text_prompt('Who was Albert Einstein?')]
|
|
219
219
|
with model_request_stream_sync('openai:gpt-4.1-mini', messages) as stream:
|
|
@@ -8,12 +8,14 @@ from dbos import DBOS, DBOSConfiguredInstance
|
|
|
8
8
|
from typing_extensions import Never
|
|
9
9
|
|
|
10
10
|
from pydantic_ai import (
|
|
11
|
+
AbstractToolset,
|
|
11
12
|
_utils,
|
|
12
13
|
messages as _messages,
|
|
13
14
|
models,
|
|
14
15
|
usage as _usage,
|
|
15
16
|
)
|
|
16
17
|
from pydantic_ai.agent import AbstractAgent, AgentRun, AgentRunResult, EventStreamHandler, RunOutputDataT, WrapperAgent
|
|
18
|
+
from pydantic_ai.agent.abstract import Instructions
|
|
17
19
|
from pydantic_ai.exceptions import UserError
|
|
18
20
|
from pydantic_ai.models import Model
|
|
19
21
|
from pydantic_ai.output import OutputDataT, OutputSpec
|
|
@@ -26,7 +28,6 @@ from pydantic_ai.tools import (
|
|
|
26
28
|
Tool,
|
|
27
29
|
ToolFuncEither,
|
|
28
30
|
)
|
|
29
|
-
from pydantic_ai.toolsets import AbstractToolset
|
|
30
31
|
|
|
31
32
|
from ._model import DBOSModel
|
|
32
33
|
from ._utils import StepConfig
|
|
@@ -704,8 +705,9 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
|
|
|
704
705
|
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
|
|
705
706
|
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
|
|
706
707
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
|
|
708
|
+
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
|
|
707
709
|
) -> Iterator[None]:
|
|
708
|
-
"""Context manager to temporarily override agent dependencies, model, toolsets, or
|
|
710
|
+
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
|
|
709
711
|
|
|
710
712
|
This is particularly useful when testing.
|
|
711
713
|
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
|
|
@@ -715,11 +717,18 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
|
|
|
715
717
|
model: The model to use instead of the model passed to the agent run.
|
|
716
718
|
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
|
|
717
719
|
tools: The tools to use instead of the tools registered with the agent.
|
|
720
|
+
instructions: The instructions to use instead of the instructions registered with the agent.
|
|
718
721
|
"""
|
|
719
722
|
if _utils.is_set(model) and not isinstance(model, (DBOSModel)):
|
|
720
723
|
raise UserError(
|
|
721
724
|
'Non-DBOS model cannot be contextually overridden inside a DBOS workflow, it must be set at agent creation time.'
|
|
722
725
|
)
|
|
723
726
|
|
|
724
|
-
with super().override(
|
|
727
|
+
with super().override(
|
|
728
|
+
deps=deps,
|
|
729
|
+
model=model,
|
|
730
|
+
toolsets=toolsets,
|
|
731
|
+
tools=tools,
|
|
732
|
+
instructions=instructions,
|
|
733
|
+
):
|
|
725
734
|
yield
|
|
@@ -7,9 +7,8 @@ from typing import TYPE_CHECKING, Any
|
|
|
7
7
|
from dbos import DBOS
|
|
8
8
|
from typing_extensions import Self
|
|
9
9
|
|
|
10
|
+
from pydantic_ai import AbstractToolset, ToolsetTool, WrapperToolset
|
|
10
11
|
from pydantic_ai.tools import AgentDepsT, RunContext
|
|
11
|
-
from pydantic_ai.toolsets.abstract import AbstractToolset, ToolsetTool
|
|
12
|
-
from pydantic_ai.toolsets.wrapper import WrapperToolset
|
|
13
12
|
|
|
14
13
|
from ._utils import StepConfig
|
|
15
14
|
|
|
@@ -7,12 +7,12 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from dbos import DBOS
|
|
9
9
|
|
|
10
|
-
from pydantic_ai
|
|
11
|
-
from pydantic_ai.messages import (
|
|
10
|
+
from pydantic_ai import (
|
|
12
11
|
ModelMessage,
|
|
13
12
|
ModelResponse,
|
|
14
13
|
ModelResponseStreamEvent,
|
|
15
14
|
)
|
|
15
|
+
from pydantic_ai.agent import EventStreamHandler
|
|
16
16
|
from pydantic_ai.models import Model, ModelRequestParameters, StreamedResponse
|
|
17
17
|
from pydantic_ai.models.wrapper import WrapperModel
|
|
18
18
|
from pydantic_ai.settings import ModelSettings
|
|
@@ -16,12 +16,14 @@ from temporalio.workflow import ActivityConfig
|
|
|
16
16
|
from typing_extensions import Never
|
|
17
17
|
|
|
18
18
|
from pydantic_ai import (
|
|
19
|
+
AbstractToolset,
|
|
19
20
|
_utils,
|
|
20
21
|
messages as _messages,
|
|
21
22
|
models,
|
|
22
23
|
usage as _usage,
|
|
23
24
|
)
|
|
24
|
-
from pydantic_ai.agent import AbstractAgent, AgentRun, AgentRunResult, EventStreamHandler,
|
|
25
|
+
from pydantic_ai.agent import AbstractAgent, AgentRun, AgentRunResult, EventStreamHandler, WrapperAgent
|
|
26
|
+
from pydantic_ai.agent.abstract import Instructions, RunOutputDataT
|
|
25
27
|
from pydantic_ai.exceptions import UserError
|
|
26
28
|
from pydantic_ai.models import Model
|
|
27
29
|
from pydantic_ai.output import OutputDataT, OutputSpec
|
|
@@ -34,7 +36,6 @@ from pydantic_ai.tools import (
|
|
|
34
36
|
Tool,
|
|
35
37
|
ToolFuncEither,
|
|
36
38
|
)
|
|
37
|
-
from pydantic_ai.toolsets import AbstractToolset
|
|
38
39
|
|
|
39
40
|
from ._model import TemporalModel
|
|
40
41
|
from ._run_context import TemporalRunContext
|
|
@@ -748,8 +749,9 @@ class TemporalAgent(WrapperAgent[AgentDepsT, OutputDataT]):
|
|
|
748
749
|
model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
|
|
749
750
|
toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
|
|
750
751
|
tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
|
|
752
|
+
instructions: Instructions[AgentDepsT] | _utils.Unset = _utils.UNSET,
|
|
751
753
|
) -> Iterator[None]:
|
|
752
|
-
"""Context manager to temporarily override agent dependencies, model, toolsets, or
|
|
754
|
+
"""Context manager to temporarily override agent dependencies, model, toolsets, tools, or instructions.
|
|
753
755
|
|
|
754
756
|
This is particularly useful when testing.
|
|
755
757
|
You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
|
|
@@ -759,6 +761,7 @@ class TemporalAgent(WrapperAgent[AgentDepsT, OutputDataT]):
|
|
|
759
761
|
model: The model to use instead of the model passed to the agent run.
|
|
760
762
|
toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
|
|
761
763
|
tools: The tools to use instead of the tools registered with the agent.
|
|
764
|
+
instructions: The instructions to use instead of the instructions registered with the agent.
|
|
762
765
|
"""
|
|
763
766
|
if workflow.in_workflow():
|
|
764
767
|
if _utils.is_set(model):
|
|
@@ -774,5 +777,11 @@ class TemporalAgent(WrapperAgent[AgentDepsT, OutputDataT]):
|
|
|
774
777
|
'Tools cannot be contextually overridden inside a Temporal workflow, they must be set at agent creation time.'
|
|
775
778
|
)
|
|
776
779
|
|
|
777
|
-
with super().override(
|
|
780
|
+
with super().override(
|
|
781
|
+
deps=deps,
|
|
782
|
+
model=model,
|
|
783
|
+
toolsets=toolsets,
|
|
784
|
+
tools=tools,
|
|
785
|
+
instructions=instructions,
|
|
786
|
+
):
|
|
778
787
|
yield
|
|
@@ -8,9 +8,9 @@ from pydantic import ConfigDict, Discriminator, with_config
|
|
|
8
8
|
from temporalio import activity, workflow
|
|
9
9
|
from temporalio.workflow import ActivityConfig
|
|
10
10
|
|
|
11
|
+
from pydantic_ai import FunctionToolset, ToolsetTool
|
|
11
12
|
from pydantic_ai.exceptions import ApprovalRequired, CallDeferred, ModelRetry, UserError
|
|
12
13
|
from pydantic_ai.tools import AgentDepsT, RunContext
|
|
13
|
-
from pydantic_ai.toolsets import FunctionToolset, ToolsetTool
|
|
14
14
|
from pydantic_ai.toolsets.function import FunctionToolsetTool
|
|
15
15
|
|
|
16
16
|
from ._run_context import TemporalRunContext
|
|
@@ -9,10 +9,10 @@ from temporalio import activity, workflow
|
|
|
9
9
|
from temporalio.workflow import ActivityConfig
|
|
10
10
|
from typing_extensions import Self
|
|
11
11
|
|
|
12
|
+
from pydantic_ai import ToolsetTool
|
|
12
13
|
from pydantic_ai.exceptions import UserError
|
|
13
14
|
from pydantic_ai.mcp import MCPServer, ToolResult
|
|
14
15
|
from pydantic_ai.tools import AgentDepsT, RunContext, ToolDefinition
|
|
15
|
-
from pydantic_ai.toolsets.abstract import ToolsetTool
|
|
16
16
|
|
|
17
17
|
from ._run_context import TemporalRunContext
|
|
18
18
|
from ._toolset import TemporalWrapperToolset
|
|
@@ -10,13 +10,13 @@ from pydantic import ConfigDict, with_config
|
|
|
10
10
|
from temporalio import activity, workflow
|
|
11
11
|
from temporalio.workflow import ActivityConfig
|
|
12
12
|
|
|
13
|
-
from pydantic_ai
|
|
14
|
-
from pydantic_ai.exceptions import UserError
|
|
15
|
-
from pydantic_ai.messages import (
|
|
13
|
+
from pydantic_ai import (
|
|
16
14
|
ModelMessage,
|
|
17
15
|
ModelResponse,
|
|
18
16
|
ModelResponseStreamEvent,
|
|
19
17
|
)
|
|
18
|
+
from pydantic_ai.agent import EventStreamHandler
|
|
19
|
+
from pydantic_ai.exceptions import UserError
|
|
20
20
|
from pydantic_ai.models import Model, ModelRequestParameters, StreamedResponse
|
|
21
21
|
from pydantic_ai.models.wrapper import WrapperModel
|
|
22
22
|
from pydantic_ai.settings import ModelSettings
|
|
@@ -6,10 +6,8 @@ from typing import Any, Literal
|
|
|
6
6
|
|
|
7
7
|
from temporalio.workflow import ActivityConfig
|
|
8
8
|
|
|
9
|
+
from pydantic_ai import AbstractToolset, FunctionToolset, WrapperToolset
|
|
9
10
|
from pydantic_ai.tools import AgentDepsT
|
|
10
|
-
from pydantic_ai.toolsets.abstract import AbstractToolset
|
|
11
|
-
from pydantic_ai.toolsets.function import FunctionToolset
|
|
12
|
-
from pydantic_ai.toolsets.wrapper import WrapperToolset
|
|
13
11
|
|
|
14
12
|
from ._run_context import TemporalRunContext
|
|
15
13
|
|
pydantic_ai/ext/aci.py
CHANGED
|
@@ -3,8 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
|
+
from pydantic_ai import FunctionToolset
|
|
6
7
|
from pydantic_ai.tools import Tool
|
|
7
|
-
from pydantic_ai.toolsets.function import FunctionToolset
|
|
8
8
|
|
|
9
9
|
try:
|
|
10
10
|
from aci import ACI
|
pydantic_ai/ext/langchain.py
CHANGED
|
@@ -4,8 +4,8 @@ from typing import Any, Protocol
|
|
|
4
4
|
|
|
5
5
|
from pydantic.json_schema import JsonSchemaValue
|
|
6
6
|
|
|
7
|
+
from pydantic_ai import FunctionToolset
|
|
7
8
|
from pydantic_ai.tools import Tool
|
|
8
|
-
from pydantic_ai.toolsets.function import FunctionToolset
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class LangChainTool(Protocol):
|