pypi pydantic-ai 2.54.0
v2.54.0 (2026-10-02)

2 hours ago

What's Changed

⚠️ Compatibility Notes

  • Handle draft-7 list-form items in JsonSchemaTransformer, TestModel and Mistral streamed output, and make TestModel accept boolean subschemas and cap prefixItems at maxItems by @dsfaccini in #9560
  • Fix ImageGeneration under FallbackModel and dataclasses.replace, and compare Embedder by identity by @dsfaccini in #9477
  • Refuse a second durable execution engine on an agent before either binds by @DouweM in #9391
  • Make wrap_* hooks enclose complete stage lifecycles by @adtyavrdhn in #7053
  • Re-raise model errors from Temporal model activities with their original type in workflow code by @DouweM in #9580
  • End the run when a BackgroundTools tool raises an unexpected exception, as a sequential tool does by @DouweM in #9434
  • Drop the SubAgents 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 #9424

🚀 Features

  • Tint clai2 file diffs from the selected /theme palette by @mpfaffenberger in #9648
  • Make clai2 /update always install the newest build and restart into it, resuming the session by @mpfaffenberger in #9659
  • Disable RepoContext inventory by default by @DouweM in #9382
  • Give the CodeMode missing-return-schema warning its own CodeModeReturnSchemaWarning category by @DouweM in #9423
  • Add cancel_and_resume example: cancel and resume a streaming run by @DouweM in #7012
  • Reconnect dropped OpenAILiveModel sessions by forking a stored session or replaying the history by @DouweM in #9401
  • Default Pydantic AI-created HTTP clients to the OpenAI SDK's connection pool limits, and make create_async_httpx2_client() public by @DouweM in #9600
  • Use gpt-live-transcribe for OpenAI realtime's default input_transcription_model='auto' and list gpt-transcribe by @DouweM in #9402
  • Support WebSearchTool on OpenAI GPT-Live through its delegated backend by @DouweM in #9049
  • Add native to ExaSearch and YouSearch to prefer the model's native web search, and web_search_tool() for WebSearch(local=...) by @DouweM in #9386
  • Add a double-Esc conversation rewind menu to clai2 by @mpfaffenberger in #9688
  • Allow deleting unused models from the clai2 /model menu by @mpfaffenberger in #9696

🐛 Bug Fixes

  • Fail closed in the shell realpath fallback when readlink cannot read a symlink by @dsfaccini in #9613
  • Stop importing the undeclared sniffio package in pydantic-evals and pydantic-ai-harness by @pydanty in #9620
  • Fall back from ImageGenerationTool 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 #9551
  • Nest worktrees under their repository in the clai2 resume sidebar by @mpfaffenberger in #9667
  • Remove the clai2 resume-directory confirmation by @mpfaffenberger in #9682
  • Report clai2 startup plugin failures through observability by @mpfaffenberger in #9681
  • Show file diffs in compact clai2 tool output by @mpfaffenberger in #9687
  • Treat a null finish_reason on a SnowflakeModel response like an empty one by @DouweM in #9590
  • Refuse a LocalFileStore root another user owns, and log ToolOutputLimits spill and summarize fallbacks by @DouweM in #9020
  • State when the ConversationSearch default-scope warning will be removed by @DouweM in #9383
  • Warn when read_only=True removes every hosted MCP tool by @DouweM in #9387
  • Pin the request that started the current run, not the first prompt of the conversation, in the TrajectoryJudge window by @DouweM in #9425
  • Identify the search_tools tool by its tool_kind instead of its name by @DouweM in #9603
  • Find the tool search tool in CodeMode by its tool_kind, so a prefixed search tool still gets its notes by @DouweM in #9604
  • Log LLMReminder generation failures instead of silently falling back to GoalReanchor text by @DouweM in #9024
  • Include function tools run after the final result in run_stream() usage by @DouweM in #9694
  • Build the same ModelResponse from streamed and complete GoogleModel responses, and add Gemini 3 web search sources by @DouweM in #9594
  • Recover run state with RunCancelled.from_cancellation() when a DBOS workflow is cancelled by @DouweM in #9394
  • Make custom setup_logfire callbacks replay-safe and add replay_safe to LogfirePlugin by @DouweM in #9698
  • Raise ModelAPIError for undecodable 200 response bodies from Anthropic, Bedrock, Groq, Hugging Face, Google, and OpenAI embeddings and images by @DouweM in #9350
  • Keep the run state recoverable when Ctrl-C interrupts run_sync() by @DouweM in #9605
  • Clamp OpenAI realtime barge-in truncation at the profile's audio_output_sample_rate by @DouweM in #9399
  • Load a capability once when load_capability is called twice for it in one response by @DouweM in #9397
  • Keep a first-position ToolAvailabilityDeltaPart announcement out of the standing system prompt by @DouweM in #9413
  • Commit an ACP turn up to its usage limit instead of rolling it back by @DouweM in #9426
  • Preserve dependency extras in clai2 archive updates by @mpfaffenberger in #9690
  • Preserve text and reasoning part boundaries in OpenAIChatModel streams by @pydanty in #8729
  • Propagate a native cancel that lands during a command timeout's stop by @dsfaccini in #9675
  • Return the live token from PKCESignIn.token() when another clai2 session saved one without a refresh token by @dsfaccini in #9670
  • Keep BubblewrapWorkspace commands from running code on the SSH host through shell startup files or the SSHWorkspaceBackend stop script's PATH (VERIA-212) by @mpfaffenberger in #9673

Full Changelog: v2.53.0...v2.54.0

Don't miss a new pydantic-ai release

NewReleases is sending notifications on new releases.