pydantic-ai-slim 1.0.1__py3-none-any.whl → 1.0.3__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.
Files changed (36) hide show
  1. pydantic_ai/_agent_graph.py +50 -31
  2. pydantic_ai/_output.py +19 -7
  3. pydantic_ai/_parts_manager.py +8 -10
  4. pydantic_ai/_tool_manager.py +21 -0
  5. pydantic_ai/ag_ui.py +32 -17
  6. pydantic_ai/agent/__init__.py +3 -0
  7. pydantic_ai/agent/abstract.py +8 -0
  8. pydantic_ai/durable_exec/dbos/__init__.py +6 -0
  9. pydantic_ai/durable_exec/dbos/_agent.py +721 -0
  10. pydantic_ai/durable_exec/dbos/_mcp_server.py +89 -0
  11. pydantic_ai/durable_exec/dbos/_model.py +137 -0
  12. pydantic_ai/durable_exec/dbos/_utils.py +10 -0
  13. pydantic_ai/durable_exec/temporal/_agent.py +1 -1
  14. pydantic_ai/mcp.py +1 -1
  15. pydantic_ai/messages.py +42 -6
  16. pydantic_ai/models/__init__.py +8 -0
  17. pydantic_ai/models/anthropic.py +79 -25
  18. pydantic_ai/models/bedrock.py +82 -31
  19. pydantic_ai/models/cohere.py +39 -13
  20. pydantic_ai/models/function.py +8 -1
  21. pydantic_ai/models/google.py +105 -37
  22. pydantic_ai/models/groq.py +35 -7
  23. pydantic_ai/models/huggingface.py +27 -5
  24. pydantic_ai/models/instrumented.py +27 -14
  25. pydantic_ai/models/mistral.py +54 -20
  26. pydantic_ai/models/openai.py +151 -57
  27. pydantic_ai/profiles/openai.py +7 -0
  28. pydantic_ai/providers/bedrock.py +20 -4
  29. pydantic_ai/settings.py +1 -0
  30. pydantic_ai/tools.py +11 -0
  31. pydantic_ai/toolsets/function.py +7 -0
  32. {pydantic_ai_slim-1.0.1.dist-info → pydantic_ai_slim-1.0.3.dist-info}/METADATA +8 -6
  33. {pydantic_ai_slim-1.0.1.dist-info → pydantic_ai_slim-1.0.3.dist-info}/RECORD +36 -31
  34. {pydantic_ai_slim-1.0.1.dist-info → pydantic_ai_slim-1.0.3.dist-info}/WHEEL +0 -0
  35. {pydantic_ai_slim-1.0.1.dist-info → pydantic_ai_slim-1.0.3.dist-info}/entry_points.txt +0 -0
  36. {pydantic_ai_slim-1.0.1.dist-info → pydantic_ai_slim-1.0.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,721 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import AsyncIterable, AsyncIterator, Iterator, Sequence
4
+ from contextlib import AbstractAsyncContextManager, asynccontextmanager, contextmanager
5
+ from typing import Any, overload
6
+
7
+ from dbos import DBOS, DBOSConfiguredInstance
8
+ from typing_extensions import Never
9
+
10
+ from pydantic_ai import (
11
+ _utils,
12
+ messages as _messages,
13
+ models,
14
+ usage as _usage,
15
+ )
16
+ from pydantic_ai.agent import AbstractAgent, AgentRun, AgentRunResult, EventStreamHandler, RunOutputDataT, WrapperAgent
17
+ from pydantic_ai.exceptions import UserError
18
+ from pydantic_ai.mcp import MCPServer
19
+ from pydantic_ai.models import Model
20
+ from pydantic_ai.output import OutputDataT, OutputSpec
21
+ from pydantic_ai.result import StreamedRunResult
22
+ from pydantic_ai.settings import ModelSettings
23
+ from pydantic_ai.tools import (
24
+ AgentDepsT,
25
+ DeferredToolResults,
26
+ RunContext,
27
+ Tool,
28
+ ToolFuncEither,
29
+ )
30
+ from pydantic_ai.toolsets import AbstractToolset
31
+
32
+ from ._mcp_server import DBOSMCPServer
33
+ from ._model import DBOSModel
34
+ from ._utils import StepConfig
35
+
36
+
37
+ @DBOS.dbos_class()
38
+ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
39
+ def __init__(
40
+ self,
41
+ wrapped: AbstractAgent[AgentDepsT, OutputDataT],
42
+ *,
43
+ name: str | None = None,
44
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
45
+ mcp_step_config: StepConfig | None = None,
46
+ model_step_config: StepConfig | None = None,
47
+ ):
48
+ """Wrap an agent to enable it with DBOS durable workflows, by automatically offloading model requests, tool calls, and MCP server communication to DBOS steps.
49
+
50
+ After wrapping, the original agent can still be used as normal outside of the DBOS workflow.
51
+
52
+ Args:
53
+ wrapped: The agent to wrap.
54
+ name: Optional unique agent name to use as the DBOS configured instance name. If not provided, the agent's `name` will be used.
55
+ event_stream_handler: Optional event stream handler to use instead of the one set on the wrapped agent.
56
+ mcp_step_config: The base DBOS step config to use for MCP server steps. If no config is provided, use the default settings of DBOS.
57
+ model_step_config: The DBOS step config to use for model request steps. If no config is provided, use the default settings of DBOS.
58
+ """
59
+ super().__init__(wrapped)
60
+
61
+ self._name = name or wrapped.name
62
+ self._event_stream_handler = event_stream_handler
63
+ if self._name is None:
64
+ raise UserError(
65
+ "An agent needs to have a unique `name` in order to be used with DBOS. The name will be used to identify the agent's workflows and steps."
66
+ )
67
+
68
+ # Merge the config with the default DBOS config
69
+ self._mcp_step_config = mcp_step_config or {}
70
+ self._model_step_config = model_step_config or {}
71
+
72
+ if not isinstance(wrapped.model, Model):
73
+ raise UserError(
74
+ 'An agent needs to have a `model` in order to be used with DBOS, it cannot be set at agent run time.'
75
+ )
76
+
77
+ dbos_model = DBOSModel(
78
+ wrapped.model,
79
+ step_name_prefix=self._name,
80
+ step_config=self._model_step_config,
81
+ event_stream_handler=self.event_stream_handler,
82
+ )
83
+ self._model = dbos_model
84
+
85
+ dbosagent_name = self._name
86
+
87
+ def dbosify_toolset(toolset: AbstractToolset[AgentDepsT]) -> AbstractToolset[AgentDepsT]:
88
+ # Replace MCPServer with DBOSMCPServer
89
+ if isinstance(toolset, MCPServer):
90
+ return DBOSMCPServer(
91
+ wrapped=toolset,
92
+ step_name_prefix=dbosagent_name,
93
+ step_config=self._mcp_step_config,
94
+ )
95
+ else:
96
+ return toolset
97
+
98
+ dbos_toolsets = [toolset.visit_and_replace(dbosify_toolset) for toolset in wrapped.toolsets]
99
+ self._toolsets = dbos_toolsets
100
+ DBOSConfiguredInstance.__init__(self, self._name)
101
+
102
+ # Wrap the `run` method in a DBOS workflow
103
+ @DBOS.workflow(name=f'{self._name}.run')
104
+ async def wrapped_run_workflow(
105
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
106
+ *,
107
+ output_type: OutputSpec[RunOutputDataT] | None = None,
108
+ message_history: list[_messages.ModelMessage] | None = None,
109
+ deferred_tool_results: DeferredToolResults | None = None,
110
+ model: models.Model | models.KnownModelName | str | None = None,
111
+ deps: AgentDepsT,
112
+ model_settings: ModelSettings | None = None,
113
+ usage_limits: _usage.UsageLimits | None = None,
114
+ usage: _usage.RunUsage | None = None,
115
+ infer_name: bool = True,
116
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
117
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
118
+ **_deprecated_kwargs: Never,
119
+ ) -> AgentRunResult[Any]:
120
+ with self._dbos_overrides():
121
+ return await super(WrapperAgent, self).run(
122
+ user_prompt,
123
+ output_type=output_type,
124
+ message_history=message_history,
125
+ deferred_tool_results=deferred_tool_results,
126
+ model=model,
127
+ deps=deps,
128
+ model_settings=model_settings,
129
+ usage_limits=usage_limits,
130
+ usage=usage,
131
+ infer_name=infer_name,
132
+ toolsets=toolsets,
133
+ event_stream_handler=event_stream_handler,
134
+ **_deprecated_kwargs,
135
+ )
136
+
137
+ self.dbos_wrapped_run_workflow = wrapped_run_workflow
138
+
139
+ # Wrap the `run_sync` method in a DBOS workflow
140
+ @DBOS.workflow(name=f'{self._name}.run_sync')
141
+ def wrapped_run_sync_workflow(
142
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
143
+ *,
144
+ output_type: OutputSpec[RunOutputDataT] | None = None,
145
+ message_history: list[_messages.ModelMessage] | None = None,
146
+ deferred_tool_results: DeferredToolResults | None = None,
147
+ model: models.Model | models.KnownModelName | str | None = None,
148
+ deps: AgentDepsT,
149
+ model_settings: ModelSettings | None = None,
150
+ usage_limits: _usage.UsageLimits | None = None,
151
+ usage: _usage.RunUsage | None = None,
152
+ infer_name: bool = True,
153
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
154
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
155
+ **_deprecated_kwargs: Never,
156
+ ) -> AgentRunResult[Any]:
157
+ with self._dbos_overrides():
158
+ return super(DBOSAgent, self).run_sync(
159
+ user_prompt,
160
+ output_type=output_type,
161
+ message_history=message_history,
162
+ deferred_tool_results=deferred_tool_results,
163
+ model=model,
164
+ deps=deps,
165
+ model_settings=model_settings,
166
+ usage_limits=usage_limits,
167
+ usage=usage,
168
+ infer_name=infer_name,
169
+ toolsets=toolsets,
170
+ event_stream_handler=event_stream_handler,
171
+ **_deprecated_kwargs,
172
+ )
173
+
174
+ self.dbos_wrapped_run_sync_workflow = wrapped_run_sync_workflow
175
+
176
+ @property
177
+ def name(self) -> str | None:
178
+ return self._name
179
+
180
+ @name.setter
181
+ def name(self, value: str | None) -> None: # pragma: no cover
182
+ raise UserError(
183
+ 'The agent name cannot be changed after creation. If you need to change the name, create a new agent.'
184
+ )
185
+
186
+ @property
187
+ def model(self) -> Model:
188
+ return self._model
189
+
190
+ @property
191
+ def event_stream_handler(self) -> EventStreamHandler[AgentDepsT] | None:
192
+ handler = self._event_stream_handler or super().event_stream_handler
193
+ if handler is None:
194
+ return None
195
+ elif DBOS.workflow_id is not None and DBOS.step_id is None:
196
+ # Special case if it's in a DBOS workflow but not a step, we need to iterate through all events and call the handler.
197
+ return self._call_event_stream_handler_in_workflow
198
+ else:
199
+ return handler
200
+
201
+ async def _call_event_stream_handler_in_workflow(
202
+ self, ctx: RunContext[AgentDepsT], stream: AsyncIterable[_messages.AgentStreamEvent]
203
+ ) -> None:
204
+ handler = self._event_stream_handler or super().event_stream_handler
205
+ assert handler is not None
206
+
207
+ async def streamed_response(event: _messages.AgentStreamEvent):
208
+ yield event
209
+
210
+ async for event in stream:
211
+ await handler(ctx, streamed_response(event))
212
+
213
+ @property
214
+ def toolsets(self) -> Sequence[AbstractToolset[AgentDepsT]]:
215
+ with self._dbos_overrides():
216
+ return super().toolsets
217
+
218
+ @contextmanager
219
+ def _dbos_overrides(self) -> Iterator[None]:
220
+ # Override with DBOSModel and DBOSMCPServer in the toolsets.
221
+ with (
222
+ super().override(model=self._model, toolsets=self._toolsets, tools=[]),
223
+ self.sequential_tool_calls(),
224
+ ):
225
+ yield
226
+
227
+ @overload
228
+ async def run(
229
+ self,
230
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
231
+ *,
232
+ output_type: None = None,
233
+ message_history: list[_messages.ModelMessage] | None = None,
234
+ deferred_tool_results: DeferredToolResults | None = None,
235
+ model: models.Model | models.KnownModelName | str | None = None,
236
+ deps: AgentDepsT = None,
237
+ model_settings: ModelSettings | None = None,
238
+ usage_limits: _usage.UsageLimits | None = None,
239
+ usage: _usage.RunUsage | None = None,
240
+ infer_name: bool = True,
241
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
242
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
243
+ ) -> AgentRunResult[OutputDataT]: ...
244
+
245
+ @overload
246
+ async def run(
247
+ self,
248
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
249
+ *,
250
+ output_type: OutputSpec[RunOutputDataT],
251
+ message_history: list[_messages.ModelMessage] | None = None,
252
+ deferred_tool_results: DeferredToolResults | None = None,
253
+ model: models.Model | models.KnownModelName | str | None = None,
254
+ deps: AgentDepsT = None,
255
+ model_settings: ModelSettings | None = None,
256
+ usage_limits: _usage.UsageLimits | None = None,
257
+ usage: _usage.RunUsage | None = None,
258
+ infer_name: bool = True,
259
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
260
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
261
+ ) -> AgentRunResult[RunOutputDataT]: ...
262
+
263
+ async def run(
264
+ self,
265
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
266
+ *,
267
+ output_type: OutputSpec[RunOutputDataT] | None = None,
268
+ message_history: list[_messages.ModelMessage] | None = None,
269
+ deferred_tool_results: DeferredToolResults | None = None,
270
+ model: models.Model | models.KnownModelName | str | None = None,
271
+ deps: AgentDepsT = None,
272
+ model_settings: ModelSettings | None = None,
273
+ usage_limits: _usage.UsageLimits | None = None,
274
+ usage: _usage.RunUsage | None = None,
275
+ infer_name: bool = True,
276
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
277
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
278
+ **_deprecated_kwargs: Never,
279
+ ) -> AgentRunResult[Any]:
280
+ """Run the agent with a user prompt in async mode.
281
+
282
+ This method builds an internal agent graph (using system prompts, tools and result schemas) and then
283
+ runs the graph to completion. The result of the run is returned.
284
+
285
+ Example:
286
+ ```python
287
+ from pydantic_ai import Agent
288
+
289
+ agent = Agent('openai:gpt-4o')
290
+
291
+ async def main():
292
+ agent_run = await agent.run('What is the capital of France?')
293
+ print(agent_run.output)
294
+ #> The capital of France is Paris.
295
+ ```
296
+
297
+ Args:
298
+ user_prompt: User input to start/continue the conversation.
299
+ output_type: Custom output type to use for this run, `output_type` may only be used if the agent has no
300
+ output validators since output validators would expect an argument that matches the agent's output type.
301
+ message_history: History of the conversation so far.
302
+ deferred_tool_results: Optional results for deferred tool calls in the message history.
303
+ model: Optional model to use for this run, required if `model` was not set when creating the agent.
304
+ deps: Optional dependencies to use for this run.
305
+ model_settings: Optional settings to use for this model's request.
306
+ usage_limits: Optional limits on model request count or token usage.
307
+ usage: Optional usage to start with, useful for resuming a conversation or agents used in tools.
308
+ infer_name: Whether to try to infer the agent name from the call frame if it's not set.
309
+ toolsets: Optional additional toolsets for this run.
310
+ event_stream_handler: Optional event stream handler to use for this run.
311
+
312
+ Returns:
313
+ The result of the run.
314
+ """
315
+ return await self.dbos_wrapped_run_workflow(
316
+ user_prompt,
317
+ output_type=output_type,
318
+ message_history=message_history,
319
+ deferred_tool_results=deferred_tool_results,
320
+ model=model,
321
+ deps=deps,
322
+ model_settings=model_settings,
323
+ usage_limits=usage_limits,
324
+ usage=usage,
325
+ infer_name=infer_name,
326
+ toolsets=toolsets,
327
+ event_stream_handler=event_stream_handler,
328
+ **_deprecated_kwargs,
329
+ )
330
+
331
+ @overload
332
+ def run_sync(
333
+ self,
334
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
335
+ *,
336
+ output_type: None = None,
337
+ message_history: list[_messages.ModelMessage] | None = None,
338
+ deferred_tool_results: DeferredToolResults | None = None,
339
+ model: models.Model | models.KnownModelName | str | None = None,
340
+ deps: AgentDepsT = None,
341
+ model_settings: ModelSettings | None = None,
342
+ usage_limits: _usage.UsageLimits | None = None,
343
+ usage: _usage.RunUsage | None = None,
344
+ infer_name: bool = True,
345
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
346
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
347
+ ) -> AgentRunResult[OutputDataT]: ...
348
+
349
+ @overload
350
+ def run_sync(
351
+ self,
352
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
353
+ *,
354
+ output_type: OutputSpec[RunOutputDataT],
355
+ message_history: list[_messages.ModelMessage] | None = None,
356
+ deferred_tool_results: DeferredToolResults | None = None,
357
+ model: models.Model | models.KnownModelName | str | None = None,
358
+ deps: AgentDepsT = None,
359
+ model_settings: ModelSettings | None = None,
360
+ usage_limits: _usage.UsageLimits | None = None,
361
+ usage: _usage.RunUsage | None = None,
362
+ infer_name: bool = True,
363
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
364
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
365
+ ) -> AgentRunResult[RunOutputDataT]: ...
366
+
367
+ def run_sync(
368
+ self,
369
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
370
+ *,
371
+ output_type: OutputSpec[RunOutputDataT] | None = None,
372
+ message_history: list[_messages.ModelMessage] | None = None,
373
+ deferred_tool_results: DeferredToolResults | None = None,
374
+ model: models.Model | models.KnownModelName | str | None = None,
375
+ deps: AgentDepsT = None,
376
+ model_settings: ModelSettings | None = None,
377
+ usage_limits: _usage.UsageLimits | None = None,
378
+ usage: _usage.RunUsage | None = None,
379
+ infer_name: bool = True,
380
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
381
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
382
+ **_deprecated_kwargs: Never,
383
+ ) -> AgentRunResult[Any]:
384
+ """Synchronously run the agent with a user prompt.
385
+
386
+ This is a convenience method that wraps [`self.run`][pydantic_ai.agent.AbstractAgent.run] with `loop.run_until_complete(...)`.
387
+ You therefore can't use this method inside async code or if there's an active event loop.
388
+
389
+ Example:
390
+ ```python
391
+ from pydantic_ai import Agent
392
+
393
+ agent = Agent('openai:gpt-4o')
394
+
395
+ result_sync = agent.run_sync('What is the capital of Italy?')
396
+ print(result_sync.output)
397
+ #> The capital of Italy is Rome.
398
+ ```
399
+
400
+ Args:
401
+ user_prompt: User input to start/continue the conversation.
402
+ output_type: Custom output type to use for this run, `output_type` may only be used if the agent has no
403
+ output validators since output validators would expect an argument that matches the agent's output type.
404
+ message_history: History of the conversation so far.
405
+ deferred_tool_results: Optional results for deferred tool calls in the message history.
406
+ model: Optional model to use for this run, required if `model` was not set when creating the agent.
407
+ deps: Optional dependencies to use for this run.
408
+ model_settings: Optional settings to use for this model's request.
409
+ usage_limits: Optional limits on model request count or token usage.
410
+ usage: Optional usage to start with, useful for resuming a conversation or agents used in tools.
411
+ infer_name: Whether to try to infer the agent name from the call frame if it's not set.
412
+ toolsets: Optional additional toolsets for this run.
413
+ event_stream_handler: Optional event stream handler to use for this run.
414
+
415
+ Returns:
416
+ The result of the run.
417
+ """
418
+ return self.dbos_wrapped_run_sync_workflow(
419
+ user_prompt,
420
+ output_type=output_type,
421
+ message_history=message_history,
422
+ deferred_tool_results=deferred_tool_results,
423
+ model=model,
424
+ deps=deps,
425
+ model_settings=model_settings,
426
+ usage_limits=usage_limits,
427
+ usage=usage,
428
+ infer_name=infer_name,
429
+ toolsets=toolsets,
430
+ event_stream_handler=event_stream_handler,
431
+ **_deprecated_kwargs,
432
+ )
433
+
434
+ @overload
435
+ def run_stream(
436
+ self,
437
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
438
+ *,
439
+ output_type: None = None,
440
+ message_history: list[_messages.ModelMessage] | None = None,
441
+ deferred_tool_results: DeferredToolResults | None = None,
442
+ model: models.Model | models.KnownModelName | str | None = None,
443
+ deps: AgentDepsT = None,
444
+ model_settings: ModelSettings | None = None,
445
+ usage_limits: _usage.UsageLimits | None = None,
446
+ usage: _usage.RunUsage | None = None,
447
+ infer_name: bool = True,
448
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
449
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
450
+ ) -> AbstractAsyncContextManager[StreamedRunResult[AgentDepsT, OutputDataT]]: ...
451
+
452
+ @overload
453
+ def run_stream(
454
+ self,
455
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
456
+ *,
457
+ output_type: OutputSpec[RunOutputDataT],
458
+ message_history: list[_messages.ModelMessage] | None = None,
459
+ deferred_tool_results: DeferredToolResults | None = None,
460
+ model: models.Model | models.KnownModelName | str | None = None,
461
+ deps: AgentDepsT = None,
462
+ model_settings: ModelSettings | None = None,
463
+ usage_limits: _usage.UsageLimits | None = None,
464
+ usage: _usage.RunUsage | None = None,
465
+ infer_name: bool = True,
466
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
467
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
468
+ ) -> AbstractAsyncContextManager[StreamedRunResult[AgentDepsT, RunOutputDataT]]: ...
469
+
470
+ @asynccontextmanager
471
+ async def run_stream(
472
+ self,
473
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
474
+ *,
475
+ output_type: OutputSpec[RunOutputDataT] | None = None,
476
+ message_history: list[_messages.ModelMessage] | None = None,
477
+ deferred_tool_results: DeferredToolResults | None = None,
478
+ model: models.Model | models.KnownModelName | str | None = None,
479
+ deps: AgentDepsT = None,
480
+ model_settings: ModelSettings | None = None,
481
+ usage_limits: _usage.UsageLimits | None = None,
482
+ usage: _usage.RunUsage | None = None,
483
+ infer_name: bool = True,
484
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
485
+ event_stream_handler: EventStreamHandler[AgentDepsT] | None = None,
486
+ **_deprecated_kwargs: Never,
487
+ ) -> AsyncIterator[StreamedRunResult[AgentDepsT, Any]]:
488
+ """Run the agent with a user prompt in async mode, returning a streamed response.
489
+
490
+ Example:
491
+ ```python
492
+ from pydantic_ai import Agent
493
+
494
+ agent = Agent('openai:gpt-4o')
495
+
496
+ async def main():
497
+ async with agent.run_stream('What is the capital of the UK?') as response:
498
+ print(await response.get_output())
499
+ #> The capital of the UK is London.
500
+ ```
501
+
502
+ Args:
503
+ user_prompt: User input to start/continue the conversation.
504
+ output_type: Custom output type to use for this run, `output_type` may only be used if the agent has no
505
+ output validators since output validators would expect an argument that matches the agent's output type.
506
+ message_history: History of the conversation so far.
507
+ deferred_tool_results: Optional results for deferred tool calls in the message history.
508
+ model: Optional model to use for this run, required if `model` was not set when creating the agent.
509
+ deps: Optional dependencies to use for this run.
510
+ model_settings: Optional settings to use for this model's request.
511
+ usage_limits: Optional limits on model request count or token usage.
512
+ usage: Optional usage to start with, useful for resuming a conversation or agents used in tools.
513
+ infer_name: Whether to try to infer the agent name from the call frame if it's not set.
514
+ toolsets: Optional additional toolsets for this run.
515
+ event_stream_handler: Optional event stream handler to use for this run. It will receive all the events up until the final result is found, which you can then read or stream from inside the context manager.
516
+
517
+ Returns:
518
+ The result of the run.
519
+ """
520
+ if DBOS.workflow_id is not None and DBOS.step_id is None:
521
+ raise UserError(
522
+ '`agent.run_stream()` cannot currently be used inside a DBOS workflow. '
523
+ 'Set an `event_stream_handler` on the agent and use `agent.run()` instead. '
524
+ 'Please file an issue if this is not sufficient for your use case.'
525
+ )
526
+
527
+ async with super().run_stream(
528
+ user_prompt,
529
+ output_type=output_type,
530
+ message_history=message_history,
531
+ deferred_tool_results=deferred_tool_results,
532
+ model=model,
533
+ deps=deps,
534
+ model_settings=model_settings,
535
+ usage_limits=usage_limits,
536
+ usage=usage,
537
+ infer_name=infer_name,
538
+ toolsets=toolsets,
539
+ event_stream_handler=event_stream_handler,
540
+ **_deprecated_kwargs,
541
+ ) as result:
542
+ yield result
543
+
544
+ @overload
545
+ def iter(
546
+ self,
547
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
548
+ *,
549
+ output_type: None = None,
550
+ message_history: list[_messages.ModelMessage] | None = None,
551
+ deferred_tool_results: DeferredToolResults | None = None,
552
+ model: models.Model | models.KnownModelName | str | None = None,
553
+ deps: AgentDepsT = None,
554
+ model_settings: ModelSettings | None = None,
555
+ usage_limits: _usage.UsageLimits | None = None,
556
+ usage: _usage.RunUsage | None = None,
557
+ infer_name: bool = True,
558
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
559
+ **_deprecated_kwargs: Never,
560
+ ) -> AbstractAsyncContextManager[AgentRun[AgentDepsT, OutputDataT]]: ...
561
+
562
+ @overload
563
+ def iter(
564
+ self,
565
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
566
+ *,
567
+ output_type: OutputSpec[RunOutputDataT],
568
+ message_history: list[_messages.ModelMessage] | None = None,
569
+ deferred_tool_results: DeferredToolResults | None = None,
570
+ model: models.Model | models.KnownModelName | str | None = None,
571
+ deps: AgentDepsT = None,
572
+ model_settings: ModelSettings | None = None,
573
+ usage_limits: _usage.UsageLimits | None = None,
574
+ usage: _usage.RunUsage | None = None,
575
+ infer_name: bool = True,
576
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
577
+ **_deprecated_kwargs: Never,
578
+ ) -> AbstractAsyncContextManager[AgentRun[AgentDepsT, RunOutputDataT]]: ...
579
+
580
+ @asynccontextmanager
581
+ async def iter(
582
+ self,
583
+ user_prompt: str | Sequence[_messages.UserContent] | None = None,
584
+ *,
585
+ output_type: OutputSpec[RunOutputDataT] | None = None,
586
+ message_history: list[_messages.ModelMessage] | None = None,
587
+ deferred_tool_results: DeferredToolResults | None = None,
588
+ model: models.Model | models.KnownModelName | str | None = None,
589
+ deps: AgentDepsT = None,
590
+ model_settings: ModelSettings | None = None,
591
+ usage_limits: _usage.UsageLimits | None = None,
592
+ usage: _usage.RunUsage | None = None,
593
+ infer_name: bool = True,
594
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | None = None,
595
+ **_deprecated_kwargs: Never,
596
+ ) -> AsyncIterator[AgentRun[AgentDepsT, Any]]:
597
+ """A contextmanager which can be used to iterate over the agent graph's nodes as they are executed.
598
+
599
+ This method builds an internal agent graph (using system prompts, tools and output schemas) and then returns an
600
+ `AgentRun` object. The `AgentRun` can be used to async-iterate over the nodes of the graph as they are
601
+ executed. This is the API to use if you want to consume the outputs coming from each LLM model response, or the
602
+ stream of events coming from the execution of tools.
603
+
604
+ The `AgentRun` also provides methods to access the full message history, new messages, and usage statistics,
605
+ and the final result of the run once it has completed.
606
+
607
+ For more details, see the documentation of `AgentRun`.
608
+
609
+ Example:
610
+ ```python
611
+ from pydantic_ai import Agent
612
+
613
+ agent = Agent('openai:gpt-4o')
614
+
615
+ async def main():
616
+ nodes = []
617
+ async with agent.iter('What is the capital of France?') as agent_run:
618
+ async for node in agent_run:
619
+ nodes.append(node)
620
+ print(nodes)
621
+ '''
622
+ [
623
+ UserPromptNode(
624
+ user_prompt='What is the capital of France?',
625
+ instructions=None,
626
+ instructions_functions=[],
627
+ system_prompts=(),
628
+ system_prompt_functions=[],
629
+ system_prompt_dynamic_functions={},
630
+ ),
631
+ ModelRequestNode(
632
+ request=ModelRequest(
633
+ parts=[
634
+ UserPromptPart(
635
+ content='What is the capital of France?',
636
+ timestamp=datetime.datetime(...),
637
+ )
638
+ ]
639
+ )
640
+ ),
641
+ CallToolsNode(
642
+ model_response=ModelResponse(
643
+ parts=[TextPart(content='The capital of France is Paris.')],
644
+ usage=RequestUsage(input_tokens=56, output_tokens=7),
645
+ model_name='gpt-4o',
646
+ timestamp=datetime.datetime(...),
647
+ )
648
+ ),
649
+ End(data=FinalResult(output='The capital of France is Paris.')),
650
+ ]
651
+ '''
652
+ print(agent_run.result.output)
653
+ #> The capital of France is Paris.
654
+ ```
655
+
656
+ Args:
657
+ user_prompt: User input to start/continue the conversation.
658
+ output_type: Custom output type to use for this run, `output_type` may only be used if the agent has no
659
+ output validators since output validators would expect an argument that matches the agent's output type.
660
+ message_history: History of the conversation so far.
661
+ deferred_tool_results: Optional results for deferred tool calls in the message history.
662
+ model: Optional model to use for this run, required if `model` was not set when creating the agent.
663
+ deps: Optional dependencies to use for this run.
664
+ model_settings: Optional settings to use for this model's request.
665
+ usage_limits: Optional limits on model request count or token usage.
666
+ usage: Optional usage to start with, useful for resuming a conversation or agents used in tools.
667
+ infer_name: Whether to try to infer the agent name from the call frame if it's not set.
668
+ toolsets: Optional additional toolsets for this run.
669
+
670
+ Returns:
671
+ The result of the run.
672
+ """
673
+ if model is not None and not isinstance(model, DBOSModel):
674
+ raise UserError(
675
+ 'Non-DBOS model cannot be set at agent run time inside a DBOS workflow, it must be set at agent creation time.'
676
+ )
677
+
678
+ with self._dbos_overrides():
679
+ async with super().iter(
680
+ user_prompt=user_prompt,
681
+ output_type=output_type,
682
+ message_history=message_history,
683
+ deferred_tool_results=deferred_tool_results,
684
+ model=model,
685
+ deps=deps,
686
+ model_settings=model_settings,
687
+ usage_limits=usage_limits,
688
+ usage=usage,
689
+ infer_name=infer_name,
690
+ toolsets=toolsets,
691
+ **_deprecated_kwargs,
692
+ ) as run:
693
+ yield run
694
+
695
+ @contextmanager
696
+ def override(
697
+ self,
698
+ *,
699
+ deps: AgentDepsT | _utils.Unset = _utils.UNSET,
700
+ model: models.Model | models.KnownModelName | str | _utils.Unset = _utils.UNSET,
701
+ toolsets: Sequence[AbstractToolset[AgentDepsT]] | _utils.Unset = _utils.UNSET,
702
+ tools: Sequence[Tool[AgentDepsT] | ToolFuncEither[AgentDepsT, ...]] | _utils.Unset = _utils.UNSET,
703
+ ) -> Iterator[None]:
704
+ """Context manager to temporarily override agent dependencies, model, toolsets, or tools.
705
+
706
+ This is particularly useful when testing.
707
+ You can find an example of this [here](../testing.md#overriding-model-via-pytest-fixtures).
708
+
709
+ Args:
710
+ deps: The dependencies to use instead of the dependencies passed to the agent run.
711
+ model: The model to use instead of the model passed to the agent run.
712
+ toolsets: The toolsets to use instead of the toolsets passed to the agent constructor and agent run.
713
+ tools: The tools to use instead of the tools registered with the agent.
714
+ """
715
+ if _utils.is_set(model) and not isinstance(model, (DBOSModel)):
716
+ raise UserError(
717
+ 'Non-DBOS model cannot be contextually overridden inside a DBOS workflow, it must be set at agent creation time.'
718
+ )
719
+
720
+ with super().override(deps=deps, model=model, toolsets=toolsets, tools=tools):
721
+ yield