NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #1649 most downloaded on PyPI
AI Agent Framework, the Pydantic way
Last release 2 days ago
03 Oct 2026
Ships on a steady schedule
a new release about every 9 days
Nearly every release is documented
notes for 60 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
2 years old
344 releases · first in 2024
Handle draft-7 list-form items in JsonSchemaTransformer , TestModel and Mistral streamed output, and make TestModel accept boolean subschemas and cap
items in JsonSchemaTransformer, TestModel and Mistral streamed output, and make TestModel accept boolean subschemas and cap prefixItems at maxItems by @dsfaccini in #9560ImageGeneration under FallbackModel and dataclasses.replace, and compare Embedder by identity by @dsfaccini in #9477wrap_* hooks enclose complete stage lifecycles by @adtyavrdhn in #7053BackgroundTools tool raises an unexpected exception, as a sequential tool does by @DouweM in #9434SubAgents agent_folders default-change warning: since v2.52.0 (#9023) the agents folder is not loaded by default, so pass agent_folders='agents' to keep loading it by @DouweM in #9424clai2 file diffs from the selected /theme palette by @mpfaffenberger in #9648clai2 /update always install the newest build and restart into it, resuming the session by @mpfaffenberger in #9659RepoContext inventory by default by @DouweM in #9382CodeMode missing-return-schema warning its own CodeModeReturnSchemaWarning category by @DouweM in #9423cancel_and_resume example: cancel and resume a streaming run by @DouweM in #7012OpenAILiveModel sessions by forking a stored session or replaying the history by @DouweM in #9401create_async_httpx2_client() public by @DouweM in #9600gpt-live-transcribe for OpenAI realtime's default input_transcription_model='auto' and list gpt-transcribe by @DouweM in #9402WebSearchTool on OpenAI GPT-Live through its delegated backend by @DouweM in #9049native to ExaSearch and YouSearch to prefer the model's native web search, and web_search_tool() for WebSearch(local=...) by @DouweM in #9386Esc conversation rewind menu to clai2 by @mpfaffenberger in #9688clai2 /model menu by @mpfaffenberger in #9696realpath fallback when readlink cannot read a symlink by @dsfaccini in #9613sniffio package in pydantic-evals and pydantic-ai-harness by @pydanty in #9620ImageGenerationTool to the local tool on Gemini text models, and keep tool output when a native tool falls back locally on Gemini 2.5 by @dsfaccini in #9551clai2 resume sidebar by @mpfaffenberger in #9667clai2 resume-directory confirmation by @mpfaffenberger in #9682clai2 startup plugin failures through observability by @mpfaffenberger in #9681clai2 tool output by @mpfaffenberger in #9687null finish_reason on a SnowflakeModel response like an empty one by @DouweM in #9590LocalFileStore root another user owns, and log ToolOutputLimits spill and summarize fallbacks by @DouweM in #9020ConversationSearch default-scope warning will be removed by @DouweM in #9383read_only=True removes every hosted MCP tool by @DouweM in #9387TrajectoryJudge window by @DouweM in #9425search_tools tool by its tool_kind instead of its name by @DouweM in #9603CodeMode by its tool_kind, so a prefixed search tool still gets its notes by @DouweM in #9604LLMReminder generation failures instead of silently falling back to GoalReanchor text by @DouweM in #9024run_stream() usage by @DouweM in #9694ModelResponse from streamed and complete GoogleModel responses, and add Gemini 3 web search sources by @DouweM in #9594RunCancelled.from_cancellation() when a DBOS workflow is cancelled by @DouweM in #9394setup_logfire callbacks replay-safe and add replay_safe to LogfirePlugin by @DouweM in #9698ModelAPIError for undecodable 200 response bodies from Anthropic, Bedrock, Groq, Hugging Face, Google, and OpenAI embeddings and images by @DouweM in #9350run_sync() by @DouweM in #9605audio_output_sample_rate by @DouweM in #9399load_capability is called twice for it in one response by @DouweM in #9397ToolAvailabilityDeltaPart announcement out of the standing system prompt by @DouweM in #9413clai2 archive updates by @mpfaffenberger in #9690OpenAIChatModel streams by @pydanty in #8729PKCESignIn.token() when another clai2 session saved one without a refresh token by @dsfaccini in #9670BubblewrapWorkspace commands from running code on the SSH host through shell startup files or the SSHWorkspaceBackend stop script's PATH (VERIA-212) by @mpfaffenberger in #9673Full Changelog: v2.53.0...v2.54.0
One column per month.
Move session naming into clai2 and deprecate pydantic_ai_harness.step_persistence.naming by @mpfaffenberger in #9499
This release fixes one security issue in ConcurrencyLimitedModel. See the advisory for full details and affected versions.
ConcurrencyLimitedModel or limit_model_concurrency could keep its concurrency slot when the slot was released on a different task than the one that acquired it: after an early exit (the consumer stopped iterating, raised, or was cancelled), and also after fully consuming stream_text() with its default debouncing. Repeated streams could then block every request sharing the limiter. Agent-level max_concurrency and non-streaming requests are not affected. Reported by @lche511. (#9478)The fix also changes how limiters are shared: a model wrapper now raises UserError when it shares a limiter with the agent making the request or with an enclosing model wrapper, ConcurrencyLimiter.acquire() takes a slot on every call, even on the same task, and a custom AbstractConcurrencyLimiter must allow release() from another task.
Patched in 2.53.0. v1 is not affected.
oneOf schema support to TestModel's generated data by @pydanty in #8783clai2 plugins declarative Plugin subclasses, modeled on AbstractCapability by @mpfaffenberger in #9493clai2 and deprecate pydantic_ai_harness.step_persistence.naming by @mpfaffenberger in #9499posthog plugin to pydantic-clai2 with /keys or browser sign-in by @mpfaffenberger in #8901grain plugin to clai2 with a keyring-backed Grain sign-in by @mpfaffenberger in #8905linear plugin to clai2 with a settings menu and /keys credentials by @mpfaffenberger in #8949usage by @pydanty in #8891AbsurdDurability to the harness as a replacement for pydantic-ai-absurd by @adtyavrdhn in #8946host.model_provider by @mpfaffenberger in #9468clai2 status row by @mpfaffenberger in #9473pydantic-clai2 by @mpfaffenberger in #9467clai2 by @mpfaffenberger in #9480AskUser defer questions to the host and time out a slow answerer by @mpfaffenberger in #9509/fast command to CLAI2 by @mpfaffenberger in #9518SystemOneModel to run decision models such as CLM and Laya over the /v1/systemone API by @mpfaffenberger in #8942logfire plugin to observability by @mpfaffenberger in #9566ToolCallJudge to assess tool calls before execution by @DouweM in #9041observability (Logfire) plugin by @mpfaffenberger in #9306/update with stable (PyPI) and bleeding (main) channels by @mpfaffenberger in #9576/plugins menu themed and readable, with plugin descriptions by @mpfaffenberger in #9570clai2 plugin settings with the features they need, and skip a plugin capability that rejects its settings at run setup by @mpfaffenberger in #9569repair_messages by @DouweM in #8370LocalWorkspaceBackend.run timeout fires during process startup by @dsfaccini in #9358clai-NAME and reopen existing worktrees with --worktree NAME by @mpfaffenberger in #9462CodeMode analysis by @mpfaffenberger in #9475clai2 resume sessions by repository identity by @mpfaffenberger in #9482Memory toolset across runs so durable execution accepts it by @mpfaffenberger in #9489Planning toolset across runs so durable execution accepts it by @mpfaffenberger in #9507BubblewrapSandbox on the next launch by @dsfaccini in #9457inf/-inf/nan by @pydanty in #8852gemini-3.1-flash-image thinking efforts to minimal and high on the Gemini API by @dsfaccini in #9515UnexpectedModelBehavior instead of running the wrong tool when function tool calls share a tool_call_id by @pydanty in #8782/reload hits a stale Harness import by @mpfaffenberger in #9571XaiModel thinking part per output, matching the non-streamed response by @DouweM in #9416OpenAIResponsesModel replay when openai_store=False by @DouweM in #9388ModelResponse from streamed and complete OpenAIChatModel and OpenRouterModel responses by @DouweM in #9418OpenAIResponsesModel build the same ModelResponse from a stream as from a complete response by @DouweM in #9417commit_audio() alone no longer triggers a reply, and create_response() is always answered by @DouweM in #9070status, status_details and session values the SDK does not know yet by @DouweM in #9392SubAgents from forcing thinking on disk agents by @DouweM in #9384DynamicWorkflow reveal announcements after compaction or history loss by @DouweM in #9371/compact by @mpfaffenberger in #9587clai2 when capability functions supply none, and expose unrestricted_filesystem in /plugins configure coder by @mpfaffenberger in #9593ActivityConfig schema by @pydanty in #9577GoogleRealtimeModel declare tools whose dict values are recursive models by @dsfaccini in #9607termflow-md 0.11.0 by @mpfaffenberger in #9483Full Changelog: v2.52.0...v2.53.0
Stop SubAgents loading agent files by default, and deprecate inherit_tools by @DouweM in #9023
This release fixes one security issue in web_fetch. See the advisory for full details and affected versions.
web_fetch tool could consume excessive CPU and memory. Provider-native web fetching is not affected. Reported by @SounLabs. (#8984)Patched in 2.52.0 (v2) and 1.107.7 (v1).
pydantic-ai-harness now lives in this repository and ships with every Pydantic AI release, so it jumps from 0.36.0 to 0.52.0. pydantic-clai2 0.52.0 is its first release: uvx pydantic-clai2.
Coder, FileSystem, Shell and the rest work through ctx.workspace, locally or in a sandbox by @adtyavrdhn in #8866ModalSandbox's own tools with a Modal workspace, so Coder, Shell and FileSystem run in the sandbox; ModalSandboxBackend replaces ModalSandboxSession by @adtyavrdhn in #8867AnthropicModel's default max_tokens from 4096 to 16384 on Claude Sonnet 4.5 and later by @DouweM in #9025DecisionModel's judged text after a retry by @dsfaccini in #8967SubAgents loading agent files by default, and deprecate inherit_tools by @DouweM in #9023AnthropicModel's max_tokens to the model's maximum output, streaming such requests behind the scenes by @DouweM in #9298ctx.workspace gives tools one API for files and commands, on your machine or in a sandbox, with durable execution support by @adtyavrdhn in #6492SpritesSandbox: a workspace that runs Coder, Shell, FileSystem and every other harness capability in a Fly.io Sprite by @adtyavrdhn in #8869E2BSandbox: a workspace that runs Coder, Shell, FileSystem and every other harness capability in an E2B sandbox by @adtyavrdhn in #8868Coder file tools a retry budget of 5 and keep scratch files out of the project by @mpfaffenberger in #8970typesafe extra to pydantic-clai2 and reject models with a missing provider SDK at /model time by @mpfaffenberger in #8962claude-sonnet-5-5) support by @dsfaccini in #8974async_tool_call_mode with a shared async_tool_calls setting by @DouweM in #8813pydantic-clai2 tool headers, clipped by display.tool_arg_chars by @mpfaffenberger in #9100clai2 plugin's settings menu when it is turned on, and end every settings menu with Save & close by @mpfaffenberger in #9102_process_provider_details hook to OpenAIResponsesModel by @pydanty in #9094clai2 --agent MODULE:ATTR to chat with an existing Agent with plugins off by @mpfaffenberger in #9291github plugin to clai2 with a settings menu and its token in /keys by @mpfaffenberger in #8904pylon plugin to CLAI2 with a settings menu and a named /keys entry by @mpfaffenberger in #8953gemini-3.1-flash-live-preview and gemini-3.8-live by @DouweM in #9047answer_webrtc_offer and a sideband session by @DouweM in #9059SSHWorkspace and BubblewrapSandbox harness capabilities by @mpfaffenberger in #8956pydantic-clai2 console script so uvx pydantic-clai2 runs CLAI by @mpfaffenberger in #9304azure_voice_live_voice to choose an Azure voice for Azure AI Voice Live sessions by @DouweM in #9044google_workspace as a built-in clai2 plugin backed by harness GoogleWorkspace by @mpfaffenberger in #8907thinking, openai_turn_detection, openai_input_noise_reduction and a new azure_voice_live_temperature on Azure AI Voice Live by @DouweM in #9051gemini-3.8-live by @DouweM in #9058day_ai plugin to clai2 with a settings menu and /keys or browser sign-in by @mpfaffenberger in #8940RequestUsage.extract() failures by @adtyavrdhn in #8564ordinal plugin to clai2 with token or keyring-backed browser sign-in by @mpfaffenberger in #8941default_cache_retention + prompt_cache_outlook() cold-window helper; rename resolve_prompt_cache_retention() to resolve_cache_retention() by @DouweM in #6337notion plugin to clai2 with a settings menu and its key in /keys by @mpfaffenberger in #8944thinking and parallel_tool_calls settings to the GPT-Live backend model by @DouweM in #9040mxfp4, nvfp4, and mxfp8 OpenRouter quantizations and the exacto sort value by @harimaruthachalam in #8888slack plugin to pydantic-clai2 with a settings menu, /keys user token, or browser sign-in by @mpfaffenberger in #8908logfire_mcp built-in plugin to clai2 with /keys, LOGFIRE_API_KEY, and keyring-backed OAuth by @mpfaffenberger in #8903gpt-6.1-sol model support and allow image output on gpt-6-astra by @dsfaccini in #9305application/toml as text-like for inline model inputs by @JoeyTan21 in #8848wait_for_reply() hanging on merged or failed replies by @DouweM in #8765ModelProfile so they apply on every provider route by @DouweM in #8808RealtimeTurnCompleteEvent before the spoken answer by @DouweM in #8766output_type by @DouweM in #8812max_tokens by @DouweM in #8986response.create by @DouweM in #8763UserError instead of ModelRetry for Macroscope setup failures by @DouweM in #8999RequestUsage.details and price them in cost by @dltsum in #8310clai2 menus by @mpfaffenberger in #9101!command shell descendants on cancellation in clai2 by @dafyy321-pixel in #9092UserWarnings in clai2, and group CodeMode missing-return-schema warnings by @mpfaffenberger in #9099clai2 shell process startup by @DouweM in #9104compact_messages() by @yang0228 in #8241clai2 recalls a slash command by @mpfaffenberger in #9297azure_voice_live=True for gpt-realtime-2 models on AzureRealtimeModel by @DouweM in #9050handshake_timeout by @DouweM in #9042gemini-live-2.5-flash and remove a stale Gemini Live docs claim by @DouweM in #9069DeferredToolRequestsEvent in realtime sessions before the HandleDeferredToolCalls handler runs by @DouweM in #9057ModelAPIError by @pydanty in #8846ModelAPIError in OpenAIChatModel, GroqModel and HuggingFaceModel by @DouweM in #9313ModelAPIError instead of ValidationError when an OpenRouterModel stream drops mid-response by @DouweM in #9312capabilities docs topic from capabilities/overview.md in PydanticAIDocs by @DouweM in #9011FileSystem default read_only_patterns to nested .env and .git/ paths by @DouweM in #9021CodeMode discovery announcements after compaction or history loss by @DouweM in #9045TrajectoryJudge window when the transcript is clamped by @DouweM in #9012ContentFilterError for a thinking-only response refused by the content filter, instead of retrying by @DouweM in #9355BubblewrapSandbox by @mpfaffenberger in #9349LogfireMCP instructions so they stop busting the prompt cache by @mpfaffenberger in #9319ModelAPIError when the OpenAI Responses API reports a failed response or an error stream event by @DouweM in #9321MistralError from the Mistral SDK to ModelHTTPError or ModelAPIError by @DouweM in #9307GoogleModel.count_tokens and XaiModel file uploads by @DouweM in #9308ClampOversizedMessages, SubAgents, and StepPersistence by @DouweM in #9026data validation errors under result.data so retry feedback keeps the failing input by @pydanty in #8669shell job log deleted mid-read as empty instead of failing the call by @dsfaccini in #9322turn_complete_reason as the realtime response's finish_reason by @DouweM in #9390request_limit by @DouweM in #9380SubAgent usage toward parent budgets by @DouweM in #9374Full Changelog: v2.51.0...v2.52.0
Match dated gemini-3.8-live ids, reject google_affective_dialog on Gemini 3.1 Flash Live and 3.8 Live at connect, and raise RealtimeError for Gemini L
gemini-3.8-live ids, reject google_affective_dialog on Gemini 3.1 Flash Live and 3.8 Live at connect, and raise RealtimeError for Gemini Live close codes by @DouweM in #8761UserError for a realtime tool_choice that forces a tool call on OpenAI, Azure OpenAI, and xAI by @DouweM in #8755OpenAILiveModel by @DouweM in #8390context_window_used on realtime sessions, from GPT-Live's reported ratio or response usage by @DouweM in #8803RunContext copying overhead in capability hooks by @Kludex in #8775provider_details on OpenAI Realtime tool-call responses and the response id on replies cut off by a drop or close() by @DouweM in #8762CompletedStreamedResponse replay by @Kludex in #8799Agent.run() by @Kludex in #8658Full Changelog: v2.50.0...v2.51.0
Ask a DecisionModel which route to take by name, with one label per route by @DouweM in #8733
DecisionModel which route to take by name, with one label per route by @DouweM in #8733ModelSelectionContext.messages end with the request being routed, and add ModelSelectionContext.prompt by @DouweM in #8737decision_route_threshold by @DouweM in #8739service_tier in provider details by @pydanty in #7945DecisionModel, a base for Decisions-protocol models, and make TypeSafeModel one by @DouweM in #8696RunContext.in_durable_context so hooks can tell they run in durable workflow code by @mpfaffenberger in #8723gemini-3.8-live and gemini-3.8-live-extended-thinking realtime support by @DouweM in #8393DecisionModel's route fields with the route question under a route premise, with nested-field context and a done state after tool calls by @DouweM in #8749decide span for every request a DecisionModel sends by @DouweM in #8698OutputSpec[T] passed to Agent.run under mypy by @DouweM in #8730ThinkingParts in the history decision models judge by @DouweM in #8738RequestUsage.audio_seconds so duration-billed voice models are priced by @DouweM in #8427output_type as a route beside other routes, and rename ToolCallProposed to UnfillableRoute under a DecisionHandOff base by @DouweM in #8744wait_for_reply() no longer hangs on it by @DouweM in #8747thinking=False on OpenAI Realtime by sending reasoning.effort: 'none' by @DouweM in #8753context_window from genai-prices and document compacting a Jev conversation by @DouweM in #8740stream_audio() view so speaker-paced playback gets whole replies by @DouweM in #8750RealtimeSessionErrorEvent by @DouweM in #8752Full Changelog: v2.49.0...v2.50.0
Add GitHubCopilotOAuthFlow for device authorization by @Kludex in #8618
GitHubCopilotOAuthFlow for device authorization by @Kludex in #8618BoolCriteria to say what a bool field's yes and no mean, and let a True/False Enum do the same by @DouweM in #8586None as the "none of these" option in TypeSafeModel by @DouweM in #8684Choice in TypeSafeModel by @DouweM in #8686RealtimeSession.wait_for_reply() by @DouweM in #8514OpenAIChatModel logprobs in provider_details['logprobs'] by @adtyavrdhn in #8653gpt-6-sol, gpt-6-luna, and gpt-6-astra on Bedrock Converse by @sevakva in #8656@GraphBuilder.stream node errors in-context during graph.iter() by @pydanty in #8304gs:// references as fileData in GoogleImageGenerationModel on Vertex AI by @dorukgezici in #8225Annotated model types by @ikriv in #8608None in a list of output types as | None so output_type=[Foo, Bar, None] passes pyright by @DouweM in #8641google_proactive_audio, which no Gemini Live session could ever connect with by @DouweM in #8394temperature and top_p for OpenAI GPT-5.6 and GPT-6 on Bedrock Converse instead of failing with a 400 by @kimnamu in #8668TypeSafeModel answers "None of these" for an optional field by @DouweM in #8685send_audio(iterable) cleanly on close by @DouweM in #8138Annotated metadata on the members of an X | Y output_type by @DouweM in #8687TypeSafeModel answers "None of these" for every field under it by @DouweM in #8697Annotated, Literal and union output_types as PEP 747 TypeForms, and bump pyright to 1.1.414 by @DouweM in #8690RunContext.tracer, trace_include_content and instrumentation_version follow an explicit Instrumentation capability by @DouweM in #8706OpenAICodexModel instead of failing with a 400 by @aweis89 in #8693Full Changelog: v2.48.0...v2.49.0
Support genai-prices 0.1.7 and new OpenAI audio models by @adtyavrdhn in #8617
genai-prices 0.1.7 and new OpenAI audio models by @adtyavrdhn in #8617gpt-6-sol and gpt-6-luna model support by @DouweM in #8635claude-opus-5-5) support by @DouweM in #8637UIMessage.id across Vercel AI load_messages and dump_messages by @adtyavrdhn in #8623Message.id across AGUIAdapter.load_messages and dump_messages by @adtyavrdhn in #8632Full Changelog: v2.47.0...v2.48.0
Name a None output route None rather than NoneType by @DouweM in #8590
None output route None rather than NoneType by @DouweM in #8590UserPromptPart.content is not a str or a sequence, instead of silently sending a dict's keys by @DouweM in #8595tuple output field and a self-contained model instead of crashing by @DouweM in #8537None be a route TypeSafeModel can pick by @DouweM in #8540Choices set describe itself as a TypeSafeModel route by @DouweM in #8541None route and a None option that carry a description by @DouweM in #8598TypeSafeModel request that fills it by @DouweM in #8589ag-ui-protocol to <1 by @adtyavrdhn in #8579Full Changelog: v2.46.0...v2.47.0
Let TypeSafeModel fill a tool's arguments when Jev can express them by @DouweM in #8501
TypeSafeModel fill a tool's arguments when Jev can express them by @DouweM in #8501RealtimeSession.wait_for_playback() and let the docs examples finish the reply before closing by @DouweM in #8141supports_text_output to ModelProfile, and run LLMJudge and GEval on a model without it by @DouweM in #8480typesafe_boolean_threshold for what a yes/no has to be before it is True by @DouweM in #8505TypeSafeModel fill a union of output types by choosing the type first by @DouweM in #8481event_stream_topic to TemporalDurability to stream agent events via Workflow Streams by @brianstrauch in #6639Enum's options by its member docstrings when it mixes in UseEnumMemberDocstrings by @DouweM in #8479Choices helper for a set of described options built at run time by @DouweM in #8530TypeSafeModel by @DouweM in #8484ToolReturnPart when a realtime tool raises, and keep a tool call and its speech in one ModelResponse by @DouweM in #8135ToolDefinition in CombinedToolset and FunctionToolset by @adtyavrdhn in #8082ModelRetry when web_fetch_tool gets a URL httpx2 rejects as invalid by @DouweM in #8521usage.cost and UsageLimits.cost_limit work in a session by @DouweM in #8136Full Changelog: v2.45.0...v2.46.0
Add TypeSafeModel for TypeSafe's Jev by @adtyavrdhn in #8450
TypeSafeModel for TypeSafe's Jev by @adtyavrdhn in #8450xhigh effort through on Bedrock when the model profile supports it by @willfrey in #8392gpt-5.6-sol, gpt-5.6-luna, and gpt-5.6-terra on Bedrock Converse by @pydanty in #7825DynamicToolset once per durable run instead of inside every durable unit by @DouweM in #8455MCPSamplingModel by @DouweM in #8466httpx in pydantic_ai.mcp, which a FastMCP 4 install does not ship by @DouweM in #8461Full Changelog: v2.44.0...v2.45.0
This release fixes four security issues, all of them reached through web_fetch_tool or OpenTelemetry instrumentation. See each advisory for full detai
This release fixes four security issues, all of them reached through web_fetch_tool or OpenTelemetry instrumentation. See each advisory for full details and affected versions.
FileUrl(force_download='allow-local') or web_fetch_tool(allow_local_urls=True). Both are off by default. Reported by @euriconicacio. (#8401)web_fetch processed responses in superlinear time on the event loop, in both the HTML conversion and the charset decode, so a single attacker-chosen page could stall every agent in the process. Reported by @BrianWillows. (#8397, #8418, #8433)web_fetch_tool's domain lists were compared as written rather than in the form the resolver uses, so a blocked domain could be reached under another spelling. (#8407, #8421)InstrumentationSettings(include_content=False), spans still carried exceptions, error statuses, instructions and the output template. Reported by @BrianWillows. (#8403, #8408, #8419, #8428)Patched in 2.44.0 (v2) and 1.107.6 (v1).
RunContext.enqueue() safe from worker threads by @adtyavrdhn in #7758Content-Type on UI adapter requests by @DouweM in #8396@durable_operation called from a per-request hook, instead of silently running it inline by @DouweM in #8395AgentRunResult a stable serialized shape, and settle a finished stream into one by @DouweM in #8269Storage page so persistence is findable by @DouweM in #8336EnqueuedMessagesEvent when a realtime session delivers enqueued content by @DouweM in #8134blocked_domains to OpenAI web search by @adtyavrdhn in #8323tool_search pairing in AG-UI by @adtyavrdhn in #8313Agent.from_spec() construct without a model, deferring the requirement to run time by @DouweM in #8339RealtimeSession.close() finish its teardown when the closing task is cancelled by @DouweM in #8142prepare_tools over every tool the availability gate admits by @DouweM in #8071Full Changelog: v2.43.0...v2.44.0
Add a first-run banner describing the run, and open clai sessions with it by @DouweM in #7447
OpenAIChatModel by @KaranJayakumar in #8235Full Changelog: v2.42.0...v2.43.0
Reject invalid DeferredToolResults.approvals values by @adtyavrdhn in #8081
DeferredToolResults.approvals values by @adtyavrdhn in #8081GitHubCopilotProvider for GitHub Copilot's OpenAI-compatible API by @dsfaccini in #8059anthropic_disallows_sampling_settings in BedrockConverseModel by @rscholz98 in #7961$ref definitions inline in code-mode function signatures by @pydanty in #8056ToolReturnContent without a Python call per JSON node by @dsfaccini in #7823Full Changelog: v2.41.0...v2.42.0
Deprecate fallback_model in favor of fallback_subagent_model on ImageGeneration and XSearch by @dsfaccini in #8077
fallback_model in favor of fallback_subagent_model on ImageGeneration and XSearch by @dsfaccini in #8077openai-codex provider for ChatGPT/Codex subscription authentication by @mpfaffenberger in #7769ImageGenerator by @EgonFerri in #5357RequestUsage.details and price them in cost by @adtyavrdhn in #8169ModelAPIError in BedrockConverseModel by @kimnamu in #8131Full Changelog: v2.40.0...v2.41.0
Add pydantic_ai.prices.update_in_background() by @adtyavrdhn in #4841
pydantic_ai.prices.update_in_background() by @adtyavrdhn in #4841handle_barge_in=True, interrupt(played_bytes=...), and played_audio_bytes by @DouweM in #7870provider_factory to infer_realtime_model by @DouweM in #8106@agent.on_event for registering event listeners on an Agent by @DouweM in #8101respond= to RealtimeSession.send() and document that a text turn solicits a reply by @DouweM in #8110RealtimeSession.enqueue() for out-of-band prompts from code driving the session by @DouweM in #8109finish_reason on OpenAI Responses stream terminal events by @pydanty in #7916defer_loading reveal synthesis splitting a parallel batch's tool_result from its tool_use by @pydanty in #7879reasoning to the dated gpt-realtime-2025-08-28 snapshot by @DouweM in #8103stream_audio() and stream_transcripts() views when they are called, not on first iteration by @DouweM in #8107ctx.realtime_session.close() instead of wedging itself by @DouweM in #8105interrupt(played_ms=) cancel race, and two provider tables by @DouweM in #8132Full Changelog: v2.39.0...v2.40.0
Add OpenAI gpt-6-astra model support by @dsfaccini in #8055
gpt-6-astra model support by @dsfaccini in #8055context_subtree() exporter cache and its span-processor leaks by @dsfaccini in #7667Instrumentation spec option include_model_request_parameters and sharpen the undeclared-attribute merge error by @DouweM in #8046AzureProvider and for AsyncAzureOpenAI clients on OpenAIProvider by @quinnarnold in #7922stream_transcripts() by @DouweM in #8062Full Changelog: v2.38.0...v2.39.0
Give one-off capabilities a default id and a combine rule for repeats by @dsfaccini in #7248
id and a combine rule for repeats by @dsfaccini in #7248context_window to ModelProfile and context_window_used to RunContext by @adtyavrdhn in #4611finish_reason by @jonashaag in #7096gemini-3.8-flash model by @dsfaccini in #8021CustomEvents and CapabilityEvents into the run event stream and subscribe with @on_event by @DouweM in #6258claude-fable-5-1) and Claude Mythos 5.1 (claude-mythos-5-1) support by @dsfaccini in #7989VLLMProvider for vLLM servers by @adtyavrdhn in #6153CancellationToken in UI adapter run methods by @dsfaccini in #7743pytest tests/durable_exec/temporal from crashing when the suite's requirements are missing by @dsfaccini in #7898tool_choice handling and support NativeOutput on DeepSeek's Responses API by @dsfaccini in #7450CodeExecutionTool uploads never reaching a fresh Anthropic container on a multi-turn history by @dsfaccini in #7864REASONING_* events from ag-ui-protocol 0.1.11 instead of 0.1.13 by @dsfaccini in #7226GoogleProvider's overload by @dsfaccini in #8030XaiModel streamed text after a native tool call being merged into the ended pre-call part by @pydanty[bot] in #7925native factory config in XSearch and ImageGeneration fallback subagents by @CoralGarden52 in #7541genai-prices to 0.1.6 by @adtyavrdhn in #8019Full Changelog: v2.37.0...v2.38.0
Add glm-5.3-flash and rework the Z.AI test suite onto cassettes by @dsfaccini in #7887
glm-5.3-flash and rework the Z.AI test suite onto cassettes by @dsfaccini in #7887finish_reason values by @zhj12395 in #7685TEXT_MESSAGE_START for the assistant message that owns a response's tool calls by @dsfaccini in #7699GoogleModel by client transport instead of provider name by @thejamesgore in #7280capabilities= on DBOS, matching Temporal by @DouweM in #6955Full Changelog: v2.36.0...v2.37.0
Add --mcp-config support and tool-call streaming to clai by @Kludex in #1374
@durable_operation for capabilities and a public backend API for third-party durable execution engines by @DouweM in #6696InstructionPart.id by @DouweM in #6887RealtimeSession.send_audio() and move the voice example to listentome by @DouweM in #7860@durable_operation by @DouweM in #7868TestModel generation for narrow exclusive numeric bounds by @Terminator666666 in #7800ToolDefinition into Prefect cache keys by @DouweM in #7872Full Changelog: v2.35.3...v2.36.0
Route Heroku GLM models through zai_model_profile by @LHMQ878 in #6837
zai_model_profile by @LHMQ878 in #6837safe_download cookies to original hostnames by @Diwak4r in #7077DeferredToolRequests.remaining resolving cross-category result IDs by @pydanty in #7626dbos extra; add opentelemetry-instrumentation-logging as a test dependency instead by @dsfaccini in #7820Full Changelog: v2.35.1...v2.35.3
Carry Bedrock guardrail trace in ModelResponse.provider_details by @pydanty in #7562
trace in ModelResponse.provider_details by @pydanty in #7562provider_factory when cancelling Temporal responses by @DouweM in #7000dbos below 2.31.0 to avoid a missing opentelemetry-instrumentation-logging import by @dsfaccini in #7804Full Changelog: v2.35.0...v2.35.1
Deprecate RunContext.capability_loaded and available_capability_ids in favor of capability_active and active_capability_ids by @DouweM in #7454
RunContext.capability_loaded and available_capability_ids in favor of capability_active and active_capability_ids by @DouweM in #7454maximum reachable in TestModel by @pydanty in #7697Tool description instead of falling back to the function docstring by @mpfaffenberger in #7759Full Changelog: v2.34.0...v2.35.0
Add a LangChain migration skill by @adtyavrdhn in #7679
ZaiModel by @aisk in #7600TestModel generation for equal inclusive bounds by @pydanty in #7642Literal in FunctionSignature by @pydanty in #7579TestModel generation of falsy JSON Schema const values by @pydanty in #7630UIEventStream part state on cancellation by @adtyavrdhn in #7675logit_bias from Cerebras model settings by @ryanl-cerebras in #7653VercelAIAdapter rejecting reasoning part id in run input by @pydanty in #7706CohereModel by @pydanty in #7720VercelProvider dropping the Groq profile for groq/-prefixed models by @pydanty in #7551SpanQuery maximums by @lntutor in #6934Retry-After dates in wait_retry_after() by @parveshsaini in #7711load_capability by @lntutor in #6937r1 alias in deepseek_model_profile() by @adtyavrdhn in #7723Full Changelog: v2.33.0...v2.34.0
⚠️ If Anthropic stopped working for you in the last day
anthropic 1.0.0 — rebuilt on httpx2, with legacy httpx support removed — reached PyPI on August 20. Every earlier pydantic-ai release, including v2.32.2 cut a few hours before this one, allowed that version without supporting it: a fresh or unpinned install of pydantic-ai[anthropic] could resolve anthropic 1.0.0 and then fail at runtime when using an Anthropic model. Apologies for the breakage window.
pydantic-ai v2.33.0, which requires and supports anthropic>=1.0.0.anthropic<1.If you pass your own http_client to AnthropicProvider, it must now be an httpx2.AsyncClient — the 1.x SDK rejects legacy httpx clients at construction.
httpx2 for Anthropic clients by @dsfaccini in #7657Full Changelog: v2.32.2...v2.33.0
Fail the workflow on UnexpectedModelBehavior and FallbackExceptionGroup under the deprecated TemporalAgent by @aviseth in #7465
pydantic_evals tasks and the evaluate decorator by @pydanty[bot] in #7535RunContext.cancel() in realtime sessions by @adtyavrdhn in #7528m.youtube.com URLs in VideoUrl by @uczltw6 in #7592UnexpectedModelBehavior and FallbackExceptionGroup under the deprecated TemporalAgent by @aviseth in #7465Full Changelog: v2.32.1...v2.32.2
Reject Agent.run_sync() from synchronous callbacks inside agent runs by @dsfaccini in #7277
Agent.run_sync() from synchronous callbacks inside agent runs by @dsfaccini in #7277thinking blocks with an empty signature by @mpfaffenberger in #7601FunctionModel function or stream_function by @dsfaccini in #7589Full Changelog: v2.32.0...v2.32.1
Suggest known model names for invalid identifiers by @dsfaccini in #7325
provider_details["annotations"] by @dsfaccini in #7458role: 'tool' by @dsfaccini in #7582timeout= for blocking sync tools and hooks by @adtyavrdhn in #7557RunContext.cancel() from setup-phase for_run hooks instead of raising UserError by @adtyavrdhn in #7567httpx2 for compatible HTTP clients by @dsfaccini in #7351Full Changelog: v2.31.1...v2.32.0
Deny native structured output for Claude Sonnet 5 and Fable 5 on Bedrock by @pydanty[bot] in #7374
thinking_level='LOW' for Gemini models that reject MINIMAL by @pydanty[bot] in #7469Full Changelog: v2.31.0...v2.31.1
Allow a UIEventStream to be built without a run_input , and give AGUIEventStream its own thread_id / run_id by @dsfaccini in #7292
UIEventStream to be built without a run_input, and give AGUIEventStream its own thread_id/run_id by @dsfaccini in #7292FallbackModel spans to the failing model, not the fallback: wrapper by @strawgate in #7018openai through Temporal workflow sandboxes by @adtyavrdhn in #7464Full Changelog: v2.30.0...v2.31.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
UIEventStream to be built without a run_input, and give AGUIEventStream its own thread_id/run_id by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7292FallbackModel spans to the failing model, not the fallback: wrapper by @strawgate in https://github.com/pydantic/pydantic-ai/pull/7018openai through Temporal workflow sandboxes by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/7464Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.30.0...v2.31.0
GHSA-q2xc-rrxj-58x9 : the local dev web chat UI ( Agent.to_web() , clai web ) didn't validate the Host header, so DNS rebinding from a website you vis
Agent.to_web(), clai web) didn't validate the Host header, so DNS rebinding from a website you visit could reach it and run the served agent with your local process's tools and credentials. Fixed in pydantic-ai/pydantic-ai-slim 2.30.0 by validating Host against localhost/loopback/LAN addresses by default; deployments reached under a real hostname must opt in with the new allowed_hosts setting.openrouter:web_search for web search by @dsfaccini in #7378gemini-3.7-flash model by @dsfaccini in #7445metadata on XaiProvider by @pydanty[bot] in #7423allowed_hosts to Agent.to_web() and clai web by @DouweM in #7437openai resource imports and genai-prices data loading at Model construction time by @adtyavrdhn in #7408EvaluationReport.print() on non-UTF-8 consoles by @dsfaccini in #7290Full Changelog: v2.29.0...v2.30.0
Support FastMCP 4 and MCP SDK v2 in MCPToolset alongside FastMCP 3 by @adtyavrdhn in #6738
MCPToolset alongside FastMCP 3 by @adtyavrdhn in #6738azure_voice_live setting by @DouweM in #6642for_realtime bugs from #6676 by @DouweM in #7412Full Changelog: v2.28.0...v2.29.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
MCPToolset alongside FastMCP 3 by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6738azure_voice_live setting by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6642for_realtime bugs from #6676 by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7412Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.28.0...v2.29.0
Fixes a high-severity vulnerability in the development web chat UI (Agent.to_web(), clai web): the chat endpoint didn't check the request's content ty…
Fixes a high-severity vulnerability in the development web chat UI (Agent.to_web(), clai web): the chat endpoint didn't check the request's content type, so a plain cross-origin request from a website open in the developer's browser could reach the endpoint without a CORS preflight and trigger the served agent to run and execute its tools with the local process's privileges and credentials. The endpoint now requires Content-Type: application/json and rejects other requests before the body is parsed and before the agent runs. See GHSA-h4xc-3qfq-jf93. Patched in 2.28.0 (v2) and 1.107.4 (v1).
Agent.realtime() by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6324CachePoint to the preceding user message instead of raising by @Diwak4r in https://github.com/pydantic/pydantic-ai/pull/7071PeekableAsyncStream pulls by @mikemikimike in https://github.com/pydantic/pydantic-ai/pull/7023state_restored honestly on realtime reconnect by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7379await_maybe helper by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7265safe_download Host header dropping non-default port by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/7348cerebras optional dependency group by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7387Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.27.1...v2.28.0
This release fixed an information-disclosure issue: retry-prompt content (validation feedback sent back to the model, which can quote invalid values f
This release fixed an information-disclosure issue: retry-prompt content (validation feedback sent back to the model, which can quote invalid values from its output) was not redacted by InstrumentationSettings(include_content=False) when the retry was not tied to a tool call. Now disclosed as GHSA-3gh4-cghq-f8v4 (low). Fixed here in 2.27.1 (#7357); v1 users should upgrade to 1.107.4 or later.
<!-- Release notes generated using configuration in .github/release.yml at main -->
XaiStreamedResponse finish_reason mapping for streaming responses by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6814RetryPromptPart OpenTelemetry content on include_content by @sean-kim05 in https://github.com/pydantic/pydantic-ai/pull/7357Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.27.0...v2.27.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
xai_agent_count to XaiModelSettings by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/7155CompactionPart through the Vercel AI and AG-UI adapters by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7287SnowflakeModel and SnowflakeProvider for Snowflake Cortex by @ayirpown in https://github.com/pydantic/pydantic-ai/pull/6150include_binary_content=False in every OTel serialization sink by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7131ToolReturn.tools in the redacted OTel shape by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7273SpanQuery has_attributes matching for JSON-serialized dict and list values by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/5905encrypted_content verbatim by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7286sanitize_messages by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7285Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.26.0...v2.27.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
load_capability, or ToolReturn.tools — using each provider's native deferral/addition channel by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7104AgentRun.cancel(), RunContext.cancel(), RunCancelled by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6497Model.resolve_prompt_cache_retention() to resolve effective prompt-cache retention from model settings by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7254run_stream_events() iterator to public AgentRunEvents handle with cancel() and run-state access by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6498OpenAIResponsesModel + DeepSeekProvider by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7202model_id through WrapperModel and resolve it against the active model in TemporalModel by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7181supports_inline_system_prompts=False by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7253is_tool_available, TestModel native additions) by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7260CompactionPart boundaries by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7225UIEventStream callbacks that return an async iterator without being an async generator function by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7256CompactionPart by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7228Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.25.0...v2.26.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
FileSearchTool collections search options by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/7154max_tokens for Mistral models, not max_completion_tokens by @feiiiiii5 in https://github.com/pydantic/pydantic-ai/pull/6929base_url port and forward base_url through WrapperModel by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7136thinking="minimal" for GPT-5.6 models by @daikeren in https://github.com/pydantic/pydantic-ai/pull/7082ToolCallPart.args_as_json_str() by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7092Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.24.0...v2.25.0
This release included a fix for an availability vulnerability — unbounded memory use when downloading remote content via the local web_fetch tool or F…
This release included a fix for an availability vulnerability — unbounded memory use when downloading remote content via the local web_fetch tool or FileUrl media downloads — now disclosed as GHSA-v2xh-2vp8-57h8. Fixed in 2.24.0 (#7141); v1 users should upgrade to 1.107.2 or later.
<!-- Release notes generated using configuration in .github/release.yml at main -->
timeout=0 by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/7114allowed_function_names by @LHMQ878 in https://github.com/pydantic/pydantic-ai/pull/6875top_p=0.0 to Bedrock by @LHMQ878 in https://github.com/pydantic/pydantic-ai/pull/6864ignore_streamed_leading_whitespace in Bedrock streams by @LHMQ878 in https://github.com/pydantic/pydantic-ai/pull/6828kimi-k2-thinking and Heroku's kimi-k2-5 as Kimi reasoning models by @LHMQ878 in https://github.com/pydantic/pydantic-ai/pull/6823UserError when an OpenRouter model omits its provider prefix by @LHMQ878 in https://github.com/pydantic/pydantic-ai/pull/6860groq/compound model names by @LHMQ878 in https://github.com/pydantic/pydantic-ai/pull/6825ToolApprovalResponded.approved a StrictBool by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6995Retry-After integer values in wait_retry_after by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/7066ag-ui-protocol instead of returning 422 by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7119apply_event replay by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/7138Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.23.0...v2.24.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
ModelSettings.extra_headers by @kkauy in https://github.com/pydantic/pydantic-ai/pull/4825gemini-3-pro-image and gemini-3.1-flash-image Gateway aliases by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/7069cost to RunUsage and cost_limit to UsageLimits by @Kludex in https://github.com/pydantic/pydantic-ai/pull/2684ToolAvailabilityDeltaPart with native tool_addition and additional_tools rendering by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6793bedrock_max_concurrency instead of deadlocking on 0 by @LHMQ878 in https://github.com/pydantic/pydantic-ai/pull/6878GoogleCloudProvider credential scoping and ADC auth env-var leak by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6500created timestamp from any chunk in OpenAI streaming responses by @LKRCharon in https://github.com/pydantic/pydantic-ai/pull/5496TypeAdapter cache by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7085LogfirePlugin by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7086agent.iter() by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6871Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.22.0...v2.23.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
MCPToolset clients to skip optional MCP tasks via prefer_tasks by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6851VALIDATED tool mode on supported models by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6353system messages on Anthropic by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6765RunContext.is_tool_available by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7011safe_download redirects by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6811extra_headers before setdefault in OpenAI chat and Groq models by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6868args_validator by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6897tool_def in Temporal function-tool activities instead of re-running prepare by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6890UserError instead of hanging when run_sync() is called on an event loop it cannot drive by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6905RunContext fields a tool can read by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6944after_tool_validate when an args_validator defers the call by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6961LogfirePlugin by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6962EnqueueGuard on the DBOS/Prefect model-request and cancel_suspended_response units by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6943ActivityConfig after the activity round trip by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6947Model instances in durable runs instead of re-inferring them from model_id by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6898sets, carry conversation_id, and hard-error on omitted fields in TemporalRunContext by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6891ApprovalRequired/CallDeferred from post-validation tool hooks, UserError from pre-validation ones by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6951UserError when a history processor or fallback_on handler has unresolvable type annotations by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6958ModelAPIError for OpenRouter responses with null choices and no error envelope by @ZacharyHampton in https://github.com/pydantic/pydantic-ai/pull/6901$ref to a union $def, not just the first one by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6960ActivityConfig keys in TemporalDurability by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6964TaskConfig on Prefect MCP tools and add PydanticUserError to its non-retryable set by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6952InstrumentedModel by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6982MCPToolset.tool_for_tool_def by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6449HookTimeoutError and FallbackExceptionGroup instead of retrying forever by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6978tool_choice on OpenRouter anthropic/ models by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6957max_retries to ToolSearchToolset by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6740ActivityConfig validation on Python 3.10 and 3.11 by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6989pydantic_graph through Temporal workflow sandboxes by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6990TypeAdapters by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7001SystemPromptPart semantics across caching and Temporal by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6984genai-prices>=0.1.0 for detailed usage by @alexmojaki in https://github.com/pydantic/pydantic-ai/pull/6933anyio as a direct dependency of pydantic-ai-slim and pydantic-graph by @DouweM in https://github.com/pydantic/pydantic-ai/pull/7008Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.21.0...v2.22.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
per_request_input_tokens_limit to UsageLimits by @Oxygen56 in https://github.com/pydantic/pydantic-ai/pull/5907KnownModelName from Gateway probes and stable Google image IDs by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6806Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.20.0...v2.21.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
claude-opus-5) support by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6723reasoning.context support (default all_turns) for the gpt-5.4/gpt-5.5/gpt-5.6 families by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6673RequestUsage fields across serialization by @alexmojaki in https://github.com/pydantic/pydantic-ai/pull/6685ALLOW_MODEL_REQUESTS guards for embeddings by @zcxGGmu in https://github.com/pydantic/pydantic-ai/pull/6774include_server_side_tool_invocations for Vertex on Gemini 3+ by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6773_openrouter_settings_to_openai_settings mutating caller's settings dict by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6743PartStartEvent by @Jonas1312 in https://github.com/pydantic/pydantic-ai/pull/6785McpError from an MCP server recoverable instead of fatal by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6787Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.19.0...v2.20.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
headers and retry_after to ModelHTTPError, populate from all provider SDKs by @dmontagu in https://github.com/pydantic/pydantic-ai/pull/6733<4 by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6737Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.18.0...v2.19.0
<!-- Release notes generated using configuration in .github/release.yml at v2.18.0 -->
<!-- Release notes generated using configuration in .github/release.yml at v2.18.0 -->
AdvisorTool support for Anthropic and OpenRouter by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6605external_web_access option to WebSearchTool for OpenAI Responses by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6710BedrockMantleProvider and normalize response-scoped tool-call IDs by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6538google-genai stream errors in GoogleModel by @dmontagu in https://github.com/pydantic/pydantic-ai/pull/6693Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.17.0...v2.18.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
RequestUsage and RunUsage support arbitrary fields for upcoming genai-prices by @alexmojaki in https://github.com/pydantic/pydantic-ai/pull/6683O(n²) instrumentation cost by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6635ContentFilterError for real Model Armor response blocks (finishReason: MODEL_ARMOR) and record moderation wire-truth cassettes by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6679Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.16.0...v2.17.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
mistral_prompt_cache_key setting and pass parallel_tool_calls to the Mistral SDK by @lionpeloux in https://github.com/pydantic/pydantic-ai/pull/6654ToolFailed for model-visible failures without retries by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/5585run_id= to agent runs, durable wrappers, and UI adapters by @grahamcracker1234 in https://github.com/pydantic/pydantic-ai/pull/6615openai_moderation to OpenAIChatModelSettings and expose Chat Completions moderation results in provider_details by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6658GoogleModelSettings by @Alex-Resch in https://github.com/pydantic/pydantic-ai/pull/5691gemini-3.6-flash and gemini-3.5-flash-lite models by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6668ctx.enqueue() error inside durable units across Temporal, DBOS, and Prefect by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6666$ref sibling keywords when inlining $defs by @lntutor in https://github.com/pydantic/pydantic-ai/pull/6592ctx.enqueue() from an event_stream_handler inside DBOS steps / Prefect tasks by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6671Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.15.0...v2.16.0
Deprecate the Exa search common tools in favor of the ExaSearch capability in Pydantic AI Harness by @dsfaccini in https://github.com/pydantic/pydanti…
<!-- Release notes generated using configuration in .github/release.yml at main -->
gpt-5.6 by @Wh1isper in https://github.com/pydantic/pydantic-ai/pull/6423MistralModel prompts by @pulphix in https://github.com/pydantic/pydantic-ai/pull/6556run/iter/override time by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6072DynamicCapability toolsets in durable execution and wrap DynamicToolset in DBOS steps and Prefect tasks by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6623openai_moderation setting and expose OpenAI Responses API moderation results in provider_details by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6628ExaSearch capability in Pydantic AI Harness by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6644tool_search replay with null call IDs by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6604reasoning.encrypted_content on persisted responses by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6614register_legacy_workflows to DBOSDurability for clean DBOSAgent migration by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6640Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.14.1...v2.15.0
Temporarily withdraw durable wrapper-agent deprecations by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6625
<!-- Release notes generated using configuration in .github/release.yml at main -->
DBOSDurability by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6624Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.14.0...v2.14.1
Add TemporalDurability, DBOSDurability and PrefectDurability capabilities to replace the deprecated wrapper agents by @DouweM in https://github.com/py…
<!-- Release notes generated using configuration in .github/release.yml at main -->
reasoning_effort support via thinking settings by @YHallouard in https://github.com/pydantic/pydantic-ai/pull/5294TemporalDurability, DBOSDurability and PrefectDurability capabilities to replace the deprecated wrapper agents by @DouweM in https://github.com/pydantic/pydantic-ai/pull/4977gemini-2.5-flash-lite-preview-09-2025 and gemini-3.1-flash-lite-preview by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6606Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.13.0...v2.14.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
include_model_request_parameters instrumentation setting to omit the model_request_parameters span attribute by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6488RaiseContentFilterError capability to raise content filter error for non-empty content filter responses by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6167cache_hit_ratio property to RequestUsage and RunUsage by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6529get_model, resolve_model_id, and for_agent capability hooks by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6333MistralModel streaming settings by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6563Failed to detach context error when a streamed run is interrupted mid-segment by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6572pydantic_monty in workflow sandbox by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6564mcp to 1.28.1 for Dependabot alerts by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6562Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.12.0...v2.13.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
kimi-k3 model by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6551EnqueuedMessagesEvent when enqueued messages are delivered into the run by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6256DeferredToolCallEvent and DeferredToolResultEvent to AgentStreamEvent by @YHallouard in https://github.com/pydantic/pydantic-ai/pull/5588ToolReturnPart serialization to use field aliases so wire output matches return_schema by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6543*args by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6541id from the capability for durable execution by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6408GoogleModel per-Part media_resolution forwarding in vendor_metadata by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6525Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.11.0...v2.12.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
HistoryProcessor and add actionable hints to usage-limit and tool-retry errors by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6346MistralStreamedResponse streamed number/integer validation to accept int-valued numbers and reject bools by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6479Agent('test') when provider credentials are missing by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6342profile={"default_structured_output_mode": "native"} by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6521profile={'default_structured_output_mode': 'native'} sending untransformed schema by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6539Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.10.0...v2.11.0
Bump transformers floor to >=5.5.0 for CVE-2026-5241 by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6482
<!-- Release notes generated using configuration in .github/release.yml at main -->
message_history provider-valid out of the box (repair tool-call/result pairing) by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6319stop_reason=pause_turn by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6303has_values() returning True for all-zero usage details by @sean-kim05 in https://github.com/pydantic/pydantic-ai/pull/6466RenamedToolset silently dropping a tool on a name collision by @sean-kim05 in https://github.com/pydantic/pydantic-ai/pull/6462bytes in instrumentation serialization by @alexmojaki in https://github.com/pydantic/pydantic-ai/pull/6483run_stream_sync by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6454ToolCallPart to the preceding reasoning message by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/5924DeferredToolResults resume when an output tool call was settled in the same batch as deferred calls by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6491transformers floor to >=5.5.0 for CVE-2026-5241 by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6482Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.9.1...v2.10.0
fix(deps): bump soupsieve to 2.8.4 to fix ReDoS (CVE-2026-49477) by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6442
<!-- Release notes generated using configuration in .github/release.yml at main -->
JsonSchemaTransformer by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6440MistralModel._get_timeout_ms by @Ricardo-M-L in https://github.com/pydantic/pydantic-ai/pull/5019KnownModelName and restore Gateway-supported models by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/5843Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.9.0...v2.9.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
A moderate advisory, GHSA-jpr8-2v3g-wgf9 (CWE-863), affecting the AG-UI UIAdapter.sanitize_messages dangling-tool-call strip, was fixed in 2.5.0 and backported to 1.107.1 on the v1 line. If you are on 2.5.0 or later you already have the fix; this note calls it out now that the advisory is public.
pydantic-ai / pydantic-ai-slim >= 2.0.0, < 2.5.0 (v2) and >= 1.88.0, < 1.107.1 (v1)2.5.0 (v2) and 1.107.1 (v1)requires_approval=True / ApprovalRequiredToolset, or if your tool handlers validate their arguments and enforce authorization themselves./usage slash command to clai CLI for cumulative token usage by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6245RunContext): expose the run's usage_limits to tools and capabilities by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6341UploadedFile by @gaurav0107 in https://github.com/pydantic/pydantic-ai/pull/5815repr() crash on message parts whose field != returns a non-bool (#6415) by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6421MCPToolset on the DBOSAgent wrapper path by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6406capture_run_messages capture correctly (#1568) by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6345end_strategy='early' for NativeOutput, PromptedOutput, and image output by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6427Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.8.0...v2.9.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
to_cli() to pass model for unset-model agents by @hramezani in https://github.com/pydantic/pydantic-ai/pull/63842.0.0 and target sdk_version=7 in Agent.to_web() by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6296JsonSchemaTransformer to recurse into allOf composition by @pydanty[bot] in https://github.com/pydantic/pydantic-ai/pull/6394Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.7.0...v2.8.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
grok-4.5 model by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6362override(model=...) on an agent with no model set by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6357AlibabaProvider (Chat Completions API) by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/5727Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.6.0...v2.7.0
deps: bump torch floor to 2.12.1 to close CVE-2025-3000 by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6309
<!-- Release notes generated using configuration in .github/release.yml at main -->
files support to CodeExecutionTool for Anthropic and OpenAI by @HenryYYang in https://github.com/pydantic/pydantic-ai/pull/4338LatestBedrockModelNames by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6318WebSearchTool domain filters to Groq search_settings by @Iam-Mil in https://github.com/pydantic/pydantic-ai/pull/6160max_running by @VectorPeak in https://github.com/pydantic/pydantic-ai/pull/6282PrefectAgent cache-key drift by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6313for_run once per run and preserve resolved native tools under override(native_tools=...) by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6332genai-prices to 0.0.70 by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6330Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.5.1...v2.6.0
Exclude deprecated Bedrock gateway model anthropic.claude-3-5-sonnet-20240620-v1:0 by @ddanielcruzz in https://github.com/pydantic/pydantic-ai/pull/62…
<!-- Release notes generated using configuration in .github/release.yml at main -->
toolResult attachment co-location per-model via bedrock_tool_result_colocatable_content by @Hasnaathussain in https://github.com/pydantic/pydantic-ai/pull/6098thinking setting to Groq reasoning_effort by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6231OnlineEvaluator.max_concurrency by @VectorPeak in https://github.com/pydantic/pydantic-ai/pull/6267FileUrl.force_download in UI round-trips by @HarperZ9 in https://github.com/pydantic/pydantic-ai/pull/6205anthropic.claude-3-5-sonnet-20240620-v1:0 by @ddanielcruzz in https://github.com/pydantic/pydantic-ai/pull/6297NativeOutput description instead of last member's docstring by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6265toolResult turns by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6259ModelResponse from Mistral and Cohere request payloads by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6302Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.5.0...v2.5.1
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
This release included the fix for GHSA-jpr8-2v3g-wgf9 (moderate, CWE-863), carried by the sanitize_messages change in #6169. On the AG-UI serving path (Agent.to_ag_ui() / AGUIAdapter), the dangling-tool-call strip anchored to a pre-sanitization index, so a dropped trailing client message could re-expose a preceding unresolved tool call for execution. The v1 line is patched in 1.107.1.
2.5.0 (v2) and 1.107.1 (v1)>= 2.0.0, < 2.5.0 (v2) and >= 1.88.0, < 1.107.1 (v1)sanitize_messages for inbound message-history hardening by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/6169_clean_message_history merges consecutive ModelRequests regardless of conversation_id/metadata by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6221_build_prompt section order with its few-shot examples by @immuhammadfurqan in https://github.com/pydantic/pydantic-ai/pull/6111thinking support and add models to KnownModelNames by @SuperMarioYL in https://github.com/pydantic/pydantic-ai/pull/6208toolsets in durable runs by @Trollgeir in https://github.com/pydantic/pydantic-ai/pull/6076gen_ai.usage.details.* OTel attributes to fix double-counting by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6244anyio portal thread; fix async stream_text early-break teardown by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6199bedrock_supported_media_kinds_in_tool_returns for Meta, Mistral, and Qwen by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6254numpy source builds in examples by @hramezani in https://github.com/pydantic/pydantic-ai/pull/6246Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.4.0...v2.5.0
<!-- Release notes generated using configuration in .github/release.yml at main -->
<!-- Release notes generated using configuration in .github/release.yml at main -->
preserve_file_data into allow_uploaded_files (inbound security) and an AG-UI representation opt-in by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6232GEval evaluator and standard quality metric rubrics for LLMJudge by @dmontagu in https://github.com/pydantic/pydantic-ai/pull/5129XSearchTool handle limit by @gyx09212214-prog in https://github.com/pydantic/pydantic-ai/pull/5979process_tool_calls by @kratos0718 in https://github.com/pydantic/pydantic-ai/pull/6189WebSearchTool.user_location to xAI web search by @manan-tech in https://github.com/pydantic/pydantic-ai/pull/6181KeyboardInterrupt in synchronous run_until_complete wrappers by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6198description from ToolSearchMatch by @serozhenka in https://github.com/pydantic/pydantic-ai/pull/5654max_concurrency by @VectorPeak in https://github.com/pydantic/pydantic-ai/pull/6228run_stream_events() background task on first event iteration by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6234genai-prices to >=0.0.69 by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6212Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.3.0...v2.4.0
Your coding agent can read these notes before it upgrades. Set up the MCP server →