github pydantic/pydantic-ai v2.53.0
v2.53.0 (2026-10-01)

2 hours ago

🛡️ Security

This release fixes one security issue in ConcurrencyLimitedModel. See the advisory for full details and affected versions.

  • GHSA-6fqq-452j-qhrp (high): a streamed request through 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.

What's Changed

⚠️ Compatibility Notes

  • Add oneOf schema support to TestModel's generated data by @pydanty in #8783
  • Make clai2 plugins declarative Plugin subclasses, modeled on AbstractCapability by @mpfaffenberger in #9493

🚀 Features

  • Add a built-in posthog plugin to pydantic-clai2 with /keys or browser sign-in by @mpfaffenberger in #8901
  • Add a built-in grain plugin to clai2 with a keyring-backed Grain sign-in by @mpfaffenberger in #8905
  • Add a built-in linear plugin to clai2 with a settings menu and /keys credentials by @mpfaffenberger in #8949
  • Count Google grounding web search queries in usage by @pydanty in #8891
  • Add AbsurdDurability to the harness as a replacement for pydantic-ai-absurd by @adtyavrdhn in #8946
  • Let CLAI2 plugins run models under their own prefix with host.model_provider by @mpfaffenberger in #9468
  • Apply theme-aware accents to the clai2 status row by @mpfaffenberger in #9473
  • Add opt-in Logfire UI telemetry and a Logfire setup menu (region, sign-in, project) to pydantic-clai2 by @mpfaffenberger in #9467
  • Add an opt-in herdr plugin for clai2 by @mpfaffenberger in #9480
  • Let AskUser defer questions to the host and time out a slow answerer by @mpfaffenberger in #9509
  • Add a Codex-only /fast command to CLAI2 by @mpfaffenberger in #9518
  • Let /login take a provider name, and let plugins add their own sign-ins by @mpfaffenberger in #9485
  • Add SystemOneModel to run decision models such as CLM and Laya over the /v1/systemone API by @mpfaffenberger in #8942
  • CLAI2: plugin logins add their models; plugin models can use a provider's /model_settings controls by @mpfaffenberger in #9558
  • Rename the CLAI logfire plugin to observability by @mpfaffenberger in #9566
  • Add ToolCallJudge to assess tool calls before execution by @DouweM in #9041
  • Add managed subagents to CLAI2, with Claude and Codex agent definitions in Harness by @mpfaffenberger in #9573
  • Add a settings menu to CLAI2's built-in observability (Logfire) plugin by @mpfaffenberger in #9306
  • CLAI2: /update with stable (PyPI) and bleeding (main) channels by @mpfaffenberger in #9576
  • Make the CLAI2 /plugins menu themed and readable, with plugin descriptions by @mpfaffenberger in #9570
  • Send images and documents from GPT-Live tool results to the delegated backend by @DouweM in #9048
  • Tag clai2 plugin settings with the features they need, and skip a plugin capability that rejects its settings at run setup by @mpfaffenberger in #9569
  • Show compact used/max context in the CLAI2 status line by @mpfaffenberger in #9583
  • Expose the message-history repair pipeline as repair_messages by @DouweM in #8370

🐛 Bug Fixes

  • Kill the process group when a LocalWorkspaceBackend.run timeout fires during process startup by @dsfaccini in #9358
  • Ask for CLAI2 keychain access once per session by encrypting credentials with one keyring-held key by @mpfaffenberger in #9465
  • Name CLAI2 worktree branches clai-NAME and reopen existing worktrees with --worktree NAME by @mpfaffenberger in #9462
  • Avoid invalid-escape warning floods during CodeMode analysis by @mpfaffenberger in #9475
  • Group clai2 resume sessions by repository identity by @mpfaffenberger in #9482
  • Create the CLAI2 plugins folder at startup by @mpfaffenberger in #9484
  • Keep the registered Memory toolset across runs so durable execution accepts it by @mpfaffenberger in #9489
  • Keep the registered Planning toolset across runs so durable execution accepts it by @mpfaffenberger in #9507
  • Keep planted files from escaping BubblewrapSandbox on the next launch by @dsfaccini in #9457
  • Render non-finite eval metrics as inf/-inf/nan by @pydanty in #8852
  • Snap gemini-3.1-flash-image thinking efforts to minimal and high on the Gemini API by @dsfaccini in #9515
  • Raise UnexpectedModelBehavior instead of running the wrong tool when function tool calls share a tool_call_id by @pydanty in #8782
  • Explain that CLAI2 needs a restart when /reload hits a stale Harness import by @mpfaffenberger in #9571
  • Build one streamed XaiModel thinking part per output, matching the non-streamed response by @DouweM in #9416
  • Leave image generation calls out of the OpenAIResponsesModel replay when openai_store=False by @DouweM in #9388
  • Build the same ModelResponse from streamed and complete OpenAIChatModel and OpenRouterModel responses by @DouweM in #9418
  • Make OpenAIResponsesModel build the same ModelResponse from a stream as from a complete response by @DouweM in #9417
  • Make xAI push-to-talk reply only when asked: commit_audio() alone no longer triggers a reply, and create_response() is always answered by @DouweM in #9070
  • Tolerate OpenAI realtime status, status_details and session values the SDK does not know yet by @DouweM in #9392
  • Stop SubAgents from forcing thinking on disk agents by @DouweM in #9384
  • Restore DynamicWorkflow reveal announcements after compaction or history loss by @DouweM in #9371
  • Preserve free-text focus in CLAI2 /compact by @mpfaffenberger in #9587
  • Make Logfire Temporal spans replay-safe by @DouweM in #7006
  • Keep the launch-directory workspace in clai2 when capability functions supply none, and expose unrestricted_filesystem in /plugins configure coder by @mpfaffenberger in #9593
  • Allow unschemable types in the derived Temporal ActivityConfig schema by @pydanty in #9577
  • Let GoogleRealtimeModel declare tools whose dict values are recursive models by @dsfaccini in #9607

📦 Dependencies

New Contributors

Full Changelog: v2.52.0...v2.53.0

Don't miss a new pydantic-ai release

NewReleases is sending notifications on new releases.