github pydantic/pydantic-ai v2.58.0
v2.58.0 (2026-10-19)

latest release: v1.107.8
4 hours ago

This comment was posted by codex-tui using gpt-6.1-sol on behalf of David.

What's Changed

🛡️ Security

  • Medium — MCP request telemetry: GHSA-xv4x-g8mx-ch56. Provider-native MCP configuration could expose server URLs, authorization tokens and custom header values in OpenTelemetry request traces, even with include_content=False. URL-based MCP capabilities could also expose a credential embedded in the URL-derived identifier. Fixed in v2.58.0 and v1.107.8. Restrict access to historical traces and rotate exposed credentials.
    Temporal mitigation: URL-based MCP activity names remain unchanged to preserve in-flight workflows. With Temporal tracing enabled, also pass an explicit id= to MCP once in-flight workflows complete; changing it renames the activities.
  • Medium — UI adapter history: GHSA-5pfm-2g3g-gh85. With non-empty server-side message_history and manage_system_prompt='server' (the default), Vercel AI and AG-UI adapters could execute an available tool with client-chosen arguments without a model request. Approval-required tools are not executed by this path. Fixed in v2.58.0; v1 is unaffected.

⚠️ Compatibility Notes

  • Count a resumed 'suspended' response's usage only in the run that produced it, in RunUsage, UsageLimits and SpendLimits by @DouweM in #10078
  • Make RealtimeConnection yield lifecycle events through a public pydantic_ai.realtime.lifecycle module by @DouweM in #10353
  • Let read_file return images and PDFs, and describe other binary files by @DouweM in #9596
  • Record a realtime reply the user cut off after it finished generating as interrupted, and mark interrupted speech when seeding by @DouweM in #10466
  • Treat a native tool as unsupported when the model can't apply its allowed_domains, blocked_domains, max_uses or external_web_access setting by @DouweM in #10451
  • Add request-scoped SystemPromptPart(scope='request') sent natively as Anthropic clear_at system messages by @DouweM in #9711
  • Send Harness WarnNearLimits warnings as request-scoped system prompts by @DouweM in #10561
  • Escape RepoContext <context-file> blocks and send the nested-directory pointer as a SystemPromptPart by @DouweM in #10558
  • Make the profile's supports_auto_cache decide anthropic_cache, and use automatic caching on legacy AsyncAnthropicBedrock for Claude Opus 4.7 and later by @DouweM in #10551
  • Let any module define a ToolKind with typed tool parts, and keep unknown kinds loadable by @DouweM in #9710
  • Emit Planning status-tool events after their store reads, so DBOS recovery with an event_stream_handler replays in order by @dsfaccini in #10343
    Existing DBOS workflows using Planning with an event_stream_handler may not recover after upgrading; let in-flight workflows finish first or deploy a new DBOS application version.
  • Align RealtimeTurnCompleteEvent with the exchange boundary that wait_for_reply() waits for by @DouweM in #10517
    To react when a particular response ends, use its PartEndEvents. Caption UIs should keep user parts open until their PartEndEvent, which can arrive after the reply completes.

🚀 Features

  • Steer a running delegated task with DelegationTasks.steer by @mpfaffenberger in #10359
  • Store each message once in SqliteStepStore instead of repeating the history in every snapshot by @aweis89 in #9982
  • Add ModelSettings['max_retries'] to set how many times the provider SDK retries a request by @DouweM in #10068
  • Bound a whole agent run with timeout= and RunContext.deadline by @DouweM in #10070
  • Stream ctx.enqueue messages to Vercel AI and AG-UI frontends as history they send back but don't render by @DouweM in #10405
  • Add ModelSettings['request_timeout'] covering all attempts and stream consumption of one model request by @DouweM in #10072
  • Store each message once in PostgresStepStore and MongoStepStore instead of repeating the history in every snapshot by @DouweM in #10452
  • Let harness Skills ignore include and exclude names no library has with unknown_names='skip' by @mpfaffenberger in #10506
  • Add the openai-chatgpt provider so app users can sign in with ChatGPT and use their plan by @mpfaffenberger in #10539
  • Accept timeout= on UI adapter run_stream(), run_stream_native() and dispatch_request() by @DouweM in #10553
  • Add reasoning_summary to OpenAILiveResponsesDelegation to request the GPT-Live backend's reasoning summaries by @DouweM in #10514
  • Warn with UnsupportedSettingWarning when a model ignores a setting like timeout, max_retries or stop_sequences by @DouweM in #10508
  • Add openai_prune_tool_items to delete answered tool rounds from the OpenAI Realtime conversation by @DouweM in #10556
  • Add ElevenLabsAgentsRealtimeModel to run realtime sessions on ElevenLabs Agents by @rscholz98 in #7964

🐛 Bug Fixes

  • Stop wait_for_reply() waiting forever when a realtime tool batch receives no reply after a call is cancelled by @DouweM in #10503
  • Label a symlinked RepoContext instruction file with its target's name, so CLAUDE.md -> AGENTS.md reads AGENTS.md by @mpfaffenberger in #10438
  • Keep mid-run system prompts when ReinjectSystemPrompt(replace_existing=True) replaces the client's by @DouweM in #10389
  • Keep parallel tool calls in one ModelResponse when VercelAIAdapter loads messages by @DouweM in #10404
  • Stream the returns of tool calls skipped after a final result to AG-UI and Vercel AI frontends by @DouweM in #10409
  • Fix tool_choice='none' on BedrockConverseModel failing after a tool call by @DouweM in #10395
  • Resolve the default output mode once per run so toggling thinking per step keeps tools stable by @DouweM in #10398
  • Clear tool results in batches under ClearToolResults(max_messages=...) instead of on every request past the threshold by @DouweM in #10390
  • Force a single tool natively on MistralModel instead of filtering tools by @DouweM in #10394
  • Don't crash on a CachePoint after a replayed Anthropic MCP tool result by @DouweM in #10369
  • Fall back on stream errors raised before the first event in FallbackModel by @DouweM in #10386
  • Raise in run_stream() instead of returning a response that a model request hook rejected with ModelRetry by @DouweM in #10400
  • Give a model's provider a new HTTP client on a new event loop, and keep Model instances a selector returns open inside async with agent: by @DouweM in #10377
  • Carry non-native ThinkingParts in a user turn for models that imitate assistant formatting by @dsfaccini in #6692
  • Send tool-call args as compact JSON from ToolCallPart.args_as_json_str() so UI round trips keep the prompt cache by @DouweM in #10410
  • Send tool results in call order from Model.prepare_messages so UI round trips keep the prompt cache by @DouweM in #10411
  • Close the AsyncInferenceClient that HuggingFaceProvider builds when the provider or agent exits by @DouweM in #10393
  • Keep ToolReturn(tools=...) reveals when a Vercel AI frontend rebuilds history from the event stream by @DouweM in #10401
  • Skip the gh-aw pydantic-ai engine when an earlier step wrote a noop to GH_AW_SAFE_OUTPUTS by @dsfaccini in #10450
  • Restore the files #10457 accidentally reverted, including request_timeout by @DouweM in #10483
  • Update RealtimeSession.context_window_used together with the usage it reports by @DouweM in #10467
  • Don't load the tokenizer to replay an empty GPT-Live history on a redial by @DouweM in #10474
  • End an OpenAI realtime response created without an id when a malformed response.done closes it by @DouweM in #10511
  • Call OpenAIResponsesModel._process_provider_details on streamed responses too by @DouweM in #10515
  • Let shielded model-stream cleanup finish when an outer anyio cancel ends a debounced stream_text(), stream_output() or stream_response() by @dsfaccini in #10448
  • Add ModelProfile.tool_call_id_length and rewrite tool call IDs that Mistral models reject by @DouweM in #10519
  • Use automatic prompt caching (anthropic_cache) on AsyncAnthropicVertex by @DouweM in #10513
  • Inline GLM-5.3 tool schemas on Z.AI, Mistral, and OpenRouter by @2Zest in #10607
  • Walk propertyNames and contains when inlining JSON Schema definitions by @jukebox in #10588
  • Keep an unsaved openai-codex or openai-chatgpt token refresh instead of reverting to the stored credentials it spent by @mpfaffenberger in #10615
  • Keep a request's separate UserPromptParts through a VercelAIAdapter round trip by @DouweM in #10532
  • Escape tool names in CodeMode discovery announcements and stop recognizing announcements by their text by @DouweM in #10559
  • Keep every usage counter in RunUsage.__sub__, so durable runs keep one-hour cache writes and reasoning tokens, and declare cache_write_1h_tokens and output_reasoning_tokens by @DouweM in #10516
  • Don't ask again for a realtime tool batch's reply when the caller's send() of its last result failed by @DouweM in #10512
  • Keep a request's separate UserPromptParts through an AGUIAdapter round trip by @DouweM in #10563
  • Stop continuing an OpenAI response with openai_previous_response_id once the history before it has changed by @DouweM in #10509
  • Stop harness sub-agents from returning DeferredToolRequests to a parent that cannot resolve them by @DouweM in #10497
  • Stop continuing an OpenAI response with openai_previous_response_id once the response itself has changed by @DouweM in #10656
  • Raise RealtimeError instead of a raw websockets exception when a GPT-Live connection drops without a reconnect policy by @DouweM in #10645
  • Ignore deeply nested ReasoningMessage.encrypted_value JSON in AGUIAdapter.load_messages by @DouweM in #10650
  • Write format_as_xml mapping keys that aren't valid XML names to a key attribute by @DouweM in #10651
  • Fix UseEnumMemberDocstrings enums, Choices and BoolCriteria failing in Anthropic strict schemas by @DouweM in #10659
  • Rewrite nested $refs when merging JSON schema definitions by @limadog9 in #10601

New Contributors

Full Changelog: v2.57.0...v2.58.0

Don't miss a new pydantic-ai release

NewReleases is sending notifications on new releases.