You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds pydantic_ai_class_deep_dives_v2_46.md — 10 source-verified class deep dives verified against pydantic-ai 2.46.0 (installed from PyPI, sources read directly)
Updates index.mdx: version badge 2.43.0 → 2.46.0, new LinkCard in Reference grid, What's new table, revision history row
Updates pydantic_ai_comprehensive_guide.md: version marker 2.43.0 → 2.46.0
- sequential=True: was described as "model must call tools one at a time";
correct semantics are execution serialization (barrier — no overlap
within a step). Replace contrived pipeline example with shared-state
counter that actually benefits from barrier semantics.
- defer_loading=True: was described as "lazy schema generation"; correct
semantics are that tools are HIDDEN from the model until discovered via
tool search, load_capability, or ToolReturn.tools. Rewrite example and
explanation accordingly.
- AdvisorTool OpenRouter example: passed model= twice (positional string
+ keyword OpenRouterProvider()), causing TypeError. Fix by using
openrouter:-prefixed model strings and dropping the redundant provider
kwarg.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
- defer_loading bullet: fix description to say "hide tools until
discovered" not "defer schema loading until first use"
- NativeOutput union strict: change strict=True to strict=False;
undiscriminated root union is rejected by OpenAI strict schemas
- Default output mode comment: drop "implicit ToolOutput" claim;
agent selects mode from model profile
- StructuredDict signature: fix return annotation type[JsonSchemaValue]
-> type[dict[str, Any]] (actual runtime type)
- AdvisorTool signature: remove non-existent system_prompt and
on_advisor_turn fields; add caching field that actually exists
- All AdvisorTool examples: replace native_tools=[advisor] with
capabilities=[advisor] (Agent has no native_tools= parameter)
- Example 2: replace on_advisor_turn callback example (param doesn't
exist) with caching='5m' ephemeral context cache example
- OpenRouter example: drop unused OpenRouterProvider import; use
bare OpenRouter catalog slug for advisor model
- comprehensive_guide.md stamp: clarify 2.46.0 classes are in the
companion guide, not in this file's addendum
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
- EmbeddingResult.normalised_embeddings(): method does not exist;
replace with manual normalisation from result.embeddings
- MCPToolset cache_tools default: was False in doc, actual default
is True; update signature block, parameter table, and example
- MCPToolset allowed_tools: param does not exist; replace with
FilteredToolset(raw, lambda tool: ...) pattern which is correct
- MCPToolset constructor note: add FilteredToolset to Example 4
heading and clarify the allowlist belongs at the toolset layer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
strict=True with [Fruit, Vehicle] creates an undifferentiated root union, which strict structured-output providers reject when the schema contains a root anyOf/oneOf without a discriminator. As written, this advertised runnable example can fail before the model call; remove strict mode or add a discriminator.
These fields do not match the current AdvisorTool constructor: the repository's API reference lists model, max_uses, max_tokens, and caching, but not system_prompt or on_advisor_turn. Keeping them here makes the following examples appear source-verified while failing at construction.
Native tool specs must be registered through capabilities=[NativeTool(...)]; Agent does not accept a native_tools keyword in this API. As written, this example raises TypeError before it can run, so wrap the advisor with NativeTool and pass it via capabilities.
This issue also appears in the following locations of the same file:
line 1429
line 1453
Describe ToolOutput as an explicit tool-based output option
output_type=SomeModel is not implicitly ToolOutput here: PydanticAI selects the output mode from the model profile, which may be native or prompted. Calling ToolOutput the default makes the selection behavior inaccurate; describe it as the explicit tool-based option instead.
…ing)
The defer_loading example did not show how hidden tools are discovered.
ToolSearch is auto-injected into every agent but passing it explicitly
clarifies the discovery mechanism and allows strategy configuration.
Add ToolSearch() to capabilities= and expand the prose to explain
auto-injection, provider-native search, and local fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
- FilteredToolset predicate: lambda accepted one arg but signature is
(RunContext, ToolDefinition); fix lambda to (lambda _ctx, tool: ...)
- logit_bias token_ids: was using cl100k_base hardcoded tokenizer which
doesn't match gpt-5; use tiktoken.encoding_for_model(model) to derive
IDs from the exact model's vocabulary
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
MCPServerHTTP is not the legacy class named elsewhere in this guide; the removed transport classes are MCPServer, MCPServerStdio, MCPServerSSE, and MCPServerStreamableHTTP. As written, this paragraph names a nonexistent API and omits the actual SSE/streamable-HTTP names.
AdvisorTool extends AbstractNativeTool, not AbstractCapability, so
capabilities=[advisor] does not register it correctly at runtime.
All three AdvisorTool examples now import NativeTool from
pydantic_ai.capabilities and pass NativeTool(advisor).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
allowed_tools is advertised as a v2.46.0 MCPToolset addition in this PR, but this section explicitly says the parameter does not exist and directs users to a wrapper instead. Please verify the installed signature and document the actual allowlist behavior; as written, the page contradicts the API it claims to cover.
Clarify ToolOutput as an explicit tool-call strategy
Calling ToolOutput the default here conflicts with the later guidance in this page and with the documented Agent behavior: a bare Pydantic type selects tool/native/prompted mode from the model profile. Please describe ToolOutput as the explicit tool-call strategy so readers do not assume it is always the default.
The legacy MCP class name here is incorrect: the repository's MCP reference names the removed classes as MCPServerStdio, MCPServerSSE, and MCPServerStreamableHTTP; MCPServerHTTP is not the old API name. Correcting this matters because readers may search for or migrate from a class that never existed.
…alls
- defer_loading example: remove claim that ToolSearch is auto-injected;
describe it as a capability that must be added explicitly, since both
Codex and Copilot flag the auto-injection claim as inaccurate for
default agent configurations
- parallel_tool_calls: reframe description from 'ordering matters' to
'limits fan-out' — the setting caps calls per response to one but
does not control which tool the model invokes first; update step_b
docstring to remove the misleading 'depends on A' ordering claim
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
The PR description lists allowed_tools as a 2.46.0 MCPToolset addition, but this page says the class has no such parameter. The comprehensive reference exposes allowed_tools on the separate MCP capability; reconcile the description and this section so readers know which API supports it.
Reconcile on_advisor_turn documentation with source
The PR description advertises on_advisor_turn as a v2.46.0 AdvisorTool addition, but this source-verified signature and all examples omit it. Please reconcile that claim with the page/source so consumers know whether the callback exists and how to configure it.
This executor model string lacks the anthropic: provider prefix. Agent model examples in this guide use provider-qualified IDs, so the bare Claude name can be inferred under the wrong provider instead of using Anthropic; prefix it before presenting this as runnable code.
This issue also appears on line 1438 of the same file.
Document ResponseRejected in handler failure summary
The failure summary omits response-handler rejection: when a handler rejects every response, the exception group contains ResponseRejected, so except* ModelAPIError alone will not catch that path. Please document that type alongside the exception-handler failures.
parallel_tool_calls=False prevents multiple tool calls in one model response, but it does not make the model choose step_a before step_b across separate turns. The current wording and example imply an ordering guarantee that this setting does not provide; ordering needs an explicit application/tool-state constraint.
This Agent model string omits the provider prefix. PydanticAI resolves provider-backed model strings in provider:model-name form, so the bare Claude ID will not select Anthropic as shown in the example. Use the anthropic:-prefixed form here.
This issue also appears on line 1438 of the same file.
MCPServerHTTP is not one of the legacy classes documented for this API; the removed classes are MCPServer, MCPServerStdio, MCPServerSSE, and MCPServerStreamableHTTP. Naming the nonexistent class makes it harder for readers to migrate from the actual API. Replace it with the real class names.
… comment
- Rename response handler fn response_is_empty → response_too_short and
update docstring; the predicate only catches very-short responses, not
refusals like "I cannot help with that" (which are >10 chars and would
not trigger fallback)
- Update section heading: "skip empty or refused answers" → "skip empty
answers" to match what the code actually does
- Change Ollama PromptedOutput example comment from "# no JSON mode
support" (wrong for self-hosted Ollama) to "# PromptedOutput works on
any model, including self-hosted Ollama"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
The PR description advertises allowed_tools as a v2.46.0 MCPToolset addition, while this page explicitly says MCPToolset has no such parameter and presents FilteredToolset instead. Reconcile the summary with the verified API (or document the actual allowed_tools surface) so the release notes do not promise a nonexistent constructor argument.
This issue also appears on line 1382 of the same file.
MCPServerHTTP is not the legacy Pydantic AI type used for the HTTP transport; the documented names are MCPServerSSE and MCPServerStreamableHTTP (alongside MCPServerStdio). Using MCPServerHTTP here sends readers searching for a class that does not exist.
Replace nonexistent MCPServerHTTP with the real removed class names:
MCPServerSSE and MCPServerStreamableHTTP (alongside MCPServerStdio).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
sequential=True only prevents overlap among calls in the same model step; it is not a lock around the module-level counter_state across concurrent runs. Two simultaneous agent.run_sync/run calls can still race, so saying this prevents shared-state race conditions is too broad.
StructuredDict cannot infer the Python variable name PersonDict; this call does not pass name, and the schema title is Person. The displayed <class 'PersonDict'> is therefore misleading. Pass an explicit name or update the output comment.
- sequential=True: qualify race-condition claim as intra-step only;
add note that concurrent agent.run() calls need an external lock
- StructuredDict Example 1: pass name='PersonDict' explicitly so the
type(result.output) comment is accurate (without name=, title from
schema is used, which would be 'Person' not 'PersonDict')
- AdvisorTool examples: add anthropic: prefix to Agent executor model
strings ('anthropic:claude-haiku-4-5-20251001') — AdvisorTool.model
correctly keeps bare Anthropic IDs per its docstring
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
OpenAI's response-format JSON-schema name only allows letters, digits,
underscores, and hyphens — spaces cause the request to be rejected.
Change 'Fruit or vehicle' -> 'fruit_or_vehicle'; readable wording is
already in the description field.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
The documented default does not match the 2.46.0 constructor: the current API reference shows tools=() (see pydantic_ai_comprehensive_guide.md:3709-3715). Since this is presented as the source signature, use the empty tuple rather than a mutable-list default so readers do not copy an API signature that is not actually present.
Clarify ToolOutput is an explicit tool-call option
ToolOutput is not the default for every Pydantic output: a bare output type is resolved from the model profile and may select native, tool, or prompted mode (as the later rule-of-thumb section explains). Reword this cell as the explicit tool-call option to avoid contradicting the page's actual default behavior.
…description
- FilteredToolset example: replace deny-by-prefix predicate with an
explicit allowlist (TRUSTED_TOOLS set). The old 'not startswith'
approach would silently expose any future tool whose name doesn't
start with 'create', which is unsafe for untrusted-user scenarios.
- Output quartet table: reword ToolOutput row from 'Default for Pydantic
models' to 'Explicit tool-call strategy' — a bare output_type selects
mode from the model profile, so calling ToolOutput the default
contradicted the page's own rule-of-thumb section.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
…orrections
- FallbackModel: pass handlers as lists/bare callables; a tuple is always
parsed as exception types, so tuple-wrapped handlers raised TypeError or
were silently ignored. Add a gotcha note.
- TextOutput(str.upper) fails at Agent construction; use a def function.
- StructuredDict output type prints <class 'dict'>, not PersonDict.
- ToolSearch is auto-injected; explicit use only configures it.
- CombinedToolset raises on any name clash; prefixing renames to avoid it.
Verified against pydantic-ai 2.46.0 with FunctionModel/TestModel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UbuuyLymfkxVYM5kGzDV53
This describes parallel_tool_calls=False as an unconditional runtime guarantee, but ModelSettings is cross-provider and unsupported keys are silently ignored; the comprehensive guide documents that contract at pydantic_ai_comprehensive_guide.md:2988. Qualify this behavior by saying it applies only to providers whose adapter supports the setting.
parallel_tool_calls=False is silently ignored by providers whose
adapter does not support the setting. Add a note so readers know
to verify their target provider before relying on the behavior.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
load_capability loads deferred capabilities, not deferred tools from a FunctionToolset. With defer_loading=True, this toolset's tools are discovered through the ToolSearch path; as written, this bullet sends readers to a loader that cannot load this toolset. Remove the load_capability reference or document a separate capability wrapper.
Clarify prefer_tasks has no effect with FastMCP 4 servers
For this FastMCP 4 integration, the prefer_tasks description is misleading: the 2.46.0 MCPToolset source says this preference is a FastMCP 3/SEP-1686 client-side behavior and has no effect for FastMCP 4 servers, which direct task creation themselves. Add that caveat so users do not rely on this flag for FastMCP 4 task routing.
Lifecycle delegation example uses non-dynamic child toolsets
This section claims to demonstrate for_run/for_run_step delegation, but both children are ordinary FunctionToolset instances and step_counter only reads ctx.run_step; no child overrides either lifecycle hook or refreshes its tools. As written, the example cannot demonstrate the behavior described. Use a genuinely dynamic child toolset or reframe this as a basic composition example.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pydantic_ai_class_deep_dives_v2_46.md— 10 source-verified class deep dives verified against pydantic-ai 2.46.0 (installed from PyPI, sources read directly)index.mdx: version badge 2.43.0 → 2.46.0, new LinkCard in Reference grid, What's new table, revision history rowpydantic_ai_comprehensive_guide.md: version marker 2.43.0 → 2.46.0Classes documented (with 3–5 runnable code examples each)
FallbackModelmodels.fallbackfallback_onwith exception types, async exception handlers, response handlers (ModelResponse-typed callables)FunctionToolsettoolsets.functioninstructions,defer_loading,sequential,requires_approval,id,metadataoutputTextOutput,ToolOutput,NativeOutput,PromptedOutput— comparison table and when-to-use guidanceEmbedder+EmbeddingResultembeddingsEmbeddingResultfields (embeddings,model_name,usage,cost()),instrument_allMCPToolsetv2.46.0mcptool_error_behavior,prefer_tasks,cache_tools; allowlisting viaFilteredToolsetwrapperload_mcp_toolsetsmcpmcpServersconfig, env var${VAR:-default}expansion, prefix wrappingCombinedToolsettoolsets.combinedFilteredToolset,for_rundelegationStructuredDictoutput$defsinlining, union with Pydantic modelsModelSettingslesser-known fieldssettingsparallel_tool_calls,seed,stop_sequences,extra_headers,presence_penalty,logit_bias,extra_bodyAdvisorToolnative_toolsmax_uses,max_tokens,caching, OpenRouter gatewaySources read directly from installed package
pydantic_ai/models/fallback.pypydantic_ai/toolsets/function.pypydantic_ai/output.pypydantic_ai/embeddings/base.py+__init__.pypydantic_ai/mcp.pypydantic_ai/toolsets/combined.pypydantic_ai/settings.pypydantic_ai/native_tools/__init__.py🤖 Generated with Claude Code
https://claude.ai/code/session_01SETmwsc9jV6MkjZfXWQq9J
Generated by Claude Code