chore(deps): update dependency pydantic-ai to v2.53.0 [security] #9
Loading…
Reference in a new issue
No description provided.
Delete branch "renovate/pypi-pydantic-ai-vulnerability"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR contains the following updates:
2.24.0→2.53.0Pydantic AI OpenTelemetry instrumentation: retry prompt content is not redacted when
include_content=FalseCVE-2026-107293 / GHSA-3gh4-cghq-f8v4
More information
Details
Summary
Pydantic AI's OpenTelemetry instrumentation supports
InstrumentationSettings(include_content=False)to exclude message content — user prompts, model completions, tool call arguments and responses — from exported telemetry, so that agents can be monitored without sending sensitive content to the observability backend.Retry prompts — the feedback messages Pydantic AI sends back to the model when its output fails validation or an output validator raises
ModelRetry— were not covered by this setting when they were not associated with a tool call, as with structured output modes that don't use tool calls (e.g.NativeOutputorPromptedOutput) and output validators applied to text output. Their full content was recorded on model request spans even withinclude_content=False. Since validation feedback can quote invalid values from the model's response, message content that the setting was configured to withhold could reach the telemetry backend.Details
Retry prompts without an associated tool call were serialized into span message attributes (such as
gen_ai.input.messagesandpydantic_ai.all_messages) as regular text parts, and this path did not apply theinclude_contentcheck that every other message part applies. Retry prompts tied to a tool call, and all other message content, were redacted correctly.Impact
This does not grant an attacker any new access to the agent or its data: the content is only visible to whoever can read the exported telemetry. The exposure matters when traces are exported to a destination whose audience is broader or less trusted than the agent's own data — a third-party observability vendor or a shared backend — which is the scenario
include_content=Falseexists for. The disclosed content is limited to retry feedback: validation error details, which can quote invalid values from the model's output, or output-validatorModelRetrymessages.Who Is Affected
You are affected if you enabled instrumentation with
include_content=Falseand your agent can produce retry prompts outside of tool calls: it uses a structured output mode that doesn't rely on tool calls (such asNativeOutputorPromptedOutput), or output validators on text output. You are not affected if you don't setinclude_content=False, or if all of your agent's retries come from tool calls (including the default tool-based structured output mode), which were redacted correctly.Remediation
Upgrade to a patched version; retry prompt content now honors
include_content=Falselike all other message content. If you rely on this setting, consider reviewing previously exported traces for retry prompt content that should not have been recorded.Workaround for Unpatched Versions
If you cannot upgrade, scrub or drop the message attributes (
gen_ai.input.messages,gen_ai.output.messages,pydantic_ai.all_messages) in your telemetry pipeline (for example with an OpenTelemetry Collector processor), or use tool-based structured output modes, whose retry feedback honorsinclude_content=False.Credits
Reported privately by the University of Sydney Security Research Team (Liyi Zhou, Ziyue Wang, Strick, Maurice, Chenchen Yu), and later independently discovered and reported publicly, with a fix, by @sean-kim05.
Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Pydantic AI Web chat UI (
Agent.to_web(),clai web): a website visited by the developer can trigger agent runs and server-side tool execution on the local chat endpointCVE-2026-107295 / GHSA-h4xc-3qfq-jf93
More information
Details
Summary
The Pydantic AI development web chat UI (
Agent.to_web(),clai web) did not check the content type of requests to its chat endpoint. This allowed a website visited by a developer to submit a request to a chat UI running on that developer's machine, causing the served agent to run and to execute its tools with the privileges and credentials of the local process.Binding the web UI to localhost — the default — does not prevent this, because a page open in the developer's browser can reach the loopback address.
Impact
Applications and developers serving an agent through
Agent.to_web()orclai web. The consequences depend on the tools the served agent exposes, and can include data disclosure as well as unwanted tool side effects. Tools markedrequires_approval=Truewere not protected either, because the endpoint trusts approval decisions relayed by the client.Mitigation
Upgrade to a patched version. The chat endpoint now requires
Content-Type: application/jsonand rejects other requests before the request body is parsed and before the agent runs. The bundled chat UI already sends this header; scripts and other non-browser clients that call the endpoint directly may need to be updated to send it.If you cannot upgrade, don't run the web UI while browsing untrusted sites, stop it when you aren't using it, and don't serve an agent with side-effecting tools through it.
Credits
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:H/A:LReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Pydantic AI Web chat UI (
Agent.to_web(),clai web): the local chat endpoint does not validate theHostheaderCVE-2026-107292 / GHSA-q2xc-rrxj-58x9
More information
Details
Summary
The Pydantic AI development web chat UI (
Agent.to_web(),clai web) does not validate theHostheader of incoming requests. A website a developer visits can use DNS rebinding to make requests to a chat UI running on that developer's machine appear same-origin to the browser, causing the served agent to run and to execute its tools with the privileges and credentials of the local process.Details
Once a name the attacker controls resolves to the loopback address, the browser treats the request as same-origin, so neither an
Origincheck nor a CSRF token constrains it — a same-origin page can read the served UI and any token in it.Binding the web UI to localhost — the default — does not prevent this.
Impact
Applications and developers serving an agent through
Agent.to_web()orclai web. The consequences depend on the tools the served agent exposes, and can include data disclosure as well as unwanted tool side effects.Current browser protections reduce but do not remove this exposure: Chromium's Local Network Access gates loopback subresource requests, but does not cover top-level navigations, and Safari does not implement it.
Mitigation
Upgrade to
pydantic-ai/pydantic-ai-slim>= 2.30.0, or >= 1.107.5 on the v1 maintenance line.The fix validates the
Hostheader and rejects anything other than localhost, a loopback/LAN IP address, or an explicitly allowed host, responding421 Misdirected Requestotherwise. If you serve the web chat UI under a real hostname — behind a reverse proxy, tunnel, or similar — name it explicitly:Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:H/A:LReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Pydantic AI OpenTelemetry instrumentation: exception events on tool and agent run spans include content when
include_content=FalseCVE-2026-107291 / GHSA-4x9p-g9wm-8q7f
More information
Details
Summary
Pydantic AI's OpenTelemetry instrumentation supports
InstrumentationSettings(include_content=False)to exclude message content — user prompts, model completions, tool call arguments and responses, and any other message content — from exported telemetry, so that agents can be monitored without sending sensitive content to the observability backend.The message attributes honoured the setting. Several other parts of the same spans did not, and exported content regardless of it:
ModelRetryorToolFailedfeedback is the text sent back to the model, which can quote tool arguments and results. When a tool ran out of retries, the error that ended the run was chained from the last retry, so its stack trace repeated that text on the run span. Exceptions raised by tool code were recorded with their full message, as were failures of a model request, embedding or image generation, whose messages carry the provider's error response body.model_request_parametersattribute serialized the request's instruction parts in full, exporting the agent's instructions — both static and those built from dependencies at request time — along with the template used to prompt for structured output.Details
Content reaches these places because of what they carry rather than through any single missing check, which is why the setting was applied correctly to the message attributes (
gen_ai.input.messages,gen_ai.tool.call.arguments,gen_ai.tool.call.result, and so on) while these paths were not: the exception recording and the status description came from the OpenTelemetry SDK's defaults, and the instructions and output template were serialized as part of the request's parameters rather than treated as content.Impact
This does not grant an attacker any new access to the agent or its data: the content is only visible to whoever can read the exported telemetry. The exposure matters when traces are exported to a destination whose audience is broader or less trusted than the agent's own data — a third-party observability vendor or a shared backend — which is the scenario
include_content=Falseexists for.Who Is Affected
You are affected if you enabled instrumentation with
include_content=False. Instructions are exported on every successful run, so no failure is needed to be affected; the exception paths additionally require a tool to raise, or a model, embedding or image generation request to fail. Realtime sessions are affected the same way, through the errors their provider connections report. GHSA-3gh4-cghq-f8v4 stated that retries coming from tool calls were redacted correctly; that was true of the retry prompt in the message attributes but not of the exception event on the tool span. You are not affected if you don't setinclude_content=False.Remediation
Upgrade to a patched version. With
include_content=False, exception events now record only the exception type, error statuses carry no description, andmodel_request_parametersis exported without its instruction content or output template. If you rely on this setting, consider reviewing previously exported traces for exception events, for error status descriptions, and formodel_request_parameters.Workaround for Unpatched Versions
If you cannot upgrade, scrub the
exception.messageandexception.stacktraceevent attributes, the error status description, and the instruction parts andprompted_output_templatewithinmodel_request_parameters, on spans emitted by Pydantic AI in your telemetry pipeline (for example with an OpenTelemetry Collector processor). Settinginclude_model_request_parameters=Falsealongsideinclude_content=Falseremoves both, at the cost of the rest of that attribute.Credits
Reported privately by @BrianWillows, whose report covered the exception events on tool and agent run spans. The remaining paths were found while fixing it, by a test that drives content through every channel at once and checks the whole exported trace.
Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Pydantic AI: Event loop blocked by quadratic title extraction in
web_fetchCVE-2026-107290 / GHSA-fpf4-vwcp-v4hp
More information
Details
Summary
The local web-fetch tool (
web_fetch_tool, also used as theWebFetchcapability's local fallback) processed responses with several steps whose running time grows quadratically with the size of certain server-controlled inputs, and ran them on the event loop: decoding the body with whichever charset the server declared, extracting the page title with a backtracking regular expression, and converting the HTML to markdown. An application that exposes this tool to untrusted prompts can be steered to fetch an attacker-controlled page of a megabyte or two that blocks the event loop for minutes, stalling every other coroutine in the process — other agent runs, other requests being served — for the duration.This is an availability issue only. SSRF protections and the download size limit introduced in GHSA-v2xh-2vp8-57h8 are unaffected; that limit bounds how much is downloaded, not how long the response takes to process.
Details
Title extraction used a backtracking pattern over the raw response body, so a body made of repeated unterminated tag openings cost time proportional to the square of its size. The HTML-to-markdown conversion had the same shape in three of its steps: normalizing whitespace, stripping preformatted blocks, and numbering ordered lists all took time proportional to the square of a run of spaces or a list's length. All of it ran on the event loop, and the regex steps hold the interpreter lock even when moved off it, so the whole process paid for the size of a server-controlled response.
The response body was also decoded on the event loop with the codec named by the
charsetparameter of the response'sContent-Type, looked up in Python's codec registry. That registry includespunycode, whose decoder takes time proportional to the square of its input: a response of about one megabyte labelledcharset=punycodeblocked the event loop for roughly half a minute, with no HTML required. The registry also includes codecs that aren't text encodings at all, such asrot_13andbase64_codec; a response labelled with one of those raised an unexpected exception out of the tool, aborting the agent run that fetched it.Separately, the HTML-to-markdown conversion recursed once per nested element, so a page nested a few hundred elements deep raised a
RecursionErrorout of the tool, aborting the agent run that fetched it. A JSON response nested deeper than the interpreter allows did the same. These only affect that one run.Who Is Affected
You are affected if your application registers the local web-fetch tool (or relies on the
WebFetchcapability's local fallback) and exposes the agent to untrusted prompts.allowed_domainsnarrows the exposure to pages on those domains but does not remove it. Applications that only fetch developer-controlled URLs are not exposed to the model-chosen attack path.Remediation
Upgrade to a patched version. The title is now found with a single linear scan, the conversion steps above run in linear time, and decoding, title extraction and conversion all run in a worker thread. A charset naming a codec that isn't a text encoding, and a page too deeply nested to convert, are reported back to the model as a failed fetch instead of aborting the run; a JSON body too deeply nested to parse is returned as plain text.
Credits
Reported privately by @BrianWillows, whose report covered the quadratic title extraction. The response decoding, the codecs that are not text encodings, and the quadratic steps in the HTML-to-markdown conversion were found while fixing it.
Severity
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Pydantic AI: SSRF cloud-metadata blocklist bypass via IPv6 zone identifiers
CVE-2026-107289 / GHSA-vmxc-h2x2-jmf3
More information
Details
Summary
When an application using Pydantic AI opts a URL into local network access — either a
FileUrlwithforce_download='allow-local', orweb_fetch_tool(allow_local_urls=True)— the cloud-metadata blocklist could be bypassed by appending an IPv6 zone identifier to a metadata address (for examplefd00:ec2::254%251). The host ignores the zone identifier on a destination that is not link-local and delivers the request to the metadata endpoint anyway, exposing cloud IAM short-term credentials.This is an incomplete fix of GHSA-cqp8-fcvh-x7r3 / CVE-2026-46678 and GHSA-cg7w-rg45-pc59 / CVE-2026-48782, themselves follow-ups to CVE-2026-25580. The parent advisory's remediation guaranteed that cloud metadata endpoints are always blocked, even with local access allowed. That guarantee did not hold for zone-scoped spellings of the IPv6 metadata endpoints.
Details
The cloud-metadata guard compared IPv6 addresses against its blocklist by set membership. Python includes the zone identifier in
IPv6Addressequality and hashing, so a zone-scoped spelling of a blocked address did not match, while the network stack ignores the zone identifier for a destination that is not link-local. The private-range checks, and the IPv4 and transition-form metadata checks, were already unaffected, because they compare by network containment and by packed bytes respectively.Only the IPv6 cloud metadata endpoints were reachable this way, so the issue requires an IPv6-enabled environment — for example AWS EC2 or EKS with IPv6, GCP IPv6-only instances, or Scaleway.
Who Is Affected
You are affected only if your application opts a URL that is, or could be, influenced by untrusted input into local network access, through either:
FileUrl(ImageUrl,AudioUrl,VideoUrl,DocumentUrl) withforce_download='allow-local'; orweb_fetch_tool(allow_local_urls=True), where the model chooses the URL.Both are off by default.
You are not affected through the
FileUrlpath if you use any of the bundled integrations to ingest user input, because they do not propagateforce_downloadfrom external data:Agent.to_web/clai webVercelAIAdapterAGUIAdapter/Agent.to_ag_uiweb_fetch_toolis configured by your own application, so a client cannot turn onallow_local_urls.Applications that only download from developer-controlled URLs are not affected.
Remediation
Upgrade to a patched version. The cloud-metadata and private-IP checks now drop an IPv6 zone identifier before evaluating the address, so every blocklist comparison is made on the address itself. A zone identifier is still carried on the connection, so legitimate link-local fetches under local network access continue to work.
Workaround for Unpatched Versions
Avoid opting into local network access —
force_download='allow-local'orweb_fetch_tool(allow_local_urls=True)— on any URL that could be influenced by untrusted input. If you must, reject URL hosts containing%before constructing theFileUrlor configuring the tool.Credits
Reported by @euriconicacio.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:NReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Pydantic AI: Excessive resource use when local web fetching converts nested HTML
CVE-2026-107287 / GHSA-v36g-jcw9-x7cw
More information
Details
Summary
Applications using Pydantic AI's local web-fetch tool can experience excessive CPU and memory use when it converts attacker-controlled HTML. An agent must fetch the affected page; provider-native web fetching is not affected.
Details
Nested block elements cause HTML-to-Markdown conversion to reprocess accumulated text at each level and can greatly expand the intermediate output. The response-body limit bounds downloaded bytes, while the returned-content limit is applied only after conversion. On current releases, conversion runs in a worker thread but can still consume substantial resources and delay other work in the process. Older releases performed conversion on the event loop.
Mitigation
Upgrade to a patched release of
pydantic-aiorpydantic-ai-slim. If you cannot upgrade yet, avoid using local web fetching for attacker-controlled HTML.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:HReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Pydantic AI: Concurrency-limited models can keep their slot when a streamed request ends early
CVE-2026-107286 / GHSA-6fqq-452j-qhrp
More information
Details
Summary
Applications that wrap a model with
ConcurrencyLimitedModelorlimit_model_concurrencycan permanently lose shared concurrency capacity when a streamed request releases its slot from a different task than the one that acquired it. This can happen when a stream ends early, and also when a stream is fully consumed using the defaultstream_text()debouncing.In an application that exposes an affected streaming endpoint to network clients and shares a long-lived model limiter across requests, a client can repeatedly start a stream and disconnect. The completed requests retain their slots, eventually preventing subsequent requests that share the limiter from proceeding.
Agent-level
max_concurrencyand non-streaming model requests are not affected by this defect.Details
The built-in limiter uses
anyio.CapacityLimiter, which associates each acquired slot with its borrowing task. Pydantic AI's streaming lifecycle can acquire the slot on the task consuming the stream and run cleanup on another internal task. The limiter rejects that release, so the slot remains occupied even after the request has ended. Cleanup can raise aRuntimeError; a later request on the borrowing task can also fail because that task still holds a slot.Early termination includes stopping iteration, a consumer exception, and cancellation. Fully consuming
stream_text()with its defaultdebounce_by=0.1can also reach the cross-task release path. Fully consumed streams must therefore not be assumed safe.Mitigation
Upgrade to a patched release of
pydantic-aiorpydantic-ai-slim. If you cannot upgrade yet, use the agent-levelmax_concurrencysetting instead of a concurrency-limited model, or avoid streaming runs through a concurrency-limited model.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Release Notes
pydantic/pydantic-ai (pydantic-ai)
v2.53.0: (2026-10-01)Compare Source
🛡️ Security
This release fixes one security issue in
ConcurrencyLimitedModel. See the advisory for full details and affected versions.ConcurrencyLimitedModelorlimit_model_concurrencycould 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 consumingstream_text()with its default debouncing. Repeated streams could then block every request sharing the limiter. Agent-levelmax_concurrencyand non-streaming requests are not affected. Reported by @lche511. (#9478)The fix also changes how limiters are shared: a model wrapper now raises
UserErrorwhen 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 customAbstractConcurrencyLimitermust allowrelease()from another task.Patched in
2.53.0. v1 is not affected.What's Changed
⚠️ Compatibility Notes
oneOfschema support toTestModel's generated data by @pydanty in #8783clai2plugins declarativePluginsubclasses, modeled onAbstractCapabilityby @mpfaffenberger in #9493clai2and deprecatepydantic_ai_harness.step_persistence.namingby @mpfaffenberger in #9499🚀 Features
posthogplugin topydantic-clai2with/keysor browser sign-in by @mpfaffenberger in #8901grainplugin toclai2with a keyring-backed Grain sign-in by @mpfaffenberger in #8905linearplugin toclai2with a settings menu and/keyscredentials by @mpfaffenberger in #8949usageby @pydanty in #8891AbsurdDurabilityto the harness as a replacement forpydantic-ai-absurdby @adtyavrdhn in #8946host.model_providerby @mpfaffenberger in #9468clai2status row by @mpfaffenberger in #9473pydantic-clai2by @mpfaffenberger in #9467clai2by @mpfaffenberger in #9480AskUserdefer questions to the host and time out a slow answerer by @mpfaffenberger in #9509/fastcommand to CLAI2 by @mpfaffenberger in #9518SystemOneModelto run decision models such as CLM and Laya over the/v1/systemoneAPI by @mpfaffenberger in #8942logfireplugin toobservabilityby @mpfaffenberger in #9566ToolCallJudgeto assess tool calls before execution by @DouweM in #9041observability(Logfire) plugin by @mpfaffenberger in #9306/updatewith stable (PyPI) and bleeding (main) channels by @mpfaffenberger in #9576/pluginsmenu themed and readable, with plugin descriptions by @mpfaffenberger in #9570clai2plugin settings with the features they need, and skip a plugin capability that rejects its settings at run setup by @mpfaffenberger in #9569repair_messagesby @DouweM in #8370🐛 Bug Fixes
LocalWorkspaceBackend.runtimeout fires during process startup by @dsfaccini in #9358clai-NAMEand reopen existing worktrees with--worktree NAMEby @mpfaffenberger in #9462CodeModeanalysis by @mpfaffenberger in #9475clai2resume sessions by repository identity by @mpfaffenberger in #9482Memorytoolset across runs so durable execution accepts it by @mpfaffenberger in #9489Planningtoolset across runs so durable execution accepts it by @mpfaffenberger in #9507BubblewrapSandboxon the next launch by @dsfaccini in #9457inf/-inf/nanby @pydanty in #8852gemini-3.1-flash-imagethinking efforts tominimalandhighon the Gemini API by @dsfaccini in #9515UnexpectedModelBehaviorinstead of running the wrong tool when function tool calls share atool_call_idby @pydanty in #8782/reloadhits a stale Harness import by @mpfaffenberger in #9571XaiModelthinking part per output, matching the non-streamed response by @DouweM in #9416OpenAIResponsesModelreplay whenopenai_store=Falseby @DouweM in #9388ModelResponsefrom streamed and completeOpenAIChatModelandOpenRouterModelresponses by @DouweM in #9418OpenAIResponsesModelbuild the sameModelResponsefrom a stream as from a complete response by @DouweM in #9417commit_audio()alone no longer triggers a reply, andcreate_response()is always answered by @DouweM in #9070status,status_detailsand session values the SDK does not know yet by @DouweM in #9392SubAgentsfrom forcingthinkingon disk agents by @DouweM in #9384DynamicWorkflowreveal announcements after compaction or history loss by @DouweM in #9371/compactby @mpfaffenberger in #9587clai2when capability functions supply none, and exposeunrestricted_filesystemin/plugins configure coderby @mpfaffenberger in #9593ActivityConfigschema by @pydanty in #9577GoogleRealtimeModeldeclare tools whosedictvalues are recursive models by @dsfaccini in #9607📦 Dependencies
termflow-md0.11.0 by @mpfaffenberger in #9483New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.52.0...v2.53.0
v2.52.0: (2026-09-29)Compare Source
🛡️ Security
This release fixes one security issue in
web_fetch. See the advisory for full details and affected versions.web_fetchtool could consume excessive CPU and memory. Provider-native web fetching is not affected. Reported by @SounLabs. (#8984)Patched in
2.52.0(v2) and1.107.7(v1).📦 Harness and CLAI 2
pydantic-ai-harnessnow lives in this repository and ships with every Pydantic AI release, so it jumps from0.36.0to0.52.0.pydantic-clai20.52.0is its first release:uvx pydantic-clai2.What's Changed
⚠️ Compatibility Notes
Coder,FileSystem,Shelland the rest work throughctx.workspace, locally or in a sandbox by @adtyavrdhn in #8866ModalSandbox's own tools with a Modal workspace, soCoder,ShellandFileSystemrun in the sandbox;ModalSandboxBackendreplacesModalSandboxSessionby @adtyavrdhn in #8867AnthropicModel's defaultmax_tokensfrom 4096 to 16384 on Claude Sonnet 4.5 and later by @DouweM in #9025DecisionModel's judgedtextafter a retry by @dsfaccini in #8967SubAgentsloading agent files by default, and deprecateinherit_toolsby @DouweM in #9023AnthropicModel'smax_tokensto the model's maximum output, streaming such requests behind the scenes by @DouweM in #9298🚀 Features
ctx.workspacegives 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 runsCoder,Shell,FileSystemand every other harness capability in a Fly.io Sprite by @adtyavrdhn in #8869E2BSandbox: a workspace that runsCoder,Shell,FileSystemand every other harness capability in an E2B sandbox by @adtyavrdhn in #8868Coderfile tools a retry budget of 5 and keep scratch files out of the project by @mpfaffenberger in #8970typesafeextra topydantic-clai2and reject models with a missing provider SDK at/modeltime by @mpfaffenberger in #8962claude-sonnet-5-5) support by @dsfaccini in #8974async_tool_call_modewith a sharedasync_tool_callssetting by @DouweM in #8813pydantic-clai2tool headers, clipped bydisplay.tool_arg_charsby @mpfaffenberger in #9100clai2plugin's settings menu when it is turned on, and end every settings menu with Save & close by @mpfaffenberger in #9102_process_provider_detailshook toOpenAIResponsesModelby @pydanty in #9094clai2 --agent MODULE:ATTRto chat with an existingAgentwith plugins off by @mpfaffenberger in #9291githubplugin toclai2with a settings menu and its token in/keysby @mpfaffenberger in #8904pylonplugin to CLAI2 with a settings menu and a named/keysentry by @mpfaffenberger in #8953gemini-3.1-flash-live-previewandgemini-3.8-liveby @DouweM in #9047answer_webrtc_offerand a sideband session by @DouweM in #9059SSHWorkspaceandBubblewrapSandboxharness capabilities by @mpfaffenberger in #8956pydantic-clai2console script souvx pydantic-clai2runs CLAI by @mpfaffenberger in #9304azure_voice_live_voiceto choose an Azure voice for Azure AI Voice Live sessions by @DouweM in #9044google_workspaceas a built-inclai2plugin backed by harnessGoogleWorkspaceby @mpfaffenberger in #8907thinking,openai_turn_detection,openai_input_noise_reductionand a newazure_voice_live_temperatureon Azure AI Voice Live by @DouweM in #9051gemini-3.8-liveby @DouweM in #9058day_aiplugin toclai2with a settings menu and/keysor browser sign-in by @mpfaffenberger in #8940RequestUsage.extract()failures by @adtyavrdhn in #8564ordinalplugin toclai2with token or keyring-backed browser sign-in by @mpfaffenberger in #8941default_cache_retention+prompt_cache_outlook()cold-window helper; renameresolve_prompt_cache_retention()toresolve_cache_retention()by @DouweM in #6337notionplugin toclai2with a settings menu and its key in/keysby @mpfaffenberger in #8944thinkingandparallel_tool_callssettings to the GPT-Live backend model by @DouweM in #9040mxfp4,nvfp4, andmxfp8OpenRouterquantizationsand theexactosortvalue by @harimaruthachalam in #8888slackplugin topydantic-clai2with a settings menu,/keysuser token, or browser sign-in by @mpfaffenberger in #8908logfire_mcpbuilt-in plugin toclai2with/keys,LOGFIRE_API_KEY, and keyring-backed OAuth by @mpfaffenberger in #8903gpt-6.1-solmodel support and allow image output ongpt-6-astraby @dsfaccini in #9305🐛 Bug Fixes
application/tomlas text-like for inline model inputs by @JoeyTan21 in #8848wait_for_reply()hanging on merged or failed replies by @DouweM in #8765ModelProfileso they apply on every provider route by @DouweM in #8808RealtimeTurnCompleteEventbefore the spoken answer by @DouweM in #8766output_typeby @DouweM in #8812max_tokensby @DouweM in #8986response.createby @DouweM in #8763UserErrorinstead ofModelRetryforMacroscopesetup failures by @DouweM in #8999RequestUsage.detailsand price them incostby @dltsum in #8310clai2menus by @mpfaffenberger in #9101!commandshell descendants on cancellation inclai2by @dafyy321-pixel in #9092UserWarnings inclai2, and groupCodeModemissing-return-schema warnings by @mpfaffenberger in #9099clai2shell process startup by @DouweM in #9104compact_messages()by @yang0228 in #8241clai2recalls a slash command by @mpfaffenberger in #9297azure_voice_live=Trueforgpt-realtime-2models onAzureRealtimeModelby @DouweM in #9050handshake_timeoutby @DouweM in #9042gemini-live-2.5-flashand remove a stale Gemini Live docs claim by @DouweM in #9069DeferredToolRequestsEventin realtime sessions before theHandleDeferredToolCallshandler runs by @DouweM in #9057ModelAPIErrorby @pydanty in #8846ModelAPIErrorinOpenAIChatModel,GroqModelandHuggingFaceModelby @DouweM in #9313ModelAPIErrorinstead ofValidationErrorwhen anOpenRouterModelstream drops mid-response by @DouweM in #9312capabilitiesdocs topic fromcapabilities/overview.mdinPydanticAIDocsby @DouweM in #9011FileSystemdefaultread_only_patternsto nested.envand.git/paths by @DouweM in #9021CodeModediscovery announcements after compaction or history loss by @DouweM in #9045TrajectoryJudgewindow when the transcript is clamped by @DouweM in #9012ContentFilterErrorfor a thinking-only response refused by the content filter, instead of retrying by @DouweM in #9355BubblewrapSandboxby @mpfaffenberger in #9349LogfireMCPinstructions so they stop busting the prompt cache by @mpfaffenberger in #9319ModelAPIErrorwhen the OpenAI Responses API reports a failed response or anerrorstream event by @DouweM in #9321MistralErrorfrom the Mistral SDK toModelHTTPErrororModelAPIErrorby @DouweM in #9307GoogleModel.count_tokensandXaiModelfile uploads by @DouweM in #9308ClampOversizedMessages,SubAgents, andStepPersistenceby @DouweM in #9026datavalidation errors underresult.dataso retry feedback keeps the failing input by @pydanty in #8669shelljob log deleted mid-read as empty instead of failing the call by @dsfaccini in #9322turn_complete_reasonas the realtime response'sfinish_reasonby @DouweM in #9390request_limitby @DouweM in #9380SubAgentusage toward parent budgets by @DouweM in #9374📦 Dependencies
New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.51.0...v2.52.0
v2.51.0: (2026-09-25)Compare Source
What's Changed
⚠️ Compatibility Notes
gemini-3.8-liveids, rejectgoogle_affective_dialogon Gemini 3.1 Flash Live and 3.8 Live at connect, and raiseRealtimeErrorfor Gemini Live close codes by @DouweM in #8761UserErrorfor a realtimetool_choicethat forces a tool call on OpenAI, Azure OpenAI, and xAI by @DouweM in #8755🚀 Features
OpenAILiveModelby @DouweM in #8390context_window_usedon realtime sessions, from GPT-Live's reported ratio or response usage by @DouweM in #8803🐛 Bug Fixes
RunContextcopying overhead in capability hooks by @Kludex in #8775provider_detailson OpenAI Realtime tool-call responses and the response id on replies cut off by a drop orclose()by @DouweM in #8762CompletedStreamedResponsereplay by @Kludex in #8799Agent.run()by @Kludex in #8658Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.50.0...v2.51.0
v2.50.0: (2026-09-24)Compare Source
What's Changed
⚠️ Compatibility Notes
DecisionModelwhich route to take by name, with one label per route by @DouweM in #8733ModelSelectionContext.messagesend with the request being routed, and addModelSelectionContext.promptby @DouweM in #8737decision_route_thresholdby @DouweM in #8739🚀 Features
service_tierin provider details by @pydanty in #7945DecisionModel, a base for Decisions-protocol models, and makeTypeSafeModelone by @DouweM in #8696RunContext.in_durable_contextso hooks can tell they run in durable workflow code by @mpfaffenberger in #8723gemini-3.8-liveandgemini-3.8-live-extended-thinkingrealtime support by @DouweM in #8393DecisionModel's route fields with the route question under a route premise, with nested-fieldcontextand adonestate after tool calls by @DouweM in #8749decidespan for every request aDecisionModelsends by @DouweM in #8698🐛 Bug Fixes
OutputSpec[T]passed toAgent.rununder mypy by @DouweM in #8730ThinkingParts in the history decision models judge by @DouweM in #8738RequestUsage.audio_secondsso duration-billed voice models are priced by @DouweM in #8427output_typeas a route beside other routes, and renameToolCallProposedtoUnfillableRouteunder aDecisionHandOffbase by @DouweM in #8744wait_for_reply()no longer hangs on it by @DouweM in #8747thinking=Falseon OpenAI Realtime by sendingreasoning.effort: 'none'by @DouweM in #8753context_windowfrom genai-prices and document compacting a Jev conversation by @DouweM in #8740stream_audio()view so speaker-paced playback gets whole replies by @DouweM in #8750RealtimeSessionErrorEventby @DouweM in #8752Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.49.0...v2.50.0
v2.49.0: (2026-09-23)Compare Source
What's Changed
🚀 Features
GitHubCopilotOAuthFlowfor device authorization by @Kludex in #8618BoolCriteriato say what aboolfield's yes and no mean, and let aTrue/FalseEnumdo the same by @DouweM in #8586Noneas the "none of these" option inTypeSafeModelby @DouweM in #8684ChoiceinTypeSafeModelby @DouweM in #8686RealtimeSession.wait_for_reply()by @DouweM in #8514🐛 Bug Fixes
OpenAIChatModellogprobs inprovider_details['logprobs']by @adtyavrdhn in #8653gpt-6-sol,gpt-6-luna, andgpt-6-astraon Bedrock Converse by @sevakva in #8656@GraphBuilder.streamnode errors in-context duringgraph.iter()by @pydanty in #8304gs://references asfileDatainGoogleImageGenerationModelon Vertex AI by @dorukgezici in #8225Annotatedmodel types by @ikriv in #8608Nonein a list of output types as| Nonesooutput_type=[Foo, Bar, None]passes pyright by @DouweM in #8641google_proactive_audio, which no Gemini Live session could ever connect with by @DouweM in #8394temperatureandtop_pfor OpenAI GPT-5.6 and GPT-6 on Bedrock Converse instead of failing with a 400 by @kimnamu in #8668TypeSafeModelanswers "None of these" for an optional field by @DouweM in #8685send_audio(iterable)cleanly on close by @DouweM in #8138Annotatedmetadata on the members of anX | Youtput_typeby @DouweM in #8687TypeSafeModelanswers "None of these" for every field under it by @DouweM in #8697Annotated,Literaland unionoutput_types as PEP 747TypeForms, and bump pyright to 1.1.414 by @DouweM in #8690RunContext.tracer,trace_include_contentandinstrumentation_versionfollow an explicitInstrumentationcapability by @DouweM in #8706OpenAICodexModelinstead of failing with a 400 by @aweis89 in #8693New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.48.0...v2.49.0
v2.48.0: (2026-09-22)Compare Source
What's Changed
🚀 Features
genai-prices0.1.7 and new OpenAI audio models by @adtyavrdhn in #8617gpt-6-solandgpt-6-lunamodel support by @DouweM in #8635claude-opus-5-5) support by @DouweM in #8637🐛 Bug Fixes
UIMessage.idacross Vercel AIload_messagesanddump_messagesby @adtyavrdhn in #8623Message.idacrossAGUIAdapter.load_messagesanddump_messagesby @adtyavrdhn in #8632📦 Dependencies
genai-pricesto 0.1.8 by @DouweM in #8648Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.47.0...v2.48.0
v2.47.0: (2026-09-21)Compare Source
What's Changed
⚠️ Compatibility Notes
Noneoutput routeNonerather thanNoneTypeby @DouweM in #8590UserPromptPart.contentis not astror a sequence, instead of silently sending adict's keys by @DouweM in #8595🚀 Features
TypeSafeModelcan already answer by @DouweM in #8544🐛 Bug Fixes
tupleoutput field and a self-contained model instead of crashing by @DouweM in #8537Nonebe a routeTypeSafeModelcan pick by @DouweM in #8540Choicesset describe itself as aTypeSafeModelroute by @DouweM in #8541Noneroute and aNoneoption that carry a description by @DouweM in #8598TypeSafeModelrequest that fills it by @DouweM in #8589📦 Dependencies
ag-ui-protocolto<1by @adtyavrdhn in #8579New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.46.0...v2.47.0
v2.46.0: (2026-09-18)Compare Source
What's Changed
🚀 Features
TypeSafeModelfill 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_outputtoModelProfile, and runLLMJudgeandGEvalon a model without it by @DouweM in #8480typesafe_boolean_thresholdfor what a yes/no has to be before it isTrueby @DouweM in #8505TypeSafeModelfill a union of output types by choosing the type first by @DouweM in #8481event_stream_topictoTemporalDurabilityto stream agent events via Workflow Streams by @brianstrauch in #6639Enum's options by its member docstrings when it mixes inUseEnumMemberDocstringsby @DouweM in #8479Choiceshelper for a set of described options built at run time by @DouweM in #8530🐛 Bug Fixes
TypeSafeModelby @DouweM in #8484ToolReturnPartwhen a realtime tool raises, and keep a tool call and its speech in oneModelResponseby @DouweM in #8135ToolDefinitioninCombinedToolsetandFunctionToolsetby @adtyavrdhn in #8082ModelRetrywhenweb_fetch_toolgets a URLhttpx2rejects as invalid by @DouweM in #8521usage.costandUsageLimits.cost_limitwork in a session by @DouweM in #8136New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.45.0...v2.46.0
v2.45.0: (2026-09-17)Compare Source
What's Changed
🚀 Features
TypeSafeModelfor TypeSafe's Jev by @adtyavrdhn in #8450🐛 Bug Fixes
xhigheffort through on Bedrock when the model profile supports it by @willfrey in #8392gpt-5.6-sol,gpt-5.6-luna, andgpt-5.6-terraon Bedrock Converse by @pydanty in #7825DynamicToolsetonce per durable run instead of inside every durable unit by @DouweM in #8455MCPSamplingModelby @DouweM in #8466httpxinpydantic_ai.mcp, which a FastMCP 4 install does not ship by @DouweM in #8461New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.44.0...v2.45.0
v2.44.0: (2026-09-16)Compare Source
🛡️ Security
This release fixes four security issues, all of them reached through
web_fetch_toolor OpenTelemetry instrumentation. See each advisory for full details and affected versions.FileUrl(force_download='allow-local')orweb_fetch_tool(allow_local_urls=True). Both are off by default. Reported by @euriconicacio. (#8401)web_fetchprocessed 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) and1.107.6(v1).What's Changed
⚠️ Compatibility Notes
RunContext.enqueue()safe from worker threads by @adtyavrdhn in #7758Content-Typeon UI adapter requests by @DouweM in #8396@durable_operationcalled from a per-request hook, instead of silently running it inline by @DouweM in #8395🚀 Features
AgentRunResulta stable serialized shape, and settle a finished stream into one by @DouweM in #8269Storagepage so persistence is findable by @DouweM in #8336EnqueuedMessagesEventwhen a realtime session delivers enqueued content by @DouweM in #8134🐛 Bug Fixes
blocked_domainsto OpenAI web search by @adtyavrdhn in #8323tool_searchpairing 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_toolsover every tool the availability gate admits by @DouweM in #8071New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.43.0...v2.44.0
v2.43.0: (2026-09-11)Compare Source
What's Changed
🚀 Features
claisessions with it by @DouweM in #7447🐛 Bug Fixes
OpenAIChatModelby @KaranJayakumar in #8235New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.42.0...v2.43.0
v2.42.0: (2026-09-08)Compare Source
What's Changed
⚠️ Compatibility Notes
DeferredToolResults.approvalsvalues by @adtyavrdhn in #8081🚀 Features
GitHubCopilotProviderfor GitHub Copilot's OpenAI-compatible API by @dsfaccini in #8059🐛 Bug Fixes
anthropic_disallows_sampling_settingsinBedrockConverseModelby @rscholz98 in #7961$refdefinitions inline in code-mode function signatures by @pydanty in #8056ToolReturnContentwithout a Python call per JSON node by @dsfaccini in #7823New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.41.0...v2.42.0
v2.41.0: (2026-09-07)Compare Source
What's Changed
🚀 Features
fallback_modelin favor offallback_subagent_modelonImageGenerationandXSearchby @dsfaccini in #8077openai-codexprovider for ChatGPT/Codex subscription authentication by @mpfaffenberger in #7769ImageGeneratorby @EgonFerri in #5357🐛 Bug Fixes
RequestUsage.detailsand price them incostby @adtyavrdhn in #8169ModelAPIErrorinBedrockConverseModelby @kimnamu in #8131New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.40.0...v2.41.0
v2.40.0: (2026-09-04)Compare Source
What's Changed
🚀 Features
pydantic_ai.prices.update_in_background()by @adtyavrdhn in #4841handle_barge_in=True,interrupt(played_bytes=...), andplayed_audio_bytesby @DouweM in #7870provider_factorytoinfer_realtime_modelby @DouweM in #8106@agent.on_eventfor registering event listeners on anAgentby @DouweM in #8101respond=toRealtimeSession.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 #8109🐛 Bug Fixes
finish_reasonon OpenAI Responses stream terminal events by @pydanty in #7916defer_loadingreveal synthesis splitting a parallel batch'stool_resultfrom itstool_useby @pydanty in #7879reasoningto the datedgpt-realtime-2025-08-28snapshot by @DouweM in #8103stream_audio()andstream_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 #8132New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.39.0...v2.40.0
v2.39.0: (2026-09-03)Compare Source
What's Changed
🚀 Features
gpt-6-astramodel support by @dsfaccini in #8055🐛 Bug Fixes
context_subtree()exporter cache and its span-processor leaks by @dsfaccini in #7667Instrumentationspec optioninclude_model_request_parametersand sharpen the undeclared-attribute merge error by @DouweM in #8046AzureProviderand forAsyncAzureOpenAIclients onOpenAIProviderby @quinnarnold in #7922stream_transcripts()by @DouweM in #8062Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.38.0...v2.39.0
v2.38.0: (2026-09-03)Compare Source
What's Changed
⚠️ Compatibility Notes
idand acombinerule for repeats by @dsfaccini in #7248🚀 Features
context_windowtoModelProfileandcontext_window_usedtoRunContextby @adtyavrdhn in #4611finish_reasonby @jonashaag in #7096gemini-3.8-flashmodel by @dsfaccini in #8021CustomEvents andCapabilityEvents into the run event stream and subscribe with@on_eventby @DouweM in #6258claude-fable-5-1) and Claude Mythos 5.1 (claude-mythos-5-1) support by @dsfaccini in #7989VLLMProviderfor vLLM servers by @adtyavrdhn in #6153🐛 Bug Fixes
CancellationTokenin UI adapter run methods by @dsfaccini in #7743pytest tests/durable_exec/temporalfrom crashing when the suite's requirements are missing by @dsfaccini in #7898tool_choicehandling and supportNativeOutputon DeepSeek's Responses API by @dsfaccini in #7450CodeExecutionTooluploads never reaching a fresh Anthropic container on a multi-turn history by @dsfaccini in #7864REASONING_*events fromag-ui-protocol0.1.11 instead of 0.1.13 by @dsfaccini in #7226GoogleProvider's overload by @dsfaccini in #8030XaiModelstreamed text after a native tool call being merged into the ended pre-call part by @pydanty[bot] in #7925nativefactory config inXSearchandImageGenerationfallback subagents by @CoralGarden52 in #7541📦 Dependencies
genai-pricesto 0.1.6 by @adtyavrdhn in #8019New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.37.0...v2.38.0
v2.37.0: (2026-08-31)Compare Source
What's Changed
🚀 Features
glm-5.3-flashand rework the Z.AI test suite onto cassettes by @dsfaccini in #7887🐛 Bug Fixes
finish_reasonvalues by @zhj12395 in #7685TEXT_MESSAGE_STARTfor the assistant message that owns a response's tool calls by @dsfaccini in #7699GoogleModelby client transport instead of provider name by @thejamesgore in #7280capabilities=on DBOS, matching Temporal by @DouweM in #6955New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.36.0...v2.37.0
v2.36.0: (2026-08-28)Compare Source
What's Changed
⚠️ Compatibility Notes
--mcp-configsupport and tool-call streaming toclaiby @Kludex in #1374🚀 Features
@durable_operationfor capabilities and a public backend API for third-party durable execution engines by @DouweM in #6696InstructionPart.idby @DouweM in #6887RealtimeSession.send_audio()and move the voice example tolistentomeby @DouweM in #7860@durable_operationby @DouweM in #7868🐛 Bug Fixes
TestModelgeneration for narrow exclusive numeric bounds by @Terminator666666 in #7800ToolDefinitioninto Prefect cache keys by @DouweM in #7872New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.35.3...v2.36.0
v2.35.3: (2026-08-27)Compare Source
What's Changed
🐛 Bug Fixes
zai_model_profileby @LHMQ878 in #6837safe_downloadcookies to original hostnames by @Diwak4r in #7077DeferredToolRequests.remainingresolving cross-category result IDs by @pydanty in #7626dbosextra; addopentelemetry-instrumentation-loggingas a test dependency instead by @dsfaccini in #7820Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.35.1...v2.35.3
v2.35.1: (2026-08-26)Compare Source
What's Changed
🐛 Bug Fixes
traceinModelResponse.provider_detailsby @pydanty in #7562provider_factorywhen cancelling Temporal responses by @DouweM in #7000dbosbelow 2.31.0 to avoid a missingopentelemetry-instrumentation-loggingimport by @dsfaccini in #7804Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.35.0...v2.35.1
v2.35.0: (2026-08-25)Compare Source
What's Changed
⚠️ Compatibility Notes
RunContext.capability_loadedandavailable_capability_idsin favor ofcapability_activeandactive_capability_idsby @DouweM in #7454maximumreachable inTestModelby @pydanty in #7697🚀 Features
🐛 Bug Fixes
Tooldescription instead of falling back to the function docstring by @mpfaffenberger in #7759Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.34.0...v2.35.0
v2.34.0: (2026-08-24)Compare Source
What's Changed
🚀 Features
ZaiModelby @aisk in #7600🐛 Bug Fixes
TestModelgeneration for equal inclusive bounds by @pydanty in #7642LiteralinFunctionSignatureby @pydanty in #7579TestModelgeneration of falsy JSON Schemaconstvalues by @pydanty in #7630UIEventStreampart state on cancellation by @adtyavrdhn in #7675logit_biasfrom Cerebras model settings by @ryanl-cerebras in #7653VercelAIAdapterrejecting reasoning partidin run input by @pydanty in #7706CohereModelby @pydanty in #7720VercelProviderdropping the Groq profile forgroq/-prefixed models by @pydanty in #7551SpanQuerymaximums by @lntutor in #6934Retry-Afterdates inwait_retry_after()by @parveshsaini in #7711load_capabilityby @lntutor in #6937r1alias indeepseek_model_profile()by @adtyavrdhn in #7723New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.33.0...v2.34.0
v2.33.0: (2026-08-20)Compare Source
⚠️ If Anthropic stopped working for you in the last day
anthropic1.0.0 — rebuilt onhttpx2, with legacyhttpxsupport 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 ofpydantic-ai[anthropic]could resolveanthropic1.0.0 and then fail at runtime when using an Anthropic model. Apologies for the breakage window.pydantic-aiv2.33.0, which requires and supportsanthropic>=1.0.0.anthropic<1.If you pass your own
http_clienttoAnthropicProvider, it must now be anhttpx2.AsyncClient— the 1.x SDK rejects legacyhttpxclients at construction.What's Changed
⚠️ Compatibility Notes
httpx2for Anthropic clients by @dsfaccini in #7657Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.32.2...v2.33.0
v2.32.2: (2026-08-20)Compare Source
What's Changed
🐛 Bug Fixes
pydantic_evalstasks and theevaluatedecorator by @pydanty[bot] in #7535RunContext.cancel()in realtime sessions by @adtyavrdhn in #7528m.youtube.comURLs inVideoUrlby @uczltw6 in #7592UnexpectedModelBehaviorandFallbackExceptionGroupunder the deprecatedTemporalAgentby @aviseth in #7465New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.32.1...v2.32.2
v2.32.1: (2026-08-19)Compare Source
What's Changed
🐛 Bug Fixes
Agent.run_sync()from synchronous callbacks inside agent runs by @dsfaccini in #7277thinkingblocks with an empty signature by @mpfaffenberger in #7601FunctionModelfunctionorstream_functionby @dsfaccini in #7589Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.32.0...v2.32.1
v2.32.0: (2026-08-18)Compare Source
What's Changed
🚀 Features
provider_details["annotations"]by @dsfaccini in #7458role: 'tool'by @dsfaccini in #7582🐛 Bug Fixes
timeout=for blocking sync tools and hooks by @adtyavrdhn in #7557RunContext.cancel()from setup-phasefor_runhooks instead of raisingUserErrorby @adtyavrdhn in #7567📦 Dependencies
httpx2for compatible HTTP clients by @dsfaccini in #7351Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.31.1...v2.32.0
v2.31.1: (2026-08-17)Compare Source
What's Changed
🐛 Bug Fixes
thinking_level='LOW'for Gemini models that rejectMINIMALby @pydanty[bot] in #7469Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.31.0...v2.31.1
v2.31.0: (2026-08-14)Compare Source
What's Changed
🚀 Features
UIEventStreamto be built without arun_input, and giveAGUIEventStreamits ownthread_id/run_idby @dsfaccini in #7292🐛 Bug Fixes
FallbackModelspans to the failing model, not thefallback:wrapper by @strawgate in #7018openaithrough Temporal workflow sandboxes by @adtyavrdhn in #7464New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.30.0...v2.31.0
v2.30.0: (2026-08-13)Compare Source
What's Changed
🛡️ Security
Agent.to_web(),clai web) didn't validate theHostheader, 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 inpydantic-ai/pydantic-ai-slim2.30.0 by validatingHostagainst localhost/loopback/LAN addresses by default; deployments reached under a real hostname must opt in with the newallowed_hostssetting.🚀 Features
openrouter:web_searchfor web search by @dsfaccini in #7378gemini-3.7-flashmodel by @dsfaccini in #7445metadataonXaiProviderby @pydanty[bot] in #7423allowed_hoststoAgent.to_web()andclai webby @DouweM in #7437🐛 Bug Fixes
openairesource imports and genai-prices data loading atModelconstruction time by @adtyavrdhn in #7408EvaluationReport.print()on non-UTF-8 consoles by @dsfaccini in #7290Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.29.0...v2.30.0
v2.29.0: (2026-08-12)Compare Source
What's Changed
🚀 Features
MCPToolsetalongside FastMCP 3 by @adtyavrdhn in #6738azure_voice_livesetting by @DouweM in #6642🐛 Bug Fixes
for_realtimebugs from#6676by @DouweM in #7412New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.28.0...v2.29.0
v2.28.0: (2026-08-11)Compare Source
🛡️ Security
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 requiresContent-Type: application/jsonand rejects other requests before the body is parsed and before the agent runs. See GHSA-h4xc-3qfq-jf93. Patched in2.28.0(v2) and1.107.4(v1).What's Changed
🚀 Features
Agent.realtime()by @DouweM in #6324🐛 Bug Fixes
CachePointto the preceding user message instead of raising by @Diwak4r in #7071PeekableAsyncStreampulls by @mikemikimike in #7023state_restoredhonestly on realtime reconnect by @DouweM in #7379await_maybehelper by @DouweM in #7265safe_downloadHost header dropping non-default port by @pydanty[bot] in #7348📦 Dependencies
cerebrasoptional dependency group by @dsfaccini in #7387New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.27.1...v2.28.0
v2.27.1: (2026-08-10)Compare Source
🛡️ Security
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 in2.27.1(#7357); v1 users should upgrade to1.107.4or later.What's Changed
🐛 Bug Fixes
XaiStreamedResponsefinish_reason mapping for streaming responses by @pydanty[bot] in #6814RetryPromptPartOpenTelemetry content oninclude_contentby @sean-kim05 in #7357Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.27.0...v2.27.1
v2.27.0: (2026-08-07)Compare Source
What's Changed
🚀 Features
xai_agent_counttoXaiModelSettingsby @pydanty[bot] in #7155CompactionPartthrough the Vercel AI and AG-UI adapters by @DouweM in #7287SnowflakeModelandSnowflakeProviderfor Snowflake Cortex by @ayirpown in #6150🐛 Bug Fixes
include_binary_content=Falsein every OTel serialization sink by @dsfaccini in #7131ToolReturn.toolsin the redacted OTel shape by @DouweM in #7273SpanQueryhas_attributesmatching for JSON-serialized dict and list values by @pydanty[bot] in #5905encrypted_contentverbatim by @DouweM in #7286sanitize_messagesby @DouweM in #7285New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.26.0...v2.27.0
v2.26.0: (2026-08-06)Compare Source
What's Changed
🚀 Features
load_capability, orToolReturn.tools— using each provider's native deferral/addition channel by @DouweM in #7104AgentRun.cancel(),RunContext.cancel(),RunCancelledby @DouweM in #6497Model.resolve_prompt_cache_retention()to resolve effective prompt-cache retention from model settings by @DouweM in #7254run_stream_events()iterator to publicAgentRunEventshandle withcancel()and run-state access by @DouweM in #6498OpenAIResponsesModel+DeepSeekProviderby @dsfaccini in #7202🐛 Bug Fixes
model_idthroughWrapperModeland resolve it against the active model inTemporalModelby @dsfaccini in #7181supports_inline_system_prompts=Falseby @DouweM in #7253is_tool_available,TestModelnative additions) by @DouweM in #7260CompactionPartboundaries by @DouweM in #7225UIEventStreamcallbacks that return an async iterator without being an async generator function by @DouweM in #7256CompactionPartby @DouweM in #7228New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.25.0...v2.26.0
v2.25.0: (2026-08-05)Compare Source
What's Changed
🚀 Features
FileSearchToolcollections search options by @pydanty[bot] in #7154🐛 Bug Fixes
max_tokensfor Mistral models, notmax_completion_tokensby @feiiiiii5 in #6929base_urlport and forwardbase_urlthroughWrapperModelby @dsfaccini in #7136thinking="minimal"for GPT-5.6 models by @daikeren in #7082ToolCallPart.args_as_json_str()by @dsfaccini in #7092New Contributors
Full Changelog: https://github.com/pydantic/pydantic-ai/compare/v2.24.0...v2.25.0
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate CLI.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.