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
+133-7Lines changed: 133 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -62,13 +62,14 @@ print(result.data)
62
62
63
63
## Running Agents
64
64
65
-
There are three ways to run an agent:
65
+
There are four ways to run an agent:
66
66
67
-
1.[`agent.run()`][pydantic_ai.Agent.run] — a coroutine which returns a [`RunResult`][pydantic_ai.result.RunResult] containing a completed response
68
-
2.[`agent.run_sync()`][pydantic_ai.Agent.run_sync] — a plain, synchronous function which returns a [`RunResult`][pydantic_ai.result.RunResult] containing a completed response (internally, this just calls `loop.run_until_complete(self.run())`)
69
-
3.[`agent.run_stream()`][pydantic_ai.Agent.run_stream] — a coroutine which returns a [`StreamedRunResult`][pydantic_ai.result.StreamedRunResult], which contains methods to stream a response as an async iterable
67
+
1.[`agent.run()`][pydantic_ai.Agent.run] — a coroutine which returns a [`RunResult`][pydantic_ai.agent.AgentRunResult] containing a completed response.
68
+
2.[`agent.run_sync()`][pydantic_ai.Agent.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())`).
69
+
3.[`agent.run_stream()`][pydantic_ai.Agent.run_stream] — a coroutine which returns a [`StreamedRunResult`][pydantic_ai.result.StreamedRunResult], which contains methods to stream a response as an async iterable.
70
+
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].
70
71
71
-
Here's a simple example demonstrating all three:
72
+
Here's a simple example demonstrating the first three:
72
73
73
74
```python {title="run_agent.py"}
74
75
from pydantic_ai import Agent
@@ -94,6 +95,131 @@ _(This example is complete, it can be run "as is" — you'll need to add `asynci
94
95
You can also pass messages from previous runs to continue a conversation or provide context, as described in [Messages and Chat History](message-history.md).
95
96
96
97
98
+
### Iterating Over an Agent's Graph
99
+
100
+
Under the hood, each `Agent` in PydanticAI uses **pydantic-graph** to manage its execution flow. **pydantic-graph** is a generic, type-centric library for building and running finite state machines in Python. It doesn't actually depend on PydanticAI — you can use it standalone for workflows that have nothing to do with GenAI — but PydanticAI makes use of it to orchestrate the handling of model requests and model responses in an agent's run.
101
+
102
+
In many scenarios, you don't need to worry about pydantic-graph at all; calling `agent.run(...)` simply traverses the underlying graph from start to finish. However, if you need deeper insight or control — for example to capture each tool invocation, or to inject your own logic at specific stages — PydanticAI exposes the lower-level iteration process via [`Agent.iter`][pydantic_ai.Agent.iter]. This method returns an [`AgentRun`][pydantic_ai.agent.AgentRun], which you can async-iterate over, or manually drive node-by-node via the [`next`][pydantic_ai.agent.AgentRun.next] method. Once the agent's graph returns an [`End`][pydantic_graph.nodes.End], you have the final result along with a detailed history of all steps.
103
+
104
+
#### `async for` iteration
105
+
106
+
Here's an example of using `async for` with `iter` to record each node the agent executes:
107
+
108
+
```python {title="agent_iter_async_for.py"}
109
+
from pydantic_ai import Agent
110
+
111
+
agent = Agent('openai:gpt-4o')
112
+
113
+
114
+
asyncdefmain():
115
+
nodes = []
116
+
# Begin an AgentRun, which is an async-iterable over the nodes of the agent's graph
117
+
with agent.iter('What is the capital of France?') as agent_run:
118
+
asyncfor node in agent_run:
119
+
# Each node represents a step in the agent's execution
- The `AgentRun` is an async iterator that yields each node (`BaseNode` or `End`) in the flow.
152
+
- The run ends when an `End` node is returned.
153
+
154
+
#### Using `.next(...)` manually
155
+
156
+
You can also drive the iteration manually by passing the node you want to run next to the `AgentRun.next(...)` method. This allows you to inspect or modify the node before it executes or skip nodes based on your own logic, and to catch errors in `next()` more easily:
157
+
158
+
```python {title="agent_iter_next.py"}
159
+
from pydantic_ai import Agent
160
+
from pydantic_graph import End
161
+
162
+
agent = Agent('openai:gpt-4o')
163
+
164
+
165
+
asyncdefmain():
166
+
with agent.iter('What is the capital of France?') as agent_run:
1. We start by grabbing the first node that will be run in the agent's graph.
211
+
2. The agent run is finished once an `End` node has been produced; instances of `End` cannot be passed to `next`.
212
+
3. When you call `await agent_run.next(node)`, it executes that node in the agent's graph, updates the run's history, and returns the *next* node to run.
213
+
4. You could also inspect or mutate the new `node` here as needed.
214
+
215
+
#### Accessing usage and the final result
216
+
217
+
You can retrieve usage statistics (tokens, requests, etc.) at any time from the [`AgentRun`][pydantic_ai.agent.AgentRun] object via `agent_run.usage()`. This method returns a [`Usage`][pydantic_ai.usage.Usage] object containing the usage data.
218
+
219
+
Once the run finishes, `agent_run.final_result` becomes a [`AgentRunResult`][pydantic_ai.agent.AgentRunResult] object containing the final output (and related metadata).
220
+
221
+
---
222
+
97
223
### Additional Configuration
98
224
99
225
#### Usage Limits
@@ -177,7 +303,7 @@ except UsageLimitExceeded as e:
177
303
2. This run will error after 3 requests, preventing the infinite tool calling.
178
304
179
305
!!! note
180
-
This is especially relevant if you're registered a lot of tools, `request_limit` can be used to prevent the model from choosing to make too many of these calls.
306
+
This is especially relevant if you've registered many tools. The `request_limit` can be used to prevent the model from calling them in a loop too many times.
181
307
182
308
#### Model (Run) Settings
183
309
@@ -441,7 +567,7 @@ If models behave unexpectedly (e.g., the retry limit is exceeded, or their API r
441
567
442
568
In these cases, [`capture_run_messages`][pydantic_ai.capture_run_messages] can be used to access the messages exchanged during the run to help diagnose the issue.
443
569
444
-
```python
570
+
```python {title="agent_model_errors.py"}
445
571
from pydantic_ai import Agent, ModelRetry, UnexpectedModelBehavior, capture_run_messages
0 commit comments