You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/agents.md
+56-32Lines changed: 56 additions & 32 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -61,17 +61,18 @@ print(result.output)
61
61
62
62
## Running Agents
63
63
64
-
There are four ways to run an agent:
64
+
There are five ways to run an agent:
65
65
66
66
1.[`agent.run()`][pydantic_ai.agent.AbstractAgent.run] — an async function which returns a [`RunResult`][pydantic_ai.agent.AgentRunResult] containing a completed response.
67
67
2.[`agent.run_sync()`][pydantic_ai.agent.AbstractAgent.run_sync] — a plain, synchronous function which returns a [`RunResult`][pydantic_ai.agent.AgentRunResult] containing a completed response (internally, this just calls `loop.run_until_complete(self.run())`).
68
68
3.[`agent.run_stream()`][pydantic_ai.agent.AbstractAgent.run_stream] — an async context manager which returns a [`StreamedRunResult`][pydantic_ai.result.StreamedRunResult], which contains methods to stream text and structured output as an async iterable.
69
-
4.[`agent.iter()`][pydantic_ai.Agent.iter] — a context manager which returns an [`AgentRun`][pydantic_ai.agent.AgentRun], an async-iterable over the nodes of the agent's underlying [`Graph`][pydantic_graph.graph.Graph].
69
+
4.[`agent.run_stream_events()`][pydantic_ai.agent.AbstractAgent.run_stream_events] — a function which returns an async iterable of [`AgentStreamEvent`s][pydantic_ai.messages.AgentStreamEvent] and a [`AgentRunResultEvent`][pydantic_ai.run.AgentRunResultEvent] containing the final run result.
70
+
5.[`agent.iter()`][pydantic_ai.Agent.iter] — a context manager which returns an [`AgentRun`][pydantic_ai.agent.AgentRun], an async iterable over the nodes of the agent's underlying [`Graph`][pydantic_graph.graph.Graph].
70
71
71
-
Here's a simple example demonstrating the first three:
72
+
Here's a simple example demonstrating the first four:
72
73
73
74
```python {title="run_agent.py"}
74
-
from pydantic_ai import Agent
75
+
from pydantic_ai import Agent, AgentRunResultEvent, AgentStreamEvent
result=AgentRunResult(output='The capital of Mexico is Mexico City.')
108
+
),
109
+
]
110
+
"""
94
111
```
95
112
96
113
_(This example is complete, it can be run "as is" — you'll need to add `asyncio.run(main())` to run `main`)_
@@ -105,13 +122,13 @@ It also takes an optional `event_stream_handler` argument that you can use to ga
105
122
The example below shows how to stream events and text output. You can also [stream structured output](output.md#streaming-structured-output).
106
123
107
124
!!! note
108
-
As the `run_stream()` method will consider the first output matching the `output_type` to be the final output,
125
+
As the `run_stream()` method will consider the first output matching the [output type](output.md#structured-output) to be the final output,
109
126
it will stop running the agent graph and will not execute any tool calls made by the model after this "final" output.
110
127
111
128
If you want to always run the agent graph to completion and stream all events from the model's streaming response and the agent's execution of tools,
112
-
use [`agent.run()`][pydantic_ai.agent.AbstractAgent.run] with an `event_stream_handler` or [`agent.iter()`][pydantic_ai.agent.AbstractAgent.iter] instead, as described in the following sections.
129
+
use [`agent.run_stream_events()`][pydantic_ai.agent.AbstractAgent.run_stream_events] or [`agent.iter()`][pydantic_ai.agent.AbstractAgent.iter] instead, as described in the following sections.
output_messages.append(f'[Request] Starting part {event.index}: {event.part!r}')
170
+
elifisinstance(event, PartDeltaEvent):
171
+
ifisinstance(event.delta, TextPartDelta):
172
+
output_messages.append(f'[Request] Part {event.index} text delta: {event.delta.content_delta!r}')
173
+
elifisinstance(event.delta, ThinkingPartDelta):
174
+
output_messages.append(f'[Request] Part {event.index} thinking delta: {event.delta.content_delta!r}')
175
+
elifisinstance(event.delta, ToolCallPartDelta):
176
+
output_messages.append(f'[Request] Part {event.index} args delta: {event.delta.args_delta}')
177
+
elifisinstance(event, FunctionToolCallEvent):
178
+
output_messages.append(
179
+
f'[Tools] The LLM calls tool={event.part.tool_name!r} with args={event.part.args} (tool_call_id={event.part.tool_call_id!r})'
180
+
)
181
+
elifisinstance(event, FunctionToolResultEvent):
182
+
output_messages.append(f'[Tools] Tool call {event.tool_call_id!r} returned => {event.result.content}')
183
+
elifisinstance(event, FinalResultEvent):
184
+
output_messages.append(f'[Result] The model starting producing a final result (tool_name={event.tool_name})')
185
+
150
186
151
187
asyncdefevent_stream_handler(
152
188
ctx: RunContext,
153
189
event_stream: AsyncIterable[AgentStreamEvent],
154
190
):
155
191
asyncfor event in event_stream:
156
-
ifisinstance(event, PartStartEvent):
157
-
output_messages.append(f'[Request] Starting part {event.index}: {event.part!r}')
158
-
elifisinstance(event, PartDeltaEvent):
159
-
ifisinstance(event.delta, TextPartDelta):
160
-
output_messages.append(f'[Request] Part {event.index} text delta: {event.delta.content_delta!r}')
161
-
elifisinstance(event.delta, ThinkingPartDelta):
162
-
output_messages.append(f'[Request] Part {event.index} thinking delta: {event.delta.content_delta!r}')
163
-
elifisinstance(event.delta, ToolCallPartDelta):
164
-
output_messages.append(f'[Request] Part {event.index} args delta: {event.delta.args_delta}')
165
-
elifisinstance(event, FunctionToolCallEvent):
166
-
output_messages.append(
167
-
f'[Tools] The LLM calls tool={event.part.tool_name!r} with args={event.part.args} (tool_call_id={event.part.tool_call_id!r})'
168
-
)
169
-
elifisinstance(event, FunctionToolResultEvent):
170
-
output_messages.append(f'[Tools] Tool call {event.tool_call_id!r} returned => {event.result.content}')
171
-
elifisinstance(event, FinalResultEvent):
172
-
output_messages.append(f'[Result] The model starting producing a final result (tool_name={event.tool_name})')
173
-
192
+
await handle_event(event)
174
193
175
194
asyncdefmain():
176
195
user_prompt ='What will the weather be like in Paris on Tuesday?'
@@ -209,24 +228,29 @@ Like `agent.run_stream()`, [`agent.run()`][pydantic_ai.agent.AbstractAgent.run_s
209
228
argument that lets you stream all events from the model's streaming response and the agent's execution of tools.
210
229
Unlike `run_stream()`, it always runs the agent graph to completion even if text was received ahead of tool calls that looked like it could've been the final result.
211
230
231
+
For convenience, a [`agent.run_stream_events()`][pydantic_ai.agent.AbstractAgent.run_stream_events] method is also available as a wrapper around `run(event_stream_handler=...)`, which returns an async iterable of [`AgentStreamEvent`s][pydantic_ai.messages.AgentStreamEvent] and a [`AgentRunResultEvent`][pydantic_ai.run.AgentRunResultEvent] containing the final run result.
232
+
212
233
!!! note
213
-
When used with an `event_stream_handler`, the `run()`method currently requires you to piece together the streamed text yourself from the `PartStartEvent` and subsequent `PartDeltaEvent`s instead of providing a `stream_text()` convenience method.
234
+
As they return raw events as they come in, the `run_stream_events()`and `run(event_stream_handler=...)` methods require you to piece together the streamed text and structured output yourself from the `PartStartEvent` and subsequent `PartDeltaEvent`s.
214
235
215
236
To get the best of both worlds, at the expense of some additional complexity, you can use [`agent.iter()`][pydantic_ai.agent.AbstractAgent.iter] as described in the next section, which lets you [iterate over the agent graph](#iterating-over-an-agents-graph) and [stream both events and output](#streaming-all-events-and-output) at every step.
Copy file name to clipboardExpand all lines: docs/durable_execution/dbos.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -127,7 +127,7 @@ DBOS checkpoints workflow inputs/outputs and step outputs into a database using
127
127
128
128
### Streaming
129
129
130
-
Because DBOS cannot stream output directly to the workflow or step call site, [`Agent.run_stream()`][pydantic_ai.Agent.run_stream]is not supported when running inside of a DBOS workflow.
130
+
Because DBOS cannot stream output directly to the workflow or step call site, [`Agent.run_stream()`][pydantic_ai.Agent.run_stream]and [`Agent.run_stream_events()`][pydantic_ai.Agent.run_stream_events] are not supported when running inside of a DBOS workflow.
131
131
132
132
Instead, you can implement streaming by setting an [`event_stream_handler`][pydantic_ai.agent.EventStreamHandler] on the `Agent` or `DBOSAgent` instance and using [`DBOSAgent.run()`][pydantic_ai.durable_exec.dbos.DBOSAgent.run].
133
133
The event stream handler function will receive the agent [run context][pydantic_ai.tools.RunContext] and an async iterable of events from the model's streaming response and the agent's execution of tools. For examples, see the [streaming docs](../agents.md#streaming-all-events).
Copy file name to clipboardExpand all lines: docs/durable_execution/temporal.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -177,7 +177,7 @@ If you need one or more of these attributes to be available inside activities, y
177
177
178
178
### Streaming
179
179
180
-
Because Temporal activities cannot stream output directly to the activity call site, [`Agent.run_stream()`][pydantic_ai.Agent.run_stream] and [`Agent.iter()`][pydantic_ai.Agent.iter] are not supported.
180
+
Because Temporal activities cannot stream output directly to the activity call site, [`Agent.run_stream()`][pydantic_ai.Agent.run_stream], [`Agent.run_stream_events()`][pydantic_ai.Agent.run_stream_events], and [`Agent.iter()`][pydantic_ai.Agent.iter] are not supported.
181
181
182
182
Instead, you can implement streaming by setting an [`event_stream_handler`][pydantic_ai.agent.EventStreamHandler] on the `Agent` or `TemporalAgent` instance and using [`TemporalAgent.run()`][pydantic_ai.durable_exec.temporal.TemporalAgent.run] inside the workflow.
183
183
The event stream handler function will receive the agent [run context][pydantic_ai.tools.RunContext] and an async iterable of events from the model's streaming response and the agent's execution of tools. For examples, see the [streaming docs](../agents.md#streaming-all-events).
Copy file name to clipboardExpand all lines: docs/output.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -520,7 +520,7 @@ There two main challenges with streamed results:
520
520
it will stop running the agent graph and will not execute any tool calls made by the model after this "final" output.
521
521
522
522
If you want to always run the agent graph to completion and stream all events from the model's streaming response and the agent's execution of tools,
523
-
use [`agent.run()`][pydantic_ai.agent.AbstractAgent.run] with an `event_stream_handler` ([docs](agents.md#streaming-all-events)) or [`agent.iter()`][pydantic_ai.agent.AbstractAgent.iter] ([docs](agents.md#streaming-all-events-and-output)) instead.
523
+
use [`agent.run_stream_events()`][pydantic_ai.agent.AbstractAgent.run_stream_events] ([docs](agents.md#streaming-all-events)) or [`agent.iter()`][pydantic_ai.agent.AbstractAgent.iter] ([docs](agents.md#streaming-all-events-and-output)) instead.
0 commit comments