Skip to content

Commit f997d83

Browse files
committed
Add documentation for the agent's validation context
1 parent 343b0cc commit f997d83

File tree

1 file changed

+60
-4
lines changed

1 file changed

+60
-4
lines changed

docs/output.md

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,62 @@ print(repr(result.output))
385385

386386
_(This example is complete, it can be run "as is")_
387387

388+
### Validation context {#validation-context}
389+
390+
Some validation relies on an extra Pydantic [context](https://docs.pydantic.dev/latest/concepts/validators/#validation-context) object. You can pass such an object to an `Agent` at definition-time via its [`validation_context`][pydantic_ai.Agent.__init__] parameter.
391+
392+
This validation context is used for the validation of _all_ structured outputs. It can be either:
393+
394+
- the context object itself (`Any`), used as-is to validate outputs, or
395+
- a function that takes the [`RunContext`][pydantic_ai.tools.RunContext] and returns a context object (`Any`). This function will be called automatically before each validation, allowing you to build a dynamic validation context.
396+
397+
!!! warning "Don't confuse this _validation_ context with the _LLM_ context"
398+
This Pydantic [context](https://docs.pydantic.dev/latest/concepts/validators/#validation-data) object is only used internally by Pydantic AI for output validation. In particular, it is **not** included in the prompts or messages sent to the language model.
399+
400+
```python {title="validation_context.py"}
401+
from dataclasses import dataclass
402+
403+
from pydantic import BaseModel, ValidationInfo, field_validator
404+
405+
from pydantic_ai import Agent
406+
407+
408+
class Value(BaseModel):
409+
x: int
410+
411+
@field_validator('x')
412+
def increment_value(cls, value: int, info: ValidationInfo):
413+
return value + (info.context or 0)
414+
415+
416+
agent = Agent(
417+
'google-gla:gemini-2.5-flash',
418+
output_type=Value,
419+
validation_context=10,
420+
)
421+
result = agent.run_sync('Give me a value of 5.')
422+
print(repr(result.output)) # 5 from the model + 10 from the validation context
423+
#> Value(x=15)
424+
425+
426+
@dataclass
427+
class Deps:
428+
increment: int
429+
430+
431+
agent = Agent(
432+
'google-gla:gemini-2.5-flash',
433+
output_type=Value,
434+
deps_type=Deps,
435+
validation_context=lambda ctx: ctx.deps.increment,
436+
)
437+
result = agent.run_sync('Give me a value of 5.', deps=Deps(increment=10))
438+
print(repr(result.output)) # 5 from the model + 10 from the validation context
439+
#> Value(x=15)
440+
```
441+
442+
_(This example is complete, it can be run "as is")_
443+
388444
### Custom JSON schema {#structured-dict}
389445

390446
If it's not feasible to define your desired structured output object using a Pydantic `BaseModel`, dataclass, or `TypedDict`, for example when you get a JSON schema from an external source or generate it dynamically, you can use the [`StructuredDict()`][pydantic_ai.output.StructuredDict] helper function to generate a `dict[str, Any]` subclass with a JSON schema attached that Pydantic AI will pass to the model.
@@ -550,8 +606,8 @@ There two main challenges with streamed results:
550606
2. When receiving a response, we don't know if it's the final response without starting to stream it and peeking at the content. Pydantic AI streams just enough of the response to sniff out if it's a tool call or an output, then streams the whole thing and calls tools, or returns the stream as a [`StreamedRunResult`][pydantic_ai.result.StreamedRunResult].
551607

552608
!!! note
553-
As the `run_stream()` method will consider the first output matching the `output_type` to be the final output,
554-
it will stop running the agent graph and will not execute any tool calls made by the model after this "final" output.
609+
As the `run_stream()` method will consider the first output matching the `output_type` to be the final output,
610+
it will stop running the agent graph and will not execute any tool calls made by the model after this "final" output.
555611

556612
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,
557613
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.
@@ -609,8 +665,8 @@ async def main():
609665
_(This example is complete, it can be run "as is" — you'll need to add `asyncio.run(main())` to run `main`)_
610666

611667
!!! warning "Output message not included in `messages`"
612-
The final output message will **NOT** be added to result messages if you use `.stream_text(delta=True)`,
613-
see [Messages and chat history](message-history.md) for more information.
668+
The final output message will **NOT** be added to result messages if you use `.stream_text(delta=True)`,
669+
see [Messages and chat history](message-history.md) for more information.
614670

615671
### Streaming Structured Output
616672

0 commit comments

Comments
 (0)