Fix broken in-page docs links and check heading anchors in CI (#7693)

This commit is contained in:
David SF
2026-08-22 15:10:55 -05:00
committed by GitHub
parent 4fda38988f
commit 66f10d85fa
71 changed files with 199 additions and 172 deletions
+2 -2
View File
@@ -29,7 +29,7 @@ body:
Please explain what you're seeing and what you would expect to see.
- **A line of code is worth a thousand words**: you can include minimal, reproducible example code below.
- **A trace is worth a thousand log lines**: you can link to a [Pydantic Logfire](https://ai.pydantic.dev/logfire) trace below.
- **A trace is worth a thousand log lines**: you can link to a [Pydantic Logfire](https://pydantic.dev/docs/ai/integrations/logfire/) trace below.
validations:
required: true
@@ -55,7 +55,7 @@ body:
attributes:
label: Logfire Trace
description: >
If at all possible, please capture the agent run or model request leading up to the bug or error using [Pydantic Logfire](https://ai.pydantic.dev/logfire)
If at all possible, please capture the agent run or model request leading up to the bug or error using [Pydantic Logfire](https://pydantic.dev/docs/ai/integrations/logfire/)
and share a link to the [public trace](https://logfire.pydantic.dev/docs/guides/web-ui/public-traces/) here.
- type: textarea
+2 -2
View File
@@ -1,6 +1,6 @@
<!-- Thank you for contributing to Pydantic AI! -->
<!-- Please read the contributing guide: https://ai.pydantic.dev/contributing/ -->
<!-- Please read the contributing guide: https://pydantic.dev/docs/ai/project/contributing/ -->
<!-- For non-trivial changes, link an issue that a maintainer has agreed on -->
<!-- and assigned to you. Unassigned PRs may be auto-closed. -->
@@ -16,7 +16,7 @@
<!-- > **Migration:** ... -->
<!-- Adding a capability? Most capabilities belong in Pydantic AI Harness, not here. -->
<!-- See: https://pydantic.dev/docs/ai/harness/#what-goes-where -->
<!-- See: https://pydantic.dev/docs/ai/harness/#when-do-you-need-the-harness -->
- Closes #<issue>
+9
View File
@@ -197,6 +197,15 @@ jobs:
# Check all documentation images are tinified. You will need a Tinify API key to fix failures.
- run: uvx tinicly docs --check
# Check that links between doc pages resolve, including their `#anchor` fragments. Runs
# `--offline` so only local files are checked: external hosts are swept weekly by
# link-check.yml instead, where being down doesn't block a PR.
- name: Check doc links and heading anchors
uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0
with:
args: --no-progress --offline --include-fragments --config .github/workflows/lychee.toml './docs/**/*.md' './*.md' './examples/**/*.md'
fail: true
test:
name: test on ${{ matrix.python-version }} (${{ matrix.install.name }})
# Use Ubicloud 4-core runners for all-extras (the slowest variant) when run by maintainers or opted in via 'ci:fast' label
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
id: lychee
uses: lycheeverse/lychee-action@8646ba30535128ac92d33dfc9133794bfdd9b411 # v2.8.0
with:
args: --no-progress --config .github/workflows/lychee.toml './docs/**/*.md' './*.md'
args: --no-progress --config .github/workflows/lychee.toml './docs/**/*.md' './*.md' './examples/**/*.md'
fail: false
- name: Open issue on broken links
+18 -6
View File
@@ -1,6 +1,8 @@
# Configuration for the scheduled docs link check (see link-check.yml).
# Tuned to avoid false positives from sites that block bots or rate-limit, so the
# issue it opens only lists genuinely broken links.
# Configuration for the docs link check, shared by the PR gate in ci.yml (`docs-assets`,
# run with `--offline` so only local files are checked) and the scheduled external-link
# sweep in link-check.yml.
# Tuned to avoid false positives from sites that block bots or rate-limit, so the issue
# the scheduled sweep opens only lists genuinely broken links.
# Some sites return 403/429 to non-browser clients even though the link is fine.
accept = ["200..=299", "403", "429"]
@@ -17,9 +19,19 @@ timeout = 30
exclude_all_private = true
exclude_loopback = true
# Relative doc links are resolved by the documentation renderer, not as filesystem paths; skip the
# `file://` links lychee derives from them.
scheme = ["https", "http"]
# No `scheme` allowlist: relative links between doc pages resolve as filesystem paths, and skipping
# them is how a page's worth of dead in-page anchors shipped unnoticed. The rule for keeping heading
# anchors resolvable lives in `docs/AGENTS.md`, with the rest of the doc-authoring conventions.
#
# The PR gate adds `--include-fragments` on the command line rather than setting the key here: the
# config key's type changed between lychee releases while the flag did not, and the gate is the only
# consumer that wants it. The weekly sweep deliberately checks pages but not fragments -- roughly a
# third of the docs' external anchors are rendered client-side or are GitHub line ranges, so remote
# fragment checking reports them as broken and would bury the real hits in the issue it files.
# `CONTRIBUTING.md` is a symlink to `docs/contributing.md`, so its relative links resolve from
# `docs/` and not from the repository root. The file is checked at its real path.
exclude_path = ["CONTRIBUTING.md"]
# Login-gated or bot-blocking hosts that return non-2xx to automated checks even
# though the links are valid in a browser; not worth failing the run over.
+1 -1
View File
@@ -1,4 +1,4 @@
Welcome to the repository for [Pydantic AI](https://ai.pydantic.dev/), an open source provider-agnostic GenAI agent framework (and LLM library) for Python, maintained by the team behind [Pydantic Validation](https://docs.pydantic.dev/) and [Pydantic Logfire](https://docs.pydantic.dev/logfire/).
Welcome to the repository for [Pydantic AI](https://pydantic.dev/docs/ai/), an open source provider-agnostic GenAI agent framework (and LLM library) for Python, maintained by the team behind [Pydantic Validation](https://docs.pydantic.dev/) and [Pydantic Logfire](https://docs.pydantic.dev/logfire/).
# Your primary responsibility is to the project and its users
+1 -1
View File
@@ -18,7 +18,7 @@ authors:
- family-names: Colvin
given-names: Samuel
repository-code: 'https://github.com/pydantic/pydantic-ai'
url: 'https://ai.pydantic.dev'
url: 'https://pydantic.dev/docs/ai/'
abstract: >-
Pydantic AI is a Python agent framework designed to make it less
painful to build production grade applications and workflows with
+34 -34
View File
@@ -1,5 +1,5 @@
<div align="center">
<a href="https://ai.pydantic.dev/">
<a href="https://pydantic.dev/docs/ai/">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://pydantic.dev/docs/ai/img/pydantic-ai-dark.svg">
<img src="https://pydantic.dev/docs/ai/img/pydantic-ai-light.svg" alt="Pydantic AI">
@@ -23,11 +23,11 @@
---
**Pydantic AI** is the Python AI SDK: a typed, [extensible](https://ai.pydantic.dev/extensibility) agent loop with [every model](https://ai.pydantic.dev/models/overview) a string swap away. The same agent [runs everywhere you need it](https://ai.pydantic.dev/interfaces): behind a [web frontend](https://ai.pydantic.dev/ui/overview), in the [terminal](https://ai.pydantic.dev/cli), on a [voice call](https://ai.pydantic.dev/realtime), on a [durable background queue](https://ai.pydantic.dev/durable_execution/overview/), or as a plain object you call [`run()`](https://ai.pydantic.dev/agents/#running-agents) on. [Image generation](https://ai.pydantic.dev/capabilities/image-generation/) and [embeddings](https://ai.pydantic.dev/embeddings) come in the same box.
**Pydantic AI** is the Python AI SDK: a typed, [extensible](https://pydantic.dev/docs/ai/guides/extensibility/) agent loop with [every model](https://pydantic.dev/docs/ai/models/overview/) a string swap away. The same agent [runs everywhere you need it](https://pydantic.dev/docs/ai/overview/interfaces/): behind a [web frontend](https://pydantic.dev/docs/ai/integrations/ui/overview/), in the [terminal](https://pydantic.dev/docs/ai/integrations/cli/), on a [voice call](https://pydantic.dev/docs/ai/realtime/overview/), on a [durable background queue](https://pydantic.dev/docs/ai/capabilities/durable_execution/overview/), or as a plain object you call [`run()`](https://pydantic.dev/docs/ai/core-concepts/agent/#running-agents) on. [Image generation](https://pydantic.dev/docs/ai/capabilities/image-generation/) and [embeddings](https://pydantic.dev/docs/ai/guides/embeddings/) come in the same box.
**[Pydantic AI Harness](https://github.com/pydantic/pydantic-ai-harness)** has everything an agent needs for complex, long-running work, snapped on as [capabilities](https://ai.pydantic.dev/capabilities/overview/), from [memory](https://pydantic.dev/docs/ai/harness/memory/), [sub-agents](https://pydantic.dev/docs/ai/harness/subagents/), and [context management](https://pydantic.dev/docs/ai/harness/compaction/) to a complete [coding agent](https://pydantic.dev/docs/ai/harness/coder/).
**[Pydantic AI Harness](https://github.com/pydantic/pydantic-ai-harness)** has everything an agent needs for complex, long-running work, snapped on as [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/), from [memory](https://pydantic.dev/docs/ai/harness/memory/), [sub-agents](https://pydantic.dev/docs/ai/harness/subagents/), and [context management](https://pydantic.dev/docs/ai/harness/compaction/) to a complete [coding agent](https://pydantic.dev/docs/ai/harness/coder/).
View the complete documentation at [ai.pydantic.dev](https://ai.pydantic.dev/).
View the complete documentation at [pydantic.dev/docs/ai](https://pydantic.dev/docs/ai/).
## What are you building?
@@ -35,7 +35,7 @@ From simple typed data extraction to complex, long-running multi-agent collabora
### Coding agent
A complete coding agent in your terminal: workspace-rooted [file access](https://pydantic.dev/docs/ai/harness/filesystem/), allowlisted [shell](https://pydantic.dev/docs/ai/harness/shell/), [repo orientation](https://pydantic.dev/docs/ai/harness/repo-context/), [planning](https://pydantic.dev/docs/ai/harness/planning/), and [context management](https://pydantic.dev/docs/ai/harness/compaction/) that survives long sessions. Here with [web search](https://ai.pydantic.dev/capabilities/web-search/) and a second-opinion [advisor](https://pydantic.dev/docs/ai/harness/advisor/) snapped on alongside:
A complete coding agent in your terminal: workspace-rooted [file access](https://pydantic.dev/docs/ai/harness/filesystem/), allowlisted [shell](https://pydantic.dev/docs/ai/harness/shell/), [repo orientation](https://pydantic.dev/docs/ai/harness/repo-context/), [planning](https://pydantic.dev/docs/ai/harness/planning/), and [context management](https://pydantic.dev/docs/ai/harness/compaction/) that survives long sessions. Here with [web search](https://pydantic.dev/docs/ai/capabilities/web-search/) and a second-opinion [advisor](https://pydantic.dev/docs/ai/harness/advisor/) snapped on alongside:
```bash
uv add pydantic-ai pydantic-ai-harness
@@ -57,7 +57,7 @@ agent = Agent(
agent.to_cli_sync()
```
[`Coder`](https://pydantic.dev/docs/ai/harness/coder/) is a regular [combined capability](https://ai.pydantic.dev/capabilities/custom/#composition-and-middleware-semantics), not a black box: use it whole, or use the blocks it bundles directly; the two are equivalent:
[`Coder`](https://pydantic.dev/docs/ai/harness/coder/) is a regular [combined capability](https://pydantic.dev/docs/ai/capabilities/custom/#composition-and-middleware-semantics), not a black box: use it whole, or use the blocks it bundles directly; the two are equivalent:
```python
capabilities = [
@@ -66,7 +66,7 @@ capabilities = [
]
```
Run the file and you're chatting with the agent in your terminal. To try it before writing any code, run the exported [`coder_agent`](https://pydantic.dev/docs/ai/harness/coder/) with [`clai`](https://ai.pydantic.dev/cli#custom-agents) (the Pydantic AI CLI), via [`uvx`](https://docs.astral.sh/uv/guides/tools/):
Run the file and you're chatting with the agent in your terminal. To try it before writing any code, run the exported [`coder_agent`](https://pydantic.dev/docs/ai/harness/coder/) with [`clai`](https://pydantic.dev/docs/ai/integrations/cli/#custom-agents) (the Pydantic AI CLI), via [`uvx`](https://docs.astral.sh/uv/guides/tools/):
```bash
uvx --with pydantic-ai-harness clai -a pydantic_ai_harness.coder:coder_agent -m anthropic:claude-fable-5
@@ -76,7 +76,7 @@ uvx --with pydantic-ai-harness clai -a pydantic_ai_harness.coder:coder_agent -m
### Data extraction
Give the agent an [output type](https://ai.pydantic.dev/output) and [tools](https://ai.pydantic.dev/tools), and every run comes back validated and typed:
Give the agent an [output type](https://pydantic.dev/docs/ai/core-concepts/output/) and [tools](https://pydantic.dev/docs/ai/tools-toolsets/tools/), and every run comes back validated and typed:
```bash
uv add pydantic-ai
@@ -109,13 +109,13 @@ print(result.output)
#> label='positive' score=0.9
```
The [`@agent.tool`](https://ai.pydantic.dev/tools) function receives a [`RunContext`](https://ai.pydantic.dev/dependencies) that carries your dependencies in; the rest of its signature and its docstring become the tool schema, arguments are validated before your code runs, and the run is guaranteed to return a `Sentiment`, so your IDE, type checker, and the LLM all agree on the returned type.
The [`@agent.tool`](https://pydantic.dev/docs/ai/tools-toolsets/tools/) function receives a [`RunContext`](https://pydantic.dev/docs/ai/core-concepts/dependencies/) that carries your dependencies in; the rest of its signature and its docstring become the tool schema, arguments are validated before your code runs, and the run is guaranteed to return a `Sentiment`, so your IDE, type checker, and the LLM all agree on the returned type.
**Build this →** [Agents](https://ai.pydantic.dev/agents/), [Function Tools](https://ai.pydantic.dev/tools), and [Structured Output](https://ai.pydantic.dev/output)
**Build this →** [Agents](https://pydantic.dev/docs/ai/core-concepts/agent/), [Function Tools](https://pydantic.dev/docs/ai/tools-toolsets/tools/), and [Structured Output](https://pydantic.dev/docs/ai/core-concepts/output/)
### Realtime voice
Put the same agent on a live voice session, [tools](https://ai.pydantic.dev/realtime/tools) and [capabilities](https://ai.pydantic.dev/realtime/capabilities) included:
Put the same agent on a live voice session, [tools](https://pydantic.dev/docs/ai/realtime/tools/) and [capabilities](https://pydantic.dev/docs/ai/realtime/capabilities/) included:
```bash
uv add "pydantic-ai[openai-realtime]"
@@ -144,13 +144,13 @@ async with agent.realtime('openai:gpt-realtime-2.1').session() as session:
print(f'{part.speaker}: {part.transcript}')
```
The model calls your tools mid-conversation while it keeps talking, and every session is [instrumented](https://ai.pydantic.dev/logfire); voice is just another frontend, on OpenAI Realtime, Gemini Live, Azure, and xAI Grok Voice.
The model calls your tools mid-conversation while it keeps talking, and every session is [instrumented](https://pydantic.dev/docs/ai/integrations/logfire/); voice is just another frontend, on OpenAI Realtime, Gemini Live, Azure, and xAI Grok Voice.
**Build this →** [Realtime Voice](https://ai.pydantic.dev/realtime)
**Build this →** [Realtime Voice](https://pydantic.dev/docs/ai/realtime/overview/)
### Durable background agent
Attach [`TemporalDurability`](https://ai.pydantic.dev/durable_execution/temporal/) and the same agent runs inside a [Temporal](https://ai.pydantic.dev/durable_execution/temporal/) workflow: every model and tool call becomes a durable activity, so a run working through a background queue survives restarts, failures, and long waits:
Attach [`TemporalDurability`](https://pydantic.dev/docs/ai/capabilities/durable_execution/temporal/) and the same agent runs inside a [Temporal](https://pydantic.dev/docs/ai/capabilities/durable_execution/temporal/) workflow: every model and tool call becomes a durable activity, so a run working through a background queue survives restarts, failures, and long waits:
```bash
uv add "pydantic-ai[temporal]"
@@ -181,13 +181,13 @@ class ResearchWorkflow(PydanticAIWorkflow):
return result.output
```
[DBOS](https://ai.pydantic.dev/durable_execution/dbos/) and [Prefect](https://ai.pydantic.dev/durable_execution/prefect/) attach the same way, first-party and co-maintained, with [Restate, Kitaru, and Airflow](https://ai.pydantic.dev/durable_execution/overview/) integrations besides.
[DBOS](https://pydantic.dev/docs/ai/capabilities/durable_execution/dbos/) and [Prefect](https://pydantic.dev/docs/ai/capabilities/durable_execution/prefect/) attach the same way, first-party and co-maintained, with [Restate, Kitaru, and Airflow](https://pydantic.dev/docs/ai/capabilities/durable_execution/overview/) integrations besides.
**Build this →** [Durable Execution](https://ai.pydantic.dev/durable_execution/overview/)
**Build this →** [Durable Execution](https://pydantic.dev/docs/ai/capabilities/durable_execution/overview/)
### Image generation
Ask for an image and make it the run's typed [output](https://ai.pydantic.dev/output):
Ask for an image and make it the run's typed [output](https://pydantic.dev/docs/ai/core-concepts/output/):
```bash
uv add pydantic-ai
@@ -203,15 +203,15 @@ result = agent.run_sync('Generate a minimalist logo for a coffee shop called Ext
Path('logo.png').write_bytes(result.output.data)
```
[Provider-native generation](https://ai.pydantic.dev/native-tools#image-generation-tool) on models that support it (like this one), a [subagent fallback](https://ai.pydantic.dev/capabilities/image-generation/) you can configure for the rest, and a [standalone image API](https://github.com/pydantic/pydantic-ai/pull/5357) on the way.
[Provider-native generation](https://pydantic.dev/docs/ai/tools-toolsets/native-tools/#image-generation-tool) on models that support it (like this one), a [subagent fallback](https://pydantic.dev/docs/ai/capabilities/image-generation/) you can configure for the rest, and a [standalone image API](https://github.com/pydantic/pydantic-ai/pull/5357) on the way.
**Build this →** [Image Generation](https://ai.pydantic.dev/capabilities/image-generation/)
**Build this →** [Image Generation](https://pydantic.dev/docs/ai/capabilities/image-generation/)
<!-- Embeddings section parked (bd54): restore by removing this comment.
### Embeddings
Embed documents and queries for semantic search or a [RAG pipeline](https://ai.pydantic.dev/examples/rag):
Embed documents and queries for semantic search or a [RAG pipeline](https://pydantic.dev/docs/ai/examples/data-analytics/rag/):
```python
from pydantic_ai import Embedder
@@ -222,31 +222,31 @@ print(len(result.embeddings[0]))
#> 1536
```
Seven providers behind one typed API, [instrumented](https://ai.pydantic.dev/logfire) like everything else. It lives next to the agent that will use the results.
Seven providers behind one typed API, [instrumented](https://pydantic.dev/docs/ai/integrations/logfire/) like everything else. It lives next to the agent that will use the results.
**Build this →** [Embeddings](https://ai.pydantic.dev/embeddings)
**Build this →** [Embeddings](https://pydantic.dev/docs/ai/guides/embeddings/)
-->
## Why Pydantic AI
- **Any model, one Python API.** [Virtually every model and provider](https://ai.pydantic.dev/models/overview) (OpenAI, Anthropic, Google, Bedrock, Azure AI Foundry, Groq, Mistral, xAI, Ollama, and dozens more), swappable with a string, or through the [Pydantic AI Gateway](https://ai.pydantic.dev/gateway): one key for all of them, with failover and cost monitoring built in. No flagship feature is locked to one vendor.
- **Any model, one Python API.** [Virtually every model and provider](https://pydantic.dev/docs/ai/models/overview/) (OpenAI, Anthropic, Google, Bedrock, Azure AI Foundry, Groq, Mistral, xAI, Ollama, and dozens more), swappable with a string, or through the [Pydantic AI Gateway](https://pydantic.dev/docs/ai/overview/gateway/): one key for all of them, with failover and cost monitoring built in. No flagship feature is locked to one vendor.
- **Typed end to end.** [Structured outputs](https://ai.pydantic.dev/output), typed [dependency injection](https://ai.pydantic.dev/dependencies), [typed tools](https://ai.pydantic.dev/tools): your IDE, type checker, and coding agent all know what your agent returns, moving whole classes of errors from runtime to write-time. When plain control flow isn't enough, [Pydantic Graph](https://ai.pydantic.dev/graph) brings the same typing to graph-based workflows.
- **Typed end to end.** [Structured outputs](https://pydantic.dev/docs/ai/core-concepts/output/), typed [dependency injection](https://pydantic.dev/docs/ai/core-concepts/dependencies/), [typed tools](https://pydantic.dev/docs/ai/tools-toolsets/tools/): your IDE, type checker, and coding agent all know what your agent returns, moving whole classes of errors from runtime to write-time. When plain control flow isn't enough, [Pydantic Graph](https://pydantic.dev/docs/ai/graph/graph/) brings the same typing to graph-based workflows.
- **Measured, not vibes.** OpenTelemetry-native [instrumentation](https://ai.pydantic.dev/logfire) works with any OTel backend; one line lights up [Pydantic Logfire](https://pydantic.dev/logfire/llm-observability?utm_source=github&utm_medium=readme&utm_campaign=pydantic-ai) for real-time debugging, tracing, and cost tracking backed by [genai-prices](https://github.com/pydantic/genai-prices). [Pydantic Evals](https://ai.pydantic.dev/evals) tests agent behavior the way pytest tests code.
- **Measured, not vibes.** OpenTelemetry-native [instrumentation](https://pydantic.dev/docs/ai/integrations/logfire/) works with any OTel backend; one line lights up [Pydantic Logfire](https://pydantic.dev/logfire/llm-observability?utm_source=github&utm_medium=readme&utm_campaign=pydantic-ai) for real-time debugging, tracing, and cost tracking backed by [genai-prices](https://github.com/pydantic/genai-prices). [Pydantic Evals](https://pydantic.dev/docs/ai/evals/evals/) tests agent behavior the way pytest tests code.
- **Batteries, composably.** One primitive, the [capability](https://ai.pydantic.dev/capabilities/overview/), bundles [tools](https://ai.pydantic.dev/tools), [instructions](https://ai.pydantic.dev/agents/#instructions), [hooks](https://ai.pydantic.dev/hooks), and [model settings](https://ai.pydantic.dev/agents/#model-run-settings) into reusable units. Core ships fundamentals like [MCP](https://ai.pydantic.dev/capabilities/mcp/) and [web search](https://ai.pydantic.dev/capabilities/web-search/), the [Harness](https://github.com/pydantic/pydantic-ai-harness) ships everything else, and complete agents like [Coder](https://pydantic.dev/docs/ai/harness/coder/) and [Researcher](https://pydantic.dev/docs/ai/harness/researcher/) are just capabilities composed: they come apart the way they went together. Or skip code entirely with [YAML/JSON agent specs](https://ai.pydantic.dev/agent-spec).
- **Batteries, composably.** One primitive, the [capability](https://pydantic.dev/docs/ai/capabilities/overview/), bundles [tools](https://pydantic.dev/docs/ai/tools-toolsets/tools/), [instructions](https://pydantic.dev/docs/ai/core-concepts/agent/#instructions), [hooks](https://pydantic.dev/docs/ai/core-concepts/hooks/), and [model settings](https://pydantic.dev/docs/ai/core-concepts/agent/#model-run-settings) into reusable units. Core ships fundamentals like [MCP](https://pydantic.dev/docs/ai/capabilities/mcp/) and [web search](https://pydantic.dev/docs/ai/capabilities/web-search/), the [Harness](https://github.com/pydantic/pydantic-ai-harness) ships everything else, and complete agents like [Coder](https://pydantic.dev/docs/ai/harness/coder/) and [Researcher](https://pydantic.dev/docs/ai/harness/researcher/) are just capabilities composed: they come apart the way they went together. Or skip code entirely with [YAML/JSON agent specs](https://pydantic.dev/docs/ai/core-concepts/agent-spec/).
- **[Every interface](https://ai.pydantic.dev/interfaces).** One agent definition runs as a [CLI](https://ai.pydantic.dev/cli), a [built-in web chat](https://ai.pydantic.dev/web), or [realtime speech](https://ai.pydantic.dev/realtime) (OpenAI Realtime, Gemini Live, Azure, xAI Grok Voice); [UI event streams](https://ai.pydantic.dev/ui/overview) (AG-UI, Vercel AI) connect it to your own frontend or anything else; and [ACP](https://pydantic.dev/docs/ai/harness/acp/) *(experimental)* serves it as an editor agent.
- **[Every interface](https://pydantic.dev/docs/ai/overview/interfaces/).** One agent definition runs as a [CLI](https://pydantic.dev/docs/ai/integrations/cli/), a [built-in web chat](https://pydantic.dev/docs/ai/guides/web/), or [realtime speech](https://pydantic.dev/docs/ai/realtime/overview/) (OpenAI Realtime, Gemini Live, Azure, xAI Grok Voice); [UI event streams](https://pydantic.dev/docs/ai/integrations/ui/overview/) (AG-UI, Vercel AI) connect it to your own frontend or anything else; and [ACP](https://pydantic.dev/docs/ai/harness/acp/) *(experimental)* serves it as an editor agent.
- **Durable execution.** First-party, co-maintained [durable execution](https://ai.pydantic.dev/durable_execution/overview/) on Temporal, DBOS, or Prefect, with [Restate, Kitaru, and Airflow](https://ai.pydantic.dev/durable_execution/overview/) integrations and more coming. Agents survive restarts and run for days on the engine you already operate, with [human-in-the-loop approval](https://ai.pydantic.dev/deferred-tools#human-in-the-loop-tool-approval) built in.
- **Durable execution.** First-party, co-maintained [durable execution](https://pydantic.dev/docs/ai/capabilities/durable_execution/overview/) on Temporal, DBOS, or Prefect, with [Restate, Kitaru, and Airflow](https://pydantic.dev/docs/ai/capabilities/durable_execution/overview/) integrations and more coming. Agents survive restarts and run for days on the engine you already operate, with [human-in-the-loop approval](https://pydantic.dev/docs/ai/tools-toolsets/deferred-tools/#human-in-the-loop-tool-approval) built in.
Built by the [Pydantic](https://docs.pydantic.dev) team: [Pydantic Validation](https://pydantic.dev/docs/) is the validation layer of the OpenAI SDK, the Anthropic SDK, the Google ADK, LangChain, and most of the AI ecosystem (and the foundation FastAPI was built on). Pydantic AI brings that same feeling to agents.
## Putting it together: a bank support agent
A typed support agent showing several features working together: [dependency injection](https://ai.pydantic.dev/dependencies), [function tools](https://ai.pydantic.dev/tools), [structured output](https://ai.pydantic.dev/output), a reusable [capability](https://ai.pydantic.dev/capabilities/overview/) bundling the customer context, and an [on-demand capability](https://ai.pydantic.dev/capabilities/on-demand) the model loads only when the conversation calls for it:
A typed support agent showing several features working together: [dependency injection](https://pydantic.dev/docs/ai/core-concepts/dependencies/), [function tools](https://pydantic.dev/docs/ai/tools-toolsets/tools/), [structured output](https://pydantic.dev/docs/ai/core-concepts/output/), a reusable [capability](https://pydantic.dev/docs/ai/capabilities/overview/) bundling the customer context, and an [on-demand capability](https://pydantic.dev/docs/ai/capabilities/on-demand/) the model loads only when the conversation calls for it:
```python
from dataclasses import dataclass
@@ -344,12 +344,12 @@ async def main():
"""
```
For the annotated walkthrough and Logfire tracing, see the [same example in the docs](https://ai.pydantic.dev/#putting-it-together-a-bank-support-agent).
For the annotated walkthrough and Logfire tracing, see the [same example in the docs](https://pydantic.dev/docs/ai/overview/#putting-it-together-a-bank-support-agent).
## Next Steps
- [Install Pydantic AI](https://ai.pydantic.dev/install) and put your own coding agent to work: install the [Pydantic AI skill](https://ai.pydantic.dev/coding-agent-skills), point it at the [examples](https://ai.pydantic.dev/examples/setup) and the [Harness index](https://pydantic.dev/docs/ai/harness/), and tell it what you'd like to build. No API key needed to start (there's a built-in [`'test'` model](https://ai.pydantic.dev/testing#unit-testing-with-testmodel)).
- Read the [docs](https://ai.pydantic.dev/agents/) and the [API reference](https://ai.pydantic.dev/api/agent/).
- [Install Pydantic AI](https://pydantic.dev/docs/ai/overview/install/) and put your own coding agent to work: install the [Pydantic AI skill](https://pydantic.dev/docs/ai/overview/coding-agent-skills/), point it at the [examples](https://pydantic.dev/docs/ai/examples/setup/) and the [Harness index](https://pydantic.dev/docs/ai/harness/), and tell it what you'd like to build. No API key needed to start (there's a built-in [`'test'` model](https://pydantic.dev/docs/ai/guides/testing/#unit-testing-with-testmodel)).
- Read the [docs](https://pydantic.dev/docs/ai/core-concepts/agent/) and the [API reference](https://pydantic.dev/docs/ai/api/pydantic-ai/agent/).
- Give your agent its batteries: [Pydantic AI Harness](https://github.com/pydantic/pydantic-ai-harness).
- Join [Slack](https://logfire.pydantic.dev/docs/join-slack/) or file an issue on [GitHub](https://github.com/pydantic/pydantic-ai/issues).
@@ -361,6 +361,6 @@ Everything you need to ship production-grade AI agents:
- [Pydantic AI Harness](https://github.com/pydantic/pydantic-ai-harness): the official capability library and harness, from single capabilities to complete agents
- [Pydantic Logfire](https://pydantic.dev/logfire?utm_source=github&utm_medium=readme&utm_campaign=pydantic-ai): AI-first, full-stack observability
- [Logfire AI Gateway](https://pydantic.dev/ai-gateway?utm_source=github&utm_medium=readme&utm_campaign=pydantic-ai): unified LLM proxy
- [Pydantic Evals](https://ai.pydantic.dev/evals): evaluate any Python function, agents included, with [production evals on Logfire](https://pydantic.dev/logfire/evals?utm_source=github&utm_medium=readme&utm_campaign=pydantic-ai)
- [Pydantic Graph](https://ai.pydantic.dev/graph): typed graph control flow
- [Pydantic Evals](https://pydantic.dev/docs/ai/evals/evals/): evaluate any Python function, agents included, with [production evals on Logfire](https://pydantic.dev/logfire/evals?utm_source=github&utm_medium=readme&utm_campaign=pydantic-ai)
- [Pydantic Graph](https://pydantic.dev/docs/ai/graph/graph/): typed graph control flow
- [genai-prices](https://github.com/pydantic/genai-prices): model pricing data, kept current
+2 -1
View File
@@ -14,10 +14,11 @@
- Use Markdown heading syntax (`##`, `###`, `####`) instead of bold text for sections — preserves semantic structure and document hierarchy — Proper heading levels enable navigation, accessibility, and consistent documentation structure across all `.md` files
<!-- rule:396 -->
- Establish one canonical source per topic and link to it — prevents inconsistency and maintenance burden — Documentation that's duplicated across locations becomes outdated differently, creating contradictions and requiring multiple updates for every change
- When linking to a section of a docs page from anywhere in the repo — a docstring, a skill reference, an example README — use the `{#custom-id}` pinned on that heading in `docs/`, never an id copied out of a rendered page's URL — A copied id is whatever the site's slugifier happened to generate that week, so it goes dead the moment the heading is pinned or the slugifier changes; only files under `docs/`, `examples/`, and the repository root are anchor-checked in CI, so a link written anywhere else has nothing to catch it
<!-- rule:34 -->
- Link to official provider/project docs instead of duplicating model lists, features, or setup details — prevents stale documentation and reduces maintenance burden — Exhaustive inline lists become outdated quickly; authoritative external sources stay current and reduce maintenance
<!-- rule:138 -->
- Update all related docs in the same PR when changing functionality, APIs, or capabilities — includes docstrings, comments, external docs (e.g., `ai.pydantic.dev`), and API references — Prevents documentation drift that misleads users about actual behavior, limitations, or API contracts
- Update all related docs in the same PR when changing functionality, APIs, or capabilities — includes docstrings, comments, external docs (e.g., `pydantic.dev/docs/ai`), and API references — Prevents documentation drift that misleads users about actual behavior, limitations, or API contracts
<!-- rule:107 -->
- Register new `docs/` files in `docs/navigation.yml` — Keeps the published pydantic.dev/docs/ai navigation complete and prevents orphaned pages or route drift
<!-- rule:31 -->
+3 -3
View File
@@ -78,7 +78,7 @@ options:
--no-stream Disable streaming from the model
```
For more information on how to use it, see the [CLI documentation](https://ai.pydantic.dev/cli/).
For more information on how to use it, see the [CLI documentation](https://pydantic.dev/docs/ai/integrations/cli/).
## Web Chat UI
@@ -88,7 +88,7 @@ Launch a web-based chat interface:
clai web -m openai:gpt-5.2
```
![Web Chat UI](https://ai.pydantic.dev/img/web-chat-ui.png)
![Web Chat UI](https://pydantic.dev/docs/ai/img/web-chat-ui.png)
This will start a web server (default: http://127.0.0.1:7932) with a chat interface.
@@ -106,4 +106,4 @@ Launch the web UI with:
clai web --agent my_agent:my_agent
```
For full Web UI documentation, see [Web Chat UI](https://ai.pydantic.dev/web/).
For full Web UI documentation, see [Web Chat UI](https://pydantic.dev/docs/ai/guides/web/).
+2 -1
View File
@@ -6,6 +6,7 @@
<!-- rule:232 -->
- Link all concepts, features, and API elements to their docs/reference pages using anchor fragments (`#section-name`) for specific sections — Improves discoverability and reduces user friction by providing direct navigation to relevant documentation context
- Pin an explicit `{#custom-id}` on a heading as soon as anything links to it and its generated id would surprise the person writing that link — unpinned, `github-slugger` drops punctuation and turns every space into its own dash, so `## Tools & native abilities` would generate `#tools--native-abilities` (doubled, the `&` vanishing between two spaces) and `## SIP/telephony bridge` generates `#siptelephony-bridge` (glued, the `/` vanishing inside a word); a literal `-` is kept rather than dropped and compounds it, so `## Agentic Chat - Code` would generate `#agentic-chat---code` — An explicit id is stable across slugifier changes and reads better than the generated one, but it also *replaces* the generated id, so pin before a link exists rather than after: `SIP/telephony bridge` is left unpinned precisely because nothing links to it yet. `.github/workflows/ci.yml` fails the build on an unresolvable anchor in `docs/`, `examples/`, or a root `*.md`, though not on one inside a docstring
<!-- rule:66 -->
- Use reference-style links for API elements: `[ElementName][module.path.ElementName]` — enables hover docs and navigation on the published documentation site — Provides interactive documentation features like tooltips and jump-to-definition that plain backticks cannot support
<!-- rule:714 -->
@@ -66,7 +67,7 @@ Use "shape" only for concrete structure or wire representation. Otherwise name t
The docs index and the repository README are one story on two surfaces. Whenever one changes, mirror the other in the same PR (enforced by `tests/test_docs_parity.py`):
- `docs/index.md` uses relative links, tabs (`=== "..."`), numbered annotations (`(1)!`), and MkDocs-only markup. `README.md` uses absolute links (`https://ai.pydantic.dev/...` for core, `https://pydantic.dev/docs/ai/harness/...` for Harness), `###` sections instead of tabs, and plain one-line `#` comments instead of annotations (GitHub renders annotation markers literally).
- `docs/index.md` uses relative links, tabs (`=== "..."`), numbered annotations (`(1)!`), and MkDocs-only markup. `README.md` uses absolute links (`https://pydantic.dev/docs/ai/...`), `###` sections instead of tabs, and plain one-line `#` comments instead of annotations (GitHub renders annotation markers literally).
- The mirrored code examples (coding agent, data extraction, realtime voice, image generation, embeddings, `bank_support.py`) must stay code-identical across both surfaces; only comments/annotations and fence attributes may differ.
- `README.md` is included in `tests/test_examples.py`'s `find_examples`, so its snippets are tested and linted. Snippets that cannot run here (`pydantic_ai_harness` imports, interactive realtime sessions) are excluded by content match in `find_filter_examples`, not by fence attributes, so README fences stay bare for GitHub rendering.
- Wording that appears on both surfaces (paragraph one, the whatever-you-came-to-build line, the Why bullets, section intros) must match word for word modulo link form.
+6 -6
View File
@@ -879,7 +879,7 @@ try:
except UsageLimitExceeded as e:
print(e)
"""
Exceeded the output_tokens_limit of 10 (output_tokens=32). Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://ai.pydantic.dev/agent/#usage-limits
Exceeded the output_tokens_limit of 10 (output_tokens=32). Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://pydantic.dev/docs/ai/core-concepts/agent/#usage-limits
"""
```
@@ -919,7 +919,7 @@ try:
except UsageLimitExceeded as e:
print(e)
"""
The next request would exceed the request_limit of 3. Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://ai.pydantic.dev/agent/#usage-limits
The next request would exceed the request_limit of 3. Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://pydantic.dev/docs/ai/core-concepts/agent/#usage-limits
"""
```
@@ -947,7 +947,7 @@ try:
except UsageLimitExceeded as e:
print(e)
"""
The next tool call(s) would exceed the tool_calls_limit of 1 (tool_calls=2). Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://ai.pydantic.dev/agent/#usage-limits
The next tool call(s) would exceed the tool_calls_limit of 1 (tool_calls=2). Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://pydantic.dev/docs/ai/core-concepts/agent/#usage-limits
"""
```
@@ -974,7 +974,7 @@ try:
except UsageLimitExceeded as e:
print(e)
"""
Exceeded the per_request_input_tokens_limit of 10 (request_input_tokens=62). Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://ai.pydantic.dev/agent/#usage-limits
Exceeded the per_request_input_tokens_limit of 10 (request_input_tokens=62). Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://pydantic.dev/docs/ai/core-concepts/agent/#usage-limits
"""
```
@@ -999,7 +999,7 @@ try:
except UsageLimitExceeded as e:
print(e)
"""
Exceeded the `cost_limit` of 0.0001 (`usage.cost`=Decimal('0.000201')). Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://ai.pydantic.dev/agent/#usage-limits
Exceeded the `cost_limit` of 0.0001 (`usage.cost`=Decimal('0.000201')). Consider raising the limit, or see the docs on usage limits for budget-aware patterns: https://pydantic.dev/docs/ai/core-concepts/agent/#usage-limits
"""
```
@@ -1557,7 +1557,7 @@ with capture_run_messages() as messages: # (2)!
print('An error occurred:', e)
"""
An error occurred:
Tool 'calc_volume' exceeded max retries count of 1. Consider raising the retry limit, or see the docs on tool retries: https://ai.pydantic.dev/tools-advanced/#tool-retries
Tool 'calc_volume' exceeded max retries count of 1. Consider raising the retry limit, or see the docs on tool retries: https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#tool-retries
"""
print('cause:', repr(e.__cause__))
#> cause: ModelRetry('Please try again.')
+5 -5
View File
@@ -37,7 +37,7 @@ The workspace the agent acts in: the files it edits and the commands it runs, lo
| [Shell](https://pydantic.dev/docs/ai/harness/shell/) | Harness | Command execution with allowlists, denylists, timeouts, and credential-stripping |
| [Modal Sandbox](https://pydantic.dev/docs/ai/harness/modal-sandbox/) | Harness | Commands and files in an isolated [Modal](https://modal.com) cloud sandbox |
### Tools & native abilities
### Tools & native abilities {#tools-native-abilities}
Connections to systems outside the agent's workspace, and abilities the provider executes natively.
@@ -50,7 +50,7 @@ Connections to systems outside the agent's workspace, and abilities the provider
| [LocalStack](https://pydantic.dev/docs/ai/harness/localstack/) | Harness | An emulated AWS environment with AWS CLI tools |
| [Macroscope](https://pydantic.dev/docs/ai/harness/macroscope/) | Harness | Run a local [Macroscope](https://docs.macroscope.com/cli) code review and hand the findings to the agent |
### Web & research
### Web & research {#web-research}
Finding and reading things on the open web.
@@ -63,7 +63,7 @@ Finding and reading things on the open web.
| [Exa Agent](https://pydantic.dev/docs/ai/harness/exa-search/) | Harness | Delegate open-ended research to the Exa Agent API |
| [Browser Use](https://pydantic.dev/docs/ai/harness/browser-use/) | Harness | Hand web tasks to an autonomous [browser-use](https://github.com/browser-use/browser-use) agent driving a real browser |
### Reasoning, planning & delegation
### Reasoning, planning & delegation {#reasoning-planning-delegation}
How the agent thinks and divides the work.
@@ -88,7 +88,7 @@ How the agent spends its context window: the difference between an agent that de
| [Tool Output Limits](https://pydantic.dev/docs/ai/harness/tool-output-limits/) | Harness | Truncate, spill to a queryable file, or summarize oversized tool returns at the source |
| [Warn On Cache Busts](https://pydantic.dev/docs/ai/harness/warn-on-cache-busts/) | Harness | Detect prompt-cache prefix collapses between requests, from the provider's own numbers |
### Knowledge & memory
### Knowledge & memory {#knowledge-memory}
What the agent knows and remembers, loaded when relevant instead of carried in every prompt.
@@ -100,7 +100,7 @@ What the agent knows and remembers, loaded when relevant instead of carried in e
| [Repo Context](https://pydantic.dev/docs/ai/harness/repo-context/) | Harness | Start runs oriented: `AGENTS.md`/`CLAUDE.md` + repository structure |
| [Pydantic AI Docs](https://pydantic.dev/docs/ai/harness/pydantic-ai-docs/) | Harness | On-demand Pydantic AI documentation lookup |
### Control & safety
### Control & safety {#control-safety}
Bounding what the agent may do, and keeping it on-instructions.
+1 -1
View File
@@ -134,7 +134,7 @@ agent = Agent(model, model_settings=settings)
...
```
### Adaptive Thinking & Effort
### Adaptive Thinking & Effort {#adaptive-thinking-effort}
Starting with `claude-opus-4-6`, Anthropic supports [adaptive thinking](https://docs.anthropic.com/en/docs/build-with-claude/adaptive-thinking), where the model dynamically decides when and how much to think based on the complexity of each request. This replaces extended thinking (`type: 'enabled'` with `budget_tokens`) which is deprecated on Opus 4.6 and removed on Opus 4.7, 4.8, 5, and Sonnet 5. Claude Opus 4.7, 4.8, 5, and Sonnet 5 also add the `xhigh` effort level. Adaptive thinking also automatically enables interleaved thinking.
+4 -4
View File
@@ -22,13 +22,13 @@ Pydantic AI supports [multi-agent patterns](../multi-agent-applications.md) dire
* [`subagents-pydantic-ai`](https://github.com/vstorm-co/subagents-pydantic-ai) - `SubAgentCapability` adds tools for multi-agent delegation: `task` (spawn a subagent), `check_task`, `wait_tasks`, `list_active_tasks`, `soft_cancel_task`, `hard_cancel_task`, and `answer_subagent`. Supports sync, async, and auto-execution modes, nested subagents, and runtime agent creation. Also available as a lower-level toolset via `create_subagent_toolset`.
## Guardrails & Safety
## Guardrails & Safety {#guardrails-safety}
[Pydantic AI Harness](https://pydantic.dev/docs/ai/harness/guardrails/) provides input and output guardrails that validate or block requests and responses, and Pydantic AI enforces usage, token, and request limits via [`UsageLimits`](../agent.md#usage-limits). As a community alternative bundling several ready-made shields, including USD cost tracking:
* [`pydantic-ai-shields`](https://github.com/vstorm-co/pydantic-ai-shields) - Ready-to-use guardrail capabilities: `CostTracking` (tracks token usage and USD cost per run, raises `BudgetExceededError` on budget overrun); `ToolGuard` (block or require approval for specific tools); `InputGuard` and `OutputGuard` (custom sync or async validation functions); `PromptInjection`, `PiiDetector`, `SecretRedaction`, `BlockedKeywords`, and `NoRefusals` content shields.
## File Operations & Sandboxing
## File Operations & Sandboxing {#file-operations-sandboxing}
[Pydantic AI Harness](https://pydantic.dev/docs/ai/harness/) ships sandboxed [`FileSystem`](https://pydantic.dev/docs/ai/harness/filesystem/) and [`Shell`](https://pydantic.dev/docs/ai/harness/shell/) capabilities, plus [`CodeMode`](https://pydantic.dev/docs/ai/harness/code-mode/) for running tool calls as sandboxed Python. As a community alternative:
@@ -40,13 +40,13 @@ Pydantic AI supports [Agent Skills natively](on-demand.md#loading-skills-from-ma
* [`pydantic-ai-skills`](https://github.com/DougTrajano/pydantic-ai-skills) - `SkillsCapability` implements Agent Skills support with progressive disclosure (load skills on-demand to reduce tokens). Supports filesystem and programmatic skills; compatible with [agentskills.io](https://agentskills.io).
## Data & Analytics
## Data & Analytics {#data-analytics}
Capabilities for querying and analyzing structured data help agents answer questions over files and databases:
* [`pydantic-ai-chdb`](https://github.com/chdb-io/pydantic-ai-chdb) - `ChDBCapability` gives agents analytical SQL over local files (Parquet/CSV/JSON), object storage, and remote databases with [chDB](https://clickhouse.com/docs/en/chdb), the in-process ClickHouse engine — the engine itself needs no server or connection string to run (remote sources are reached via ClickHouse table functions, which take their own credentials). Registers `run_select_query` (read-only ClickHouse SQL with parameter binding), `list_databases`, `list_tables`, `describe_table`, `get_sample_data`, `list_functions`, and `attach_file` (opt-in writable sessions) tools plus schema-first instructions. Sessions default to the engine-level `readonly=2` setting with capped results, and typed engine errors are mapped to [`ModelRetry`][pydantic_ai.exceptions.ModelRetry] so the model can correct its queries. Works with [agent specs](../agent-spec.md) out of the box, so it can be loaded via [`from_spec`][pydantic_ai.capabilities.AbstractCapability.from_spec] / [`Agent.from_spec`][pydantic_ai.agent.Agent.from_spec]. Also available as a lower-level [toolset](../toolsets.md) via [`ChDBCapability(...).get_toolset()`][pydantic_ai.capabilities.AbstractCapability.get_toolset].
## Retrieval & RAG
## Retrieval & RAG {#retrieval-rag}
Pydantic AI demonstrates the retrieval pattern in the [RAG example](../examples/rag.md), where a search tool is registered against a vector database. The following community-developed packages provide reusable implementations of this pattern as capabilities, bundling retrieval tools with citation handling and instructions:
+1 -1
View File
@@ -127,7 +127,7 @@ These removals and behavior changes could not be announced via a V1 deprecation
- [`capture_run_messages()`][pydantic_ai.capture_run_messages] now also captures the partial `ModelRequest`/`ModelResponse` from an interrupted run, marked with `state='interrupted'` (a new `ModelRequest.state` field is added). Code that asserts on exact captured-message counts on error paths may need updating. See [#5364](https://github.com/pydantic/pydantic-ai/pull/5364).
- Output tool calls and returns now emit dedicated `OutputToolCallEvent`/`OutputToolResultEvent` instead of `FunctionToolCallEvent`/`FunctionToolResultEvent`. Separately, native tool calls and returns no longer emit dedicated events at all — the `BuiltinToolCallEvent`/`BuiltinToolResultEvent` classes are removed and they surface only via the standard `PartStartEvent`/`PartDeltaEvent`. See [#5332](https://github.com/pydantic/pydantic-ai/pull/5332) and [#5476](https://github.com/pydantic/pydantic-ai/pull/5476).
##### [`ModelProfile`][pydantic_ai.profiles.ModelProfile] is now a `TypedDict`
##### [`ModelProfile`][pydantic_ai.profiles.ModelProfile] is now a `TypedDict` {#modelprofile-is-now-a-typeddict}
See the [Model Profile guide](models/openai.md#model-profile) for an overview of what a model profile is and how to configure one.
+7 -2
View File
@@ -1,6 +1,6 @@
We'd love you to contribute to Pydantic AI!
## How we work — the short version
## How we work — the short version {#how-we-work-the-short-version}
Pydantic AI is maintained by a small team. We set our own priorities based on what benefits the most users, and we work through issues and PRs in that order — not in the order they arrive.
@@ -25,7 +25,7 @@ If the fix could reasonably go more than one way, or you're unsure it's actually
### Features, integrations, or API changes
Before writing code, ask whether the change needs to live in core at all. Most new agent behaviors belong in [**Pydantic AI Harness**](https://github.com/pydantic/pydantic-ai-harness), the official capability library — not in this repo. Pydantic AI core is for the agent loop, model providers, and capabilities that require model-specific support or are fundamental to the agent experience. Standalone capabilities — guardrails, memory, context management, file system access, etc. — belong in the harness, where they can iterate faster. See [What goes where?](https://pydantic.dev/docs/ai/harness/#what-goes-where) for the full distinction.
Before writing code, ask whether the change needs to live in core at all. Most new agent behaviors belong in [**Pydantic AI Harness**](https://github.com/pydantic/pydantic-ai-harness), the official capability library — not in this repo. Pydantic AI core is for the agent loop, model providers, and capabilities that require model-specific support or are fundamental to the agent experience. Standalone capabilities — guardrails, memory, context management, file system access, etc. — belong in the harness, where they can iterate faster. See [What goes where?](https://pydantic.dev/docs/ai/harness/#when-do-you-need-the-harness) for the full distinction.
**If your idea is a capability**, open an issue on [pydantic-ai-harness](https://github.com/pydantic/pydantic-ai-harness/issues) instead. You can also publish capabilities as your own package using the `pydantic-ai-<name>` convention — see [Publishing capability packages](extensibility.md#publishing-capability-packages). Once a capability has real users and a stable API, we can talk about upstreaming to harness or core.
@@ -150,6 +150,11 @@ either value with `/ai` or a leading slash.
For the rendered site, use the documentation preview attached to a pull request after a maintainer
adds the `trigger:docs` label.
CI checks that every link between doc pages resolves, anchor included, and fails on `Cannot find
fragment`. A heading's anchor is generated from its text, so renaming one silently breaks every link
pointing at it. Where a heading is linked to, pin its anchor with `{#custom-id}` — the heading text
is then free to change without moving the anchor.
## Rules for adding new models to Pydantic AI {#new-model-rules}
To avoid an excessive workload for the maintainers of Pydantic AI, we can't accept all model contributions, so we're setting the following rules for when we'll accept new models and when we won't. This should hopefully reduce the chances of disappointment and wasted work.
+1 -1
View File
@@ -273,7 +273,7 @@ See [Quick Start](evals/quick-start.md) for more examples and [Concurrency & Per
## API Reference
For comprehensive coverage of all classes, methods, and configuration options, see the detailed [API Reference documentation](https://ai.pydantic.dev/api/pydantic_evals/dataset/).
For comprehensive coverage of all classes, methods, and configuration options, see the detailed [API Reference documentation](api/pydantic_evals/dataset.md).
## Next Steps
+2 -2
View File
@@ -4,7 +4,7 @@ Evaluators are the core of Pydantic Evals. They analyze task outputs and provide
## When to Use Different Evaluators
### Deterministic Checks (Fast & Reliable)
### Deterministic Checks (Fast & Reliable) {#deterministic-checks-fast-reliable}
Use deterministic evaluators when you can define exact rules:
@@ -36,7 +36,7 @@ Use deterministic evaluators when you can define exact rules:
- Performance requirements (latency, token counts)
- Behavioral checks (which tools were called, which code paths executed)
### LLM-as-a-Judge (Flexible & Nuanced)
### LLM-as-a-Judge (Flexible & Nuanced) {#llm-as-a-judge-flexible-nuanced}
Use [`LLMJudge`][pydantic_evals.evaluators.LLMJudge] when evaluation requires understanding or judgment:
+6 -6
View File
@@ -86,7 +86,7 @@ Perform the following steps, waiting for the response of each step before contin
4. Report how long the background set took by diffing the two times
```
#### Agentic Chat - Code
#### Agentic Chat - Code {#agentic-chat-code}
```snippet {path="/examples/pydantic_ai_examples/ag_ui/api/agentic_chat.py"}```
@@ -103,7 +103,7 @@ If you've [run the example](#running-the-example), you can view it at <http://lo
Create a plan for breakfast and execute it
```
#### Agentic Generative UI - Code
#### Agentic Generative UI - Code {#agentic-generative-ui-code}
```snippet {path="/examples/pydantic_ai_examples/ag_ui/api/agentic_generative_ui.py"}```
@@ -122,7 +122,7 @@ plan and the user can approve it using checkboxes.
Generate a list of steps for cleaning a car for me to review
```
#### Human in the Loop - Code
#### Human in the Loop - Code {#human-in-the-loop-code}
```snippet {path="/examples/pydantic_ai_examples/ag_ui/api/human_in_the_loop.py"}```
@@ -156,7 +156,7 @@ Agent prompt
Help me complete my story about bruce the dog, is should be no longer than a sentence.
```
#### Predictive State Updates - Code
#### Predictive State Updates - Code {#predictive-state-updates-code}
```snippet {path="/examples/pydantic_ai_examples/ag_ui/api/predictive_state_updates.py"}```
@@ -179,7 +179,7 @@ If you've [run the example](#running-the-example), you can view it at <http://lo
1. Customise the basic settings of your recipe
2. Click `Improve with AI`
#### Shared State - Code
#### Shared State - Code {#shared-state-code}
```snippet {path="/examples/pydantic_ai_examples/ag_ui/api/shared_state.py"}```
@@ -199,6 +199,6 @@ If you've [run the example](#running-the-example), you can view it at <http://lo
Generate a haiku about formula 1
```
#### Tool Based Generative UI - Code
#### Tool Based Generative UI - Code {#tool-based-generative-ui-code}
```snippet {path="/examples/pydantic_ai_examples/ag_ui/api/tool_based_generative_ui.py"}```
+3 -3
View File
@@ -259,7 +259,7 @@ Built by the [Pydantic](https://docs.pydantic.dev) team: [Pydantic Validation](h
**Sign up for our newsletter, *The Pydantic Stack*, with updates & tutorials on Pydantic AI, Logfire, and Pydantic:**
<form method="POST" action="https://eu.customerioforms.com/forms/submit_action?site_id=53d2086c3c4214eaecaa&form_id=14b22611745b458&success_url=https://ai.pydantic.dev/" class="md-typeset" style="display: flex; align-items: center; gap: 0.5rem; width: 100%;">
<form method="POST" action="https://eu.customerioforms.com/forms/submit_action?site_id=53d2086c3c4214eaecaa&form_id=14b22611745b458&success_url=https://pydantic.dev/docs/ai/" class="md-typeset" style="display: flex; align-items: center; gap: 0.5rem; width: 100%;">
<input
type="email"
id="email_input"
@@ -449,10 +449,10 @@ This format is defined in Markdown and suited for LLMs and AI coding assistants
Two formats are available:
- [`llms.txt`](https://ai.pydantic.dev/llms.txt): a file containing a brief description
- [`llms.txt`](https://pydantic.dev/docs/ai/llms.txt): a file containing a brief description
of the project, along with links to the different sections of the documentation. The structure
of this file is described in details [here](https://llmstxt.org/#format).
- [`llms-full.txt`](https://ai.pydantic.dev/llms-full.txt): Similar to the `llms.txt` file,
- [`llms-full.txt`](https://pydantic.dev/docs/ai/llms-full.txt): Similar to the `llms.txt` file,
but every link content is included. Note that this file may be too large for some LLMs.
As of today, these files are not automatically leveraged by IDEs or coding agents, but they will use it if you provide a link or the full text.
+1 -1
View File
@@ -507,7 +507,7 @@ Because the per-run toolset's session is established inside the run itself, cred
As an alternative to a dynamic toolset, you can construct a new `MCPToolset` yourself for each request and pass it to the [`toolsets` argument](../toolsets.md) of the agent run methods.
## Custom TLS / SSL configuration
## Custom TLS / SSL configuration {#custom-tls-ssl-configuration}
In some environments you need to tweak how HTTPS connections are established — for example to trust an internal Certificate Authority, present a client certificate for **mTLS**, or (during local development only!) disable certificate verification altogether. `MCPToolset` exposes an `http_client` parameter so you can pass your own pre-configured [`httpx.AsyncClient`](https://www.python-httpx.org/async/):
+2 -2
View File
@@ -17,7 +17,7 @@ In every setup the session — with its [tools](tools.md), [history](history.md)
to the provider with the provider's own SDK instead moves the agent loop into the client and gives
up all of that; prefer one of the setups above.
## Browser WebRTC + server sideband
## Browser WebRTC + server sideband {#browser-webrtc-server-sideband}
For browser voice agents on OpenAI and Azure OpenAI, the browser carries microphone and speaker
audio directly over WebRTC while the backend attaches a control-plane **sideband** to the same call.
@@ -83,7 +83,7 @@ The [realtime WebRTC example](../examples/realtime-webrtc.md) demonstrates the f
browser flow. Provider-specific setup (Azure's Microsoft Entra ID and `webrtcfilter`) lives on the
[Azure](azure.md#browser-webrtc-and-microsoft-entra-id) page.
## Browser → backend WebSocket relay
## Browser → backend WebSocket relay {#browser-backend-websocket-relay}
When the browser can't use WebRTC — or the provider is Gemini Live or xAI — build a WebSocket
endpoint on your backend that accepts the browser's microphone audio and pumps it into
+2 -2
View File
@@ -557,7 +557,7 @@ def my_flaky_tool(query: str) -> str:
Both `ValidationError` and `ModelRetry` respect the configured retry limit — set per-tool via [`Tool(max_retries=N)`][pydantic_ai.tools.Tool] (or `@agent.tool(retries=N)`), per-toolset via [`FunctionToolset(max_retries=N)`][pydantic_ai.toolsets.FunctionToolset], or agent-wide via [`Agent(retries={'tools': N})`][pydantic_ai.agent.Agent.__init__], applied in that order of precedence. The agent-wide default can also be overridden per run via [`agent.run(retries={'tools': N})`][pydantic_ai.agent.Agent.run] (and `run_sync`/`run_stream`/`iter`, or for a block of runs via [`agent.override()`][pydantic_ai.agent.Agent.override]); a per-run value replaces the agent-wide default at the bottom of the precedence chain, so explicit per-tool and per-toolset limits still win. A bare `int` at these run-time call sites overrides both budgets (matching construction) — pass a dict such as `retries={'tools': N}` or `retries={'output': N}` to change just one.
Tool retries are tracked **per tool**: every function tool has its own counter, with no global 'tool call' budget shared across the run. When a tool raises `ModelRetry` or its arguments fail validation, only that tool's counter advances. Inside a tool function, [`ctx.max_retries`][pydantic_ai.tools.RunContext.max_retries] reflects that tool's enforcement limit and [`ctx.retry`][pydantic_ai.tools.RunContext.retry] is that tool's own counter. When a tool exhausts its counter, the run raises [`UnexpectedModelBehavior`][pydantic_ai.exceptions.UnexpectedModelBehavior] with message `'Tool {name!r} exceeded max retries count of {N}. Consider raising the retry limit, or see the docs on tool retries: https://ai.pydantic.dev/tools-advanced/#tool-retries'`. User-provided toolsets inherit the agent-wide tool-retry default — or its per-run override — as their default when no per-toolset value is set.
Tool retries are tracked **per tool**: every function tool has its own counter, with no global 'tool call' budget shared across the run. When a tool raises `ModelRetry` or its arguments fail validation, only that tool's counter advances. Inside a tool function, [`ctx.max_retries`][pydantic_ai.tools.RunContext.max_retries] reflects that tool's enforcement limit and [`ctx.retry`][pydantic_ai.tools.RunContext.retry] is that tool's own counter. When a tool exhausts its counter, the run raises [`UnexpectedModelBehavior`][pydantic_ai.exceptions.UnexpectedModelBehavior] with message `'Tool {name!r} exceeded max retries count of {N}. Consider raising the retry limit, or see the docs on tool retries: https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#tool-retries'`. User-provided toolsets inherit the agent-wide tool-retry default — or its per-run override — as their default when no per-toolset value is set.
### Which retry limit wins
@@ -733,7 +733,7 @@ The `args_validator` parameter is available on [`@agent.tool`][pydantic_ai.agent
The validation result is exposed via the `args_valid` field on [`FunctionToolCallEvent`][pydantic_ai.messages.FunctionToolCallEvent]. This reflects all validation — both schema validation and custom `args_validator` validation (if configured): `True` means all validation passed, `False` means validation failed, and `None` means validation was not performed (e.g. tool calls skipped due to the `'early'` end strategy, or deferred tool calls resolved without execution).
### Parallel tool calls & concurrency
### Parallel tool calls & concurrency {#parallel-tool-calls-concurrency}
When a model returns multiple tool calls in one response, Pydantic AI schedules them concurrently using `asyncio.create_task`, executing them in the order the model emitted them.
+1 -1
View File
@@ -8,4 +8,4 @@
Examples of how to use Pydantic AI and what it can do.
For full documentation of these examples and how to run them, see [ai.pydantic.dev/examples/](https://ai.pydantic.dev/examples/).
For full documentation of these examples and how to run them, see [pydantic.dev/docs/ai/examples](https://pydantic.dev/docs/ai/examples/setup/).
+1 -1
View File
@@ -12,7 +12,7 @@ To copy all examples to a new directory, run:
uv run -m pydantic_ai_examples --copy-to <destination_path>
See https://ai.pydantic.dev/examples/ for more information.
See https://pydantic.dev/docs/ai/examples/setup/ for more information.
"""
import argparse
@@ -1,6 +1,6 @@
"""Very simply CLI to run the AG-UI example.
See https://ai.pydantic.dev/examples/ag-ui/ for more information.
See https://pydantic.dev/docs/ai/examples/ag-ui/ for more information.
"""
if __name__ == '__main__':
@@ -47,7 +47,7 @@ Leaving `CAMERA_REALTIME_VOICE` empty uses the provider's default. Language, tur
proactive audio, and affective dialog are Gemini-only. OpenAI and Azure map either VAD sensitivity
control to their shared turn-detection sensitivity.
The app is instrumented with [Logfire](https://ai.pydantic.dev/logfire/). When `LOGFIRE_TOKEN` is
The app is instrumented with [Logfire](https://pydantic.dev/docs/ai/integrations/logfire/). When `LOGFIRE_TOKEN` is
set, realtime sessions, model turns, and tool calls appear as traces; otherwise nothing is sent.
## Watch, search, and drawing
@@ -1,7 +1,7 @@
"""Realtime camera + voice assistant: a browser bridged to a provider-agnostic realtime session.
The browser streams microphone PCM, one camera frame per second, and typed text over a WebSocket;
the server forwards them into a [realtime session](https://ai.pydantic.dev/realtime/overview/) and
the server forwards them into a [realtime session](https://pydantic.dev/docs/ai/realtime/overview/) and
streams model audio, transcripts, and tool results back. The spine is the two pumps in
`_run_session`; everything else is configuration and optional demo features: **Watch** (proactive
narration of scene changes), **web search** with citation chips, and **sketch redrawing** through a
@@ -5,7 +5,7 @@ latency) while a **Pydantic AI sideband** on the server runs the agent's tools,
keeps the API key off the client.
This is the recommended topology for browser voice agents (see the
[realtime guide](https://ai.pydantic.dev/realtime/lifecycle/#browser-webrtc)). The server never sits in the
[realtime guide](https://pydantic.dev/docs/ai/realtime/deployment/#browser-webrtc-server-sideband)). The server never sits in the
audio path — it is the control plane:
```
@@ -31,7 +31,7 @@ server-side tool.
Overrides: `WEBRTC_REALTIME_MODEL` (default `gpt-realtime`), `WEBRTC_REALTIME_VOICE` (default `marin`).
The app is instrumented with [Logfire](https://ai.pydantic.dev/logfire/): set `LOGFIRE_TOKEN` (e.g. in
The app is instrumented with [Logfire](https://pydantic.dev/docs/ai/integrations/logfire/): set `LOGFIRE_TOKEN` (e.g. in
the same `.env`) to see the realtime session, model turns, and tool calls as traces.
## How it works
@@ -3,7 +3,8 @@
The browser exchanges audio with OpenAI or Azure OpenAI **directly** over WebRTC (lowest latency), while this backend
stays the control plane: it relays the browser's SDP offer to the provider (so the API key never reaches the
browser), then attaches an [`AgentRealtime.session`][pydantic_ai.agent.AgentRealtime.session] to the same call by
`call_id` and runs the agent's tools server-side. See the [realtime guide](https://ai.pydantic.dev/realtime/lifecycle/#browser-webrtc).
`call_id` and runs the agent's tools server-side. See the
[realtime guide](https://pydantic.dev/docs/ai/realtime/deployment/#browser-webrtc-server-sideband).
The topology:
@@ -85,7 +85,7 @@ with gr.Blocks() as demo:
gr.HTML(
"""
<div style="display: flex; justify-content: center; align-items: center; gap: 2rem; padding: 1rem; width: 100%">
<img src="https://ai.pydantic.dev/img/logo-white.svg" style="max-width: 200px; height: auto">
<img src="https://pydantic.dev/docs/ai/img/logo-white.svg" style="max-width: 200px; height: auto">
<div>
<h1 style="margin: 0 0 1rem 0">Weather Assistant</h1>
<h3 style="margin: 0 0 0.5rem 0">
@@ -98,7 +98,7 @@ with gr.Blocks() as demo:
past_messages = gr.State([])
chatbot = gr.Chatbot(
label='Packing Assistant',
avatar_images=(None, 'https://ai.pydantic.dev/img/logo-white.svg'),
avatar_images=(None, 'https://pydantic.dev/docs/ai/img/logo-white.svg'),
examples=[
{'text': 'What is the weather like in Miami?'},
{'text': 'What is the weather like in London?'},
+1 -1
View File
@@ -8,4 +8,4 @@
Pydantic AI core logic with minimal required dependencies.
For more information on how to use this package see [ai.pydantic.dev/install](https://ai.pydantic.dev/install/).
For more information on how to use this package see [pydantic.dev/docs/ai/overview/install](https://pydantic.dev/docs/ai/overview/install/).
@@ -288,7 +288,7 @@ Key facts for building realtime agents:
audio; the sideband session runs tools and builds history (its audio methods raise, and
`audio_retention` must stay `'transcript_only'`).
See the [Realtime guide](https://ai.pydantic.dev/realtime/) for the full walkthrough.
See the [Realtime guide](https://pydantic.dev/docs/ai/realtime/overview/) for the full walkthrough.
## Task Routing Table
@@ -126,4 +126,4 @@ A `priority` controls delivery:
- `'asap'` (default): delivered at the earliest opportunity — added to the next model request, or, if the agent would otherwise terminate, used to redirect the run into one more request. This is "steering" an in-flight agent.
- `'when_idle'`: delivered only when the agent would otherwise terminate, after any `'asap'` messages — a follow-up task that shouldn't interrupt in-flight work.
Both priorities drain however you drive the run — `agent.run()`, explicit `AgentRun.next()`, and a bare `async for node in agent_run:` loop all deliver enqueued messages. See [message history docs](https://ai.pydantic.dev/message-history/#injecting-messages-mid-run) for details.
Both priorities drain however you drive the run — `agent.run()`, explicit `AgentRun.next()`, and a bare `async for node in agent_run:` loop all deliver enqueued messages. See [message history docs](https://pydantic.dev/docs/ai/core-concepts/message-history/#injecting-messages-mid-run) for details.
@@ -171,7 +171,7 @@ Plain text output (`output_type=str` / `TextOutput`, incl. a `str` fallback) is
To run a whole run's tools serially, use `with agent.parallel_tool_call_execution_mode('sequential'):` or set `parallel_tool_calls=False` on model settings.
See [Parallel Output Tool Calls](https://ai.pydantic.dev/output/#parallel-output-tool-calls) and [tools-advanced docs](https://ai.pydantic.dev/tools-advanced/#parallel-tool-calls-concurrency).
See [Parallel Output Tool Calls](https://pydantic.dev/docs/ai/core-concepts/output/#parallel-output-tool-calls) and [tools-advanced docs](https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#parallel-tool-calls-concurrency).
## Handle Network Errors and Rate Limiting Automatically
@@ -60,7 +60,7 @@ Useful `RunContext` fields include:
## Use MCP Servers
For URL-based MCP servers, use the `MCP` capability — it runs the MCP server locally by default and lets you opt into the model provider's native MCP support with `native=True`. See the [MCP capability docs](https://ai.pydantic.dev/capabilities/mcp/).
For URL-based MCP servers, use the `MCP` capability — it runs the MCP server locally by default and lets you opt into the model provider's native MCP support with `native=True`. See the [MCP capability docs](https://pydantic.dev/docs/ai/capabilities/mcp/).
```python
from pydantic_ai import Agent
@@ -91,7 +91,7 @@ agent = Agent(
)
```
When you need to manage the toolset lifecycle yourself, share an MCP server across multiple agents, or use FastMCP-specific configuration that doesn't fit the capability shape, use [`MCPToolset`](https://ai.pydantic.dev/mcp/client/) directly and pass it via `toolsets=[...]`. Its `tool_error_behavior` controls how a tool error from the server surfaces: `'retry'` (default) raises `ModelRetry`, `'failed'` raises `ToolFailed` (recorded as `outcome='failed'`), and `'error'` raises the raw `fastmcp` `ToolError`. For SEP-1686 tools with optional task support, set `prefer_tasks=False` to use normal calls; required tasks still use task-augmented execution.
When you need to manage the toolset lifecycle yourself, share an MCP server across multiple agents, or use FastMCP-specific configuration that doesn't fit the capability shape, use [`MCPToolset`](https://pydantic.dev/docs/ai/mcp/client/) directly and pass it via `toolsets=[...]`. Its `tool_error_behavior` controls how a tool error from the server surfaces: `'retry'` (default) raises `ModelRetry`, `'failed'` raises `ToolFailed` (recorded as `outcome='failed'`), and `'error'` raises the raw `fastmcp` `ToolError`. For SEP-1686 tools with optional task support, set `prefer_tasks=False` to use normal calls; required tasks still use task-augmented execution.
## Search with DuckDuckGo, Tavily, or Exa
@@ -110,4 +110,4 @@ Logfire can help demonstrate that an exercised run used the expected model, tool
Use deterministic characterization tests, provider integration tests, real clients, persistence/restart probes, database and side-effect assertions, and security tests for those claims. Report missing telemetry as missing evidence, not a passing result.
Primary references: [Pydantic AI with Logfire](https://pydantic.dev/docs/logfire/integrations/llms/pydanticai/), [Pydantic AI instrumentation settings](https://pydantic.dev/docs/ai/api/models/instrumented/), [LangChain and LangGraph with Logfire](https://pydantic.dev/docs/logfire/integrations/llms/langchain/), [Pydantic AI streaming](https://pydantic.dev/docs/ai/core-concepts/agent/#streaming), [Logfire scrubbing](https://pydantic.dev/docs/logfire/instrument/scrubbing/), [Logfire sampling](https://pydantic.dev/docs/logfire/instrument/sampling/), and [Logfire testing](https://pydantic.dev/docs/logfire/reference/testing/).
Primary references: [Pydantic AI with Logfire](https://pydantic.dev/docs/logfire/integrations/llms/pydanticai/), [Pydantic AI instrumentation settings](https://pydantic.dev/docs/ai/api/models/instrumented/), [LangChain and LangGraph with Logfire](https://pydantic.dev/docs/logfire/integrations/llms/langchain/), [Pydantic AI streaming](https://pydantic.dev/docs/ai/core-concepts/agent/#streaming-events-and-final-output), [Logfire scrubbing](https://pydantic.dev/docs/logfire/instrument/scrubbing/), [Logfire sampling](https://pydantic.dev/docs/logfire/instrument/sampling/), and [Logfire testing](https://pydantic.dev/docs/logfire/reference/testing/).
@@ -231,4 +231,4 @@ At minimum, spike these when present:
- LangChain: [middleware execution order](https://docs.langchain.com/oss/python/langchain/middleware/custom#execution-order), [structured output](https://docs.langchain.com/oss/python/langchain/structured-output), and [human-in-the-loop](https://docs.langchain.com/oss/python/langchain/human-in-the-loop)
- LangGraph: [checkpointers](https://docs.langchain.com/oss/python/langgraph/checkpointers), [interrupts](https://docs.langchain.com/oss/python/langgraph/interrupts), [fault tolerance](https://docs.langchain.com/oss/python/langgraph/fault-tolerance), and [streaming](https://docs.langchain.com/oss/python/langgraph/streaming)
- Pydantic AI: [instructions](https://pydantic.dev/docs/ai/core-concepts/agent/#instructions), [message history](https://pydantic.dev/docs/ai/core-concepts/message-history/), [structured output](https://pydantic.dev/docs/ai/output/), [parallel tools](https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#parallel-tool-calls--concurrency), [deferred tools](https://pydantic.dev/docs/ai/tools-toolsets/deferred-tools/), and [streaming](https://pydantic.dev/docs/ai/core-concepts/agent/#streaming)
- Pydantic AI: [instructions](https://pydantic.dev/docs/ai/core-concepts/agent/#instructions), [message history](https://pydantic.dev/docs/ai/core-concepts/message-history/), [structured output](https://pydantic.dev/docs/ai/output/), [parallel tools](https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#parallel-tool-calls-concurrency), [deferred tools](https://pydantic.dev/docs/ai/tools-toolsets/deferred-tools/), and [streaming](https://pydantic.dev/docs/ai/core-concepts/agent/#streaming-events-and-final-output)
@@ -615,7 +615,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
a [`ConcurrencyLimiter`][pydantic_ai.ConcurrencyLimiter] for sharing limits across
multiple agents, or None (default) for no limiting. When the limit is reached, additional calls
to `run()` or `iter()` will wait until a slot becomes available.
capabilities: Optional list of [capabilities](https://ai.pydantic.dev/capabilities/overview/) to configure the agent with,
capabilities: Optional list of [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) to configure the agent with,
including functions which take a run context and return a capability.
See [`CapabilityFunc`][pydantic_ai.capabilities.CapabilityFunc] for more information.
Custom capabilities can be created by subclassing
@@ -1294,7 +1294,7 @@ class Agent(AbstractAgent[AgentDepsT, OutputDataT]):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run. At run time, spec values are additive.
Returns:
@@ -586,7 +586,7 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
event_stream_handler: Optional handler for events from the model's streaming response and the agent's execution of tools to use for this run. Under a durability capability, this per-run handler runs workflow-side; model events are replayed after each model request completes. For handler I/O inside the durable boundary, pass `event_stream_handler=` to the durability capability.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run. At run time, spec values are additive.
Returns:
@@ -786,7 +786,7 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
event_stream_handler: Optional handler for events from the model's streaming response and the agent's execution of tools to use for this run. Under a durability capability, this per-run handler runs workflow-side; model events are replayed after each model request completes. For handler I/O inside the durable boundary, pass `event_stream_handler=` to the durability capability.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run. At run time, spec values are additive.
Returns:
@@ -952,7 +952,7 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
event_stream_handler: Optional handler for events from the model's streaming response and the agent's execution of tools to use for this run. Under a durability capability, this per-run handler runs workflow-side; model events are replayed after each model request completes. For handler I/O inside the durable boundary, pass `event_stream_handler=` to the durability capability.
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.
Note that it does _not_ receive any events after the final result is found.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run. At run time, spec values are additive.
Returns:
@@ -1268,7 +1268,7 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
event_stream_handler: Optional handler for events from the model's streaming response and the agent's execution of tools to use for this run. Under a durability capability, this per-run handler runs workflow-side; model events are replayed after each model request completes. For handler I/O inside the durable boundary, pass `event_stream_handler=` to the durability capability.
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.
Note that it does _not_ receive any events after the final result is found.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run. At run time, spec values are additive.
Returns:
@@ -1445,7 +1445,7 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run. At run time, spec values are additive.
Returns:
@@ -1647,7 +1647,7 @@ class AbstractAgent(Generic[AgentDepsT, OutputDataT], ABC):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run. At run time, spec values are additive.
Returns:
@@ -287,7 +287,7 @@ class WrapperAgent(AbstractAgent[AgentDepsT, OutputDataT]):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -481,7 +481,7 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
event_stream_handler: Optional event stream handler to use for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -634,7 +634,7 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
event_stream_handler: Optional event stream handler to use for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -785,7 +785,7 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
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.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -952,7 +952,7 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -1133,7 +1133,7 @@ class DBOSAgent(WrapperAgent[AgentDepsT, OutputDataT], DBOSConfiguredInstance):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -357,7 +357,7 @@ class PrefectAgent(WrapperAgent[AgentDepsT, OutputDataT]):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
event_stream_handler: Optional event stream handler to use for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -520,7 +520,7 @@ class PrefectAgent(WrapperAgent[AgentDepsT, OutputDataT]):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
event_stream_handler: Optional event stream handler to use for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -684,7 +684,7 @@ class PrefectAgent(WrapperAgent[AgentDepsT, OutputDataT]):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
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.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -851,7 +851,7 @@ class PrefectAgent(WrapperAgent[AgentDepsT, OutputDataT]):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -1056,7 +1056,7 @@ class PrefectAgent(WrapperAgent[AgentDepsT, OutputDataT]):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -476,7 +476,7 @@ class TemporalAgent(WrapperAgent[AgentDepsT, OutputDataT]):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
event_stream_handler: Optional event stream handler to use for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -631,7 +631,7 @@ class TemporalAgent(WrapperAgent[AgentDepsT, OutputDataT]):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
event_stream_handler: Optional event stream handler to use for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -780,7 +780,7 @@ class TemporalAgent(WrapperAgent[AgentDepsT, OutputDataT]):
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
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.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -947,7 +947,7 @@ class TemporalAgent(WrapperAgent[AgentDepsT, OutputDataT]):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -1151,7 +1151,7 @@ class TemporalAgent(WrapperAgent[AgentDepsT, OutputDataT]):
[`Agent.__init__`][pydantic_ai.agent.Agent.__init__] for semantics of the two enforcement paths.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
spec: Optional agent spec to apply for this run.
Returns:
@@ -206,7 +206,7 @@ def payload_size_errors(subject: str, remedy: str) -> Generator[None]:
'your tools or models return, configure Temporal external storage (or a claim-check '
'`payload_codec`) on your `DataConverter` — `PydanticAIPlugin` preserves it, and it covers '
'every payload in both directions. '
'See https://ai.pydantic.dev/durable_execution/temporal/#large-payloads'
'See https://pydantic.dev/docs/ai/capabilities/durable_execution/temporal/#large-payloads'
) from exc
@@ -169,7 +169,7 @@ class Embedder:
If this isn't set, then the last value set by
[`Embedder.instrument_all()`][pydantic_ai.embeddings.Embedder.instrument_all]
will be used, which defaults to False.
See the [Debugging and Monitoring guide](https://ai.pydantic.dev/logfire/) for more info.
See the [Debugging and Monitoring guide](https://pydantic.dev/docs/ai/integrations/logfire/) for more info.
"""
_instrument_default: ClassVar[InstrumentationSettings | bool] = False
@@ -42,7 +42,7 @@ def instrument_embedding_model(model: EmbeddingModel, instrument: Instrumentatio
class InstrumentedEmbeddingModel(WrapperEmbeddingModel):
"""Embedding model which wraps another model so that requests are instrumented with OpenTelemetry.
See the [Debugging and Monitoring guide](https://ai.pydantic.dev/logfire/) for more info.
See the [Debugging and Monitoring guide](https://pydantic.dev/docs/ai/integrations/logfire/) for more info.
"""
instrumentation_settings: InstrumentationSettings
+1 -1
View File
@@ -461,7 +461,7 @@ class UsageLimitExceeded(AgentRunError):
_HINT = (
'Consider raising the limit, or see the docs on usage limits '
'for budget-aware patterns: https://ai.pydantic.dev/agent/#usage-limits'
'for budget-aware patterns: https://pydantic.dev/docs/ai/core-concepts/agent/#usage-limits'
)
def __init__(self, message: str):
+2 -2
View File
@@ -3958,7 +3958,7 @@ class ToolCallEvent:
args_valid: bool | None = None
"""Whether the tool arguments passed validation.
See the [custom validation docs](https://ai.pydantic.dev/tools-advanced/#args-validator) for more info.
See the [custom validation docs](https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#args-validator) for more info.
- `True`: Schema validation and custom validation (if configured) both passed; args are guaranteed valid.
- `False`: Validation was performed and failed.
@@ -4191,7 +4191,7 @@ class RealtimeOutputSpeechStartEvent:
"""The provider started playing the model's audio to the listener.
Only reported where the provider, rather than your code, holds the audio on its way to the
listener: on a [WebRTC sideband](../realtime/lifecycle.md#browser-webrtc) the media flows
listener: on a [WebRTC sideband](../realtime/deployment.md#browser-webrtc-server-sideband) the media flows
browser ↔ provider, so the session never sees audio and this is its only signal that the model has
become audible. An ordinary session owns the audio and knows when it starts playing it, so no
provider reports this there.
@@ -69,7 +69,7 @@ class InstrumentationSettings:
- [`Agent.instrument`][pydantic_ai.agent.Agent.instrument] / [`Agent.instrument_all()`][pydantic_ai.agent.Agent.instrument_all]
- [`InstrumentedModel`][pydantic_ai.models.instrumented.InstrumentedModel]
See the [Debugging and Monitoring guide](https://ai.pydantic.dev/logfire/) for more info.
See the [Debugging and Monitoring guide](https://pydantic.dev/docs/ai/integrations/logfire/) for more info.
"""
tracer: Tracer = field(repr=False)
@@ -333,7 +333,7 @@ class InstrumentationSettings:
class InstrumentedModel(WrapperModel):
"""Model which wraps another model so that requests are instrumented with OpenTelemetry.
See the [Debugging and Monitoring guide](https://ai.pydantic.dev/logfire/) for more info.
See the [Debugging and Monitoring guide](https://pydantic.dev/docs/ai/integrations/logfire/) for more info.
"""
instrumentation_settings: InstrumentationSettings
@@ -25,7 +25,7 @@ InterfaceClient = TypeVar('InterfaceClient', default=Any)
_KEYLESS_HINT = (
"To try Pydantic AI without an API key, use the built-in test model: `Agent('test')`. "
'See https://ai.pydantic.dev/testing/'
'See https://pydantic.dev/docs/ai/guides/testing/'
)
@@ -33,7 +33,7 @@ def missing_api_key_error(message: str) -> UserError:
"""Build a [`UserError`][pydantic_ai.exceptions.UserError] for missing provider credentials.
The provider-specific `message` (which environment variable to set or how to pass the key) is followed by a
hint pointing newcomers to the keyless [test model](https://ai.pydantic.dev/testing/), so a missing key never
hint pointing newcomers to the keyless [test model](https://pydantic.dev/docs/ai/guides/testing/), so a missing key never
dead-ends the getting-started experience.
"""
return UserError(f'{message} {_KEYLESS_HINT}')
@@ -98,7 +98,7 @@ class VercelProvider(_OpenAICompatibleProvider):
'or pass the API key via `VercelProvider(api_key=...)` to use the Vercel provider.'
)
default_headers = {'http-referer': 'https://ai.pydantic.dev/', 'x-title': 'pydantic-ai'}
default_headers = {'http-referer': 'https://pydantic.dev/docs/ai/', 'x-title': 'pydantic-ai'}
if openai_client is not None:
self._client = openai_client
+1 -1
View File
@@ -261,7 +261,7 @@ class ToolManager(Generic[AgentDepsT]):
if self.ctx.retries.get(name, 0) >= max_retries:
raise UnexpectedModelBehavior(
f'Tool {name!r} exceeded max retries count of {max_retries}. Consider raising the retry '
'limit, or see the docs on tool retries: https://ai.pydantic.dev/tools-advanced/#tool-retries'
'limit, or see the docs on tool retries: https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#tool-retries'
) from error
@staticmethod
+1 -1
View File
@@ -577,7 +577,7 @@ class ToolDefinition:
(Gemini 2.5+); Anthropic and Bedrock leave it off unless you explicitly set `strict=True`.
Note: this is currently supported by OpenAI, Anthropic, Google, and Bedrock models. See
[Strict Mode](https://ai.pydantic.dev/tools-advanced/#strict-mode) for the full per-provider table.
[Strict Mode](https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#strict-mode) for the full per-provider table.
"""
sequential: bool = False
@@ -15,7 +15,7 @@ from .abstract import AbstractToolset, ToolsetTool
class WrapperToolset(AbstractToolset[AgentDepsT]):
"""A toolset that wraps another toolset and delegates to it.
See [toolset docs](../toolsets.md#wrapping-a-toolset) for more information.
See [toolset docs](../toolsets.md#changing-tool-execution) for more information.
"""
wrapped: AbstractToolset[AgentDepsT]
+3 -3
View File
@@ -508,7 +508,7 @@ class UIAdapter(ABC, Generic[RunInputT, MessageT, EventT, AgentDepsT, OutputData
[`RunContext`][pydantic_ai.tools.RunContext]; merged with the agent's configured metadata.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
Use `capabilities=[NativeTool(...)]` to add provider-side native tools per request.
"""
if deferred_tool_results is None:
@@ -612,7 +612,7 @@ class UIAdapter(ABC, Generic[RunInputT, MessageT, EventT, AgentDepsT, OutputData
[`RunContext`][pydantic_ai.tools.RunContext]; merged with the agent's configured metadata.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
Use `capabilities=[NativeTool(...)]` to add provider-side native tools per request.
on_complete: Optional callback function called when the agent run completes successfully.
The callback receives the completed [`AgentRunResult`][pydantic_ai.agent.AgentRunResult] and can optionally yield additional protocol-specific events.
@@ -694,7 +694,7 @@ class UIAdapter(ABC, Generic[RunInputT, MessageT, EventT, AgentDepsT, OutputData
[`RunContext`][pydantic_ai.tools.RunContext]; merged with the agent's configured metadata.
infer_name: Whether to try to infer the agent name from the call frame if it's not set.
toolsets: Optional additional toolsets for this run.
capabilities: Optional additional [capabilities](https://ai.pydantic.dev/capabilities/overview/) for this run, merged with the agent's configured capabilities.
capabilities: Optional additional [capabilities](https://pydantic.dev/docs/ai/capabilities/overview/) for this run, merged with the agent's configured capabilities.
Use `capabilities=[NativeTool(...)]` to add provider-side native tools per request.
on_complete: Optional callback function called when the agent run completes successfully.
The callback receives the completed [`AgentRunResult`][pydantic_ai.agent.AgentRunResult] and can optionally yield additional protocol-specific events.
+1 -1
View File
@@ -51,7 +51,7 @@ requires-python = ">=3.10"
[project.urls]
Homepage = "https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim"
Source = "https://github.com/pydantic/pydantic-ai/tree/main/pydantic_ai_slim"
Documentation = "https://ai.pydantic.dev/install/#slim-install"
Documentation = "https://pydantic.dev/docs/ai/overview/install/#slim-install"
Changelog = "https://github.com/pydantic/pydantic-ai/releases"
[tool.hatch.metadata.hooks.uv-dynamic-versioning]
+5 -5
View File
@@ -9,14 +9,14 @@
This is a library for evaluating non-deterministic (or "stochastic") functions in Python. It provides a simple,
Pythonic interface for defining and running stochastic functions, and analyzing the results of running those functions.
While this library is developed as part of [Pydantic AI](https://ai.pydantic.dev), it only uses Pydantic AI for a small
While this library is developed as part of [Pydantic AI](https://pydantic.dev/docs/ai/), it only uses Pydantic AI for a small
subset of generative functionality internally, and it is designed to be used with arbitrary "stochastic function"
implementations. In particular, it can be used with other (non-Pydantic AI) AI libraries, agent frameworks, etc.
As with Pydantic AI, this library prioritizes type safety and use of common Python syntax over esoteric, domain-specific
use of Python syntax.
Full documentation is available at [ai.pydantic.dev/evals](https://ai.pydantic.dev/evals).
Full documentation is available at [pydantic.dev/docs/ai/evals](https://pydantic.dev/docs/ai/evals/evals/).
## Example
@@ -80,8 +80,8 @@ Pydantic Evals uses OpenTelemetry to record traces for each case in your evaluat
You can send these traces to any OpenTelemetry-compatible backend. For the best experience, we recommend [Pydantic Logfire](https://logfire.pydantic.dev/docs), which includes custom views for evals:
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
<img src="https://ai.pydantic.dev/img/logfire-evals-overview.png" alt="Logfire Evals Overview" width="48%">
<img src="https://ai.pydantic.dev/img/logfire-evals-case.png" alt="Logfire Evals Case View" width="48%">
<img src="https://pydantic.dev/docs/ai/img/logfire-evals-overview.png" alt="Logfire Evals Overview" width="48%">
<img src="https://pydantic.dev/docs/ai/img/logfire-evals-case.png" alt="Logfire Evals Case View" width="48%">
</div>
You'll see full details about the inputs, outputs, token usage, execution durations, etc. And you'll have access to the full trace for each case — ideal for debugging, writing path-aware evaluators, or running the similar evaluations against production traces.
@@ -102,4 +102,4 @@ logfire.configure(
my_dataset.evaluate_sync(my_task)
```
[Read more about the Logfire integration here.](https://ai.pydantic.dev/evals/#logfire-integration)
[Read more about the Logfire integration here.](https://pydantic.dev/docs/ai/evals/how-to/logfire-integration/)
@@ -152,7 +152,7 @@ def _add_context_span_exporter() -> _ContextInMemorySpanExporter | SpanTreeRecor
return SpanTreeRecordingError(
f'To make use of the `span_tree` in an evaluator, you need to call `{required_call}` before running an'
f' evaluation.'
f' For more information, refer to the documentation at https://ai.pydantic.dev/evals/#opentelemetry-integration.'
f' For more information, refer to the documentation at https://pydantic.dev/docs/ai/evals/evaluators/span-based/.'
)
else:
# Custom TracerProvider (e.g. ddtrace) without add_span_processor - degrade gracefully.
@@ -20,7 +20,7 @@ def _context_subtree_fallback() -> typing.Generator[SpanTree | SpanTreeRecording
'To make use of the `span_tree` in an evaluator, you must install `logfire` or'
' `opentelemetry-sdk`, configure appropriate instrumentations, and set a tracer provider (e.g. by calling'
' `logfire.configure()`).'
' For more information, refer to the documentation at https://ai.pydantic.dev/evals/#opentelemetry-integration.'
' For more information, refer to the documentation at https://pydantic.dev/docs/ai/evals/evaluators/span-based/.'
)
exc.__context__ = _IMPORT_ERROR
yield exc
+2 -2
View File
@@ -60,9 +60,9 @@ dependencies = [
logfire = ["logfire>=3.14.1"]
[project.urls]
Homepage = "https://ai.pydantic.dev/evals"
Homepage = "https://pydantic.dev/docs/ai/evals/evals/"
Source = "https://github.com/pydantic/pydantic-ai"
Documentation = "https://ai.pydantic.dev/evals"
Documentation = "https://pydantic.dev/docs/ai/evals/evals/"
Changelog = "https://github.com/pydantic/pydantic-ai/releases"
[tool.hatch.build.targets.wheel]
+2 -2
View File
@@ -8,14 +8,14 @@
Graph and finite state machine library.
This library is developed as part of [Pydantic AI](https://ai.pydantic.dev), however it has no dependency
This library is developed as part of [Pydantic AI](https://pydantic.dev/docs/ai/), however it has no dependency
on `pydantic-ai` or related packages and can be considered as a pure graph-based state machine library. You may find it useful whether or not you're using Pydantic AI or even building with GenAI.
As with Pydantic AI, this library prioritizes type safety and use of common Python syntax over esoteric, domain-specific use of Python syntax.
`pydantic-graph` allows you to define graphs using standard Python syntax. In particular, edges are defined using the return type hint of nodes.
Full documentation is available at [ai.pydantic.dev/graph](https://ai.pydantic.dev/graph).
Full documentation is available at [pydantic.dev/docs/ai/graph](https://pydantic.dev/docs/ai/graph/graph/).
Here's a basic example:
+2 -2
View File
@@ -55,9 +55,9 @@ dependencies = [
]
[project.urls]
Homepage = "https://ai.pydantic.dev/graph/tree/main/pydantic_graph"
Homepage = "https://pydantic.dev/docs/ai/graph/graph/"
Source = "https://github.com/pydantic/pydantic-ai"
Documentation = "https://ai.pydantic.dev/graph"
Documentation = "https://pydantic.dev/docs/ai/graph/graph/"
Changelog = "https://github.com/pydantic/pydantic-ai/releases"
[tool.hatch.build.targets.wheel]
+2 -2
View File
@@ -86,9 +86,9 @@ google-realtime = ["pydantic-ai-slim[google-realtime]=={{ version }}"]
xai-realtime = ["pydantic-ai-slim[xai-realtime]=={{ version }}"]
[project.urls]
Homepage = "https://ai.pydantic.dev"
Homepage = "https://pydantic.dev/docs/ai/"
Source = "https://github.com/pydantic/pydantic-ai"
Documentation = "https://ai.pydantic.dev"
Documentation = "https://pydantic.dev/docs/ai/"
Changelog = "https://github.com/pydantic/pydantic-ai/releases"
[project.scripts]
+1 -1
View File
@@ -968,7 +968,7 @@ async def test_context_subtree_not_configured(mocker: MockerFixture):
'To make use of the `span_tree` in an evaluator, you need to call '
'`logfire.configure(...)` before running an evaluation. For more information, '
'refer to the documentation at '
'https://ai.pydantic.dev/evals/#opentelemetry-integration.'
'https://pydantic.dev/docs/ai/evals/evaluators/span-based/.'
)
+1 -3
View File
@@ -8,7 +8,6 @@ from inline_snapshot import snapshot
from vcr.cassette import Cassette
from pydantic_ai import Agent, BinaryImage, ModelRequest, ModelResponse, TextPart, ThinkingPart, UserPromptPart
from pydantic_ai._warnings import PydanticAIDeprecationWarning
from pydantic_ai.direct import model_request
from pydantic_ai.messages import ModelMessage
from pydantic_ai.run import AgentRunResult, AgentRunResultEvent
@@ -231,8 +230,7 @@ async def test_zai_glm_5_3_reasoning_effort(
during playback, since VCR matchers aren't sensitive to the body. The full effort mapping is unit-tested
in `test_zai_glm_5_3_reasoning_effort_mapping`.
"""
with pytest.warns(PydanticAIDeprecationWarning, match='httpx2.AsyncClient'):
provider = ZaiProvider(api_key=zai_api_key, http_client=request_capture.client)
provider = ZaiProvider(api_key=zai_api_key, http_client=request_capture.client)
model = ZaiModel('glm-5.3', provider=provider)
settings = ModelSettings(thinking='xhigh')
response = await model_request(model, [ModelRequest.user_text_prompt('What is 2 + 2?')], model_settings=settings)
+1 -1
View File
@@ -105,7 +105,7 @@ def test_exceptions_hashable(exc_factory: Callable[[], Any]):
lambda: UsageLimitExceeded('limit hit'),
{
'message': 'limit hit. Consider raising the limit, or see the docs on usage limits '
'for budget-aware patterns: https://ai.pydantic.dev/agent/#usage-limits'
'for budget-aware patterns: https://pydantic.dev/docs/ai/core-concepts/agent/#usage-limits'
},
),
(lambda: ConcurrencyLimitExceeded('too many'), {'message': 'too many'}),
+2 -2
View File
@@ -4110,7 +4110,7 @@ async def test_oversized_tool_return_payload(client: Client):
with workflow_raises(
UserError,
snapshot(
"Tool 'get_oversized_image' returned a result too large for Temporal. [TMPRL1103] Attempted to upload payloads with size that exceeded the error limit. Size: 2133494 bytes, Limit: 2097152 bytes. Binary content like an image is base64-encoded into the activity payload, so if that is the cause, the raw-byte budget is about three quarters of the limit — roughly 1.5MB at the 2MB default. Return a reference instead of the value itself, like a URL or a key your application resolves later. To keep large payloads out of the workflow history without changing what your tools or models return, configure Temporal external storage (or a claim-check `payload_codec`) on your `DataConverter` — `PydanticAIPlugin` preserves it, and it covers every payload in both directions. See https://ai.pydantic.dev/durable_execution/temporal/#large-payloads"
"Tool 'get_oversized_image' returned a result too large for Temporal. [TMPRL1103] Attempted to upload payloads with size that exceeded the error limit. Size: 2133494 bytes, Limit: 2097152 bytes. Binary content like an image is base64-encoded into the activity payload, so if that is the cause, the raw-byte budget is about three quarters of the limit — roughly 1.5MB at the 2MB default. Return a reference instead of the value itself, like a URL or a key your application resolves later. To keep large payloads out of the workflow history without changing what your tools or models return, configure Temporal external storage (or a claim-check `payload_codec`) on your `DataConverter` — `PydanticAIPlugin` preserves it, and it covers every payload in both directions. See https://pydantic.dev/docs/ai/capabilities/durable_execution/temporal/#large-payloads"
),
):
await client.execute_workflow(
@@ -4164,7 +4164,7 @@ async def test_oversized_model_response_payload(client: Client):
with workflow_raises(
UserError,
snapshot(
"The response from model 'function:oversized-response-model' is too large for Temporal. [TMPRL1103] Attempted to upload payloads with size that exceeded the error limit. Size: 2134150 bytes, Limit: 2097152 bytes. Binary content like an image is base64-encoded into the activity payload, so if that is the cause, the raw-byte budget is about three quarters of the limit — roughly 1.5MB at the 2MB default. A generated image is the usual cause, so ask the model for a smaller one through the model settings; a streamed segment can also overflow on its buffered events alone. To keep large payloads out of the workflow history without changing what your tools or models return, configure Temporal external storage (or a claim-check `payload_codec`) on your `DataConverter` — `PydanticAIPlugin` preserves it, and it covers every payload in both directions. See https://ai.pydantic.dev/durable_execution/temporal/#large-payloads"
"The response from model 'function:oversized-response-model' is too large for Temporal. [TMPRL1103] Attempted to upload payloads with size that exceeded the error limit. Size: 2134150 bytes, Limit: 2097152 bytes. Binary content like an image is base64-encoded into the activity payload, so if that is the cause, the raw-byte budget is about three quarters of the limit — roughly 1.5MB at the 2MB default. A generated image is the usual cause, so ask the model for a smaller one through the model settings; a streamed segment can also overflow on its buffered events alone. To keep large payloads out of the workflow history without changing what your tools or models return, configure Temporal external storage (or a claim-check `payload_codec`) on your `DataConverter` — `PydanticAIPlugin` preserves it, and it covers every payload in both directions. See https://pydantic.dev/docs/ai/capabilities/durable_execution/temporal/#large-payloads"
),
):
await client.execute_workflow(
+1 -1
View File
@@ -846,7 +846,7 @@ async def test_run_stream_response_error():
'<request>',
"<function-tool-call name='unknown_tool'>None</function-tool-call>",
"<function-tool-result name='unknown_tool'>Tool execution was interrupted by an error.</function-tool-result>",
"<error type='UnexpectedModelBehavior'>Tool 'unknown_tool' exceeded max retries count of 1. Consider raising the retry limit, or see the docs on tool retries: https://ai.pydantic.dev/tools-advanced/#tool-retries</error>",
"<error type='UnexpectedModelBehavior'>Tool 'unknown_tool' exceeded max retries count of 1. Consider raising the retry limit, or see the docs on tool retries: https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#tool-retries</error>",
'</request>',
'</stream>',
]
+1 -1
View File
@@ -2741,7 +2741,7 @@ Fix the errors and try again.\
},
{
'type': 'error',
'errorText': "Tool 'unknown_tool' exceeded max retries count of 1. Consider raising the retry limit, or see the docs on tool retries: https://ai.pydantic.dev/tools-advanced/#tool-retries",
'errorText': "Tool 'unknown_tool' exceeded max retries count of 1. Consider raising the retry limit, or see the docs on tool retries: https://pydantic.dev/docs/ai/tools-toolsets/tools-advanced/#tool-retries",
},
{'type': 'finish-step'},
{'type': 'finish', 'finishReason': 'error'},