v2.52.0

stackblitz-labs/bolt.diyv2.52.0Sep 30, 2026by dsfaccini

Upgrading?

AI Summary

Introduces workspaces for file and command execution, ships the new `pydantic-clai2` CLI tool, and adds a suite of built-in plugins while fixing a security vulnerability in web fetching.

Key Highlights

  • Workspaces (Sandbox, E2B, Sprite) for execution
  • New `pydantic-clai2` CLI tool
  • Security fix for web_fetch (GHSA-v36g-jcw9-x7cw)
  • Built-in plugins (Github, Slack, Notion, Linear, etc.)

Breaking Changes

  • SubAgents loading agent files by default stopped
  • ModalSandbox tools replaced with Modal workspace

New Features

  • Workspaces (E2BSandbox, SpritesSandbox)
  • pydantic-clai2 CLI
  • Built-in plugins (Github, Slack, Notion, Linear)
  • Claude Sonnet 5.5 support
  • SSHWorkspace and BubblewrapSandbox

Full Release Notes

### 🛡️ Security

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

- **[GHSA-v36g-jcw9-x7cw](https://github.com/pydantic/pydantic-ai/security/advisories/GHSA-v36g-jcw9-x7cw)** (moderate): converting attacker-controlled HTML with deeply nested elements in the local `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).

### 📦 Harness and CLAI 2

`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`.

## What's Changed
### ⚠️ Compatibility Notes
* Run harness capabilities in any workspace: `Coder`, `FileSystem`, `Shell` and the rest work through `ctx.workspace`, locally or in a sandbox by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/8866
* Replace `ModalSandbox`'s own tools with a Modal workspace, so `Coder`, `Shell` and `FileSystem` run in the sandbox; `ModalSandboxBackend` replaces `ModalSandboxSession` by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/8867
* Raise `AnthropicModel`'s default `max_tokens` from 4096 to 16384 on Claude Sonnet 4.5 and later by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9025
* Keep the prompt as a `DecisionModel`'s judged `text` after a retry by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/8967
* Stop `SubAgents` loading agent files by default, and deprecate `inherit_tools` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9023
* Default `AnthropicModel`'s `max_tokens` to the model's maximum output, streaming such requests behind the scenes by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9298
### 🚀 Features
* Add workspaces: `ctx.workspace` gives tools one API for files and commands, on your machine or in a sandbox, with durable execution support by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/6492
* Add `SpritesSandbox`: a workspace that runs `Coder`, `Shell`, `FileSystem` and every other harness capability in a Fly.io Sprite by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/8869
* Add `E2BSandbox`: a workspace that runs `Coder`, `Shell`, `FileSystem` and every other harness capability in an E2B sandbox by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/8868
* Give `Coder` file tools a retry budget of 5 and keep scratch files out of the project by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8970
* Add a `typesafe` extra to `pydantic-clai2` and reject models with a missing provider SDK at `/model` time by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8962
* Add Claude Sonnet 5.5 (`claude-sonnet-5-5`) support by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/8974
* Model realtime async tool calls as a profile `async_tool_call_mode` with a shared `async_tool_calls` setting by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8813
* Show tool-call arguments in `pydantic-clai2` tool headers, clipped by `display.tool_arg_chars` by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9100
* Open a `clai2` plugin's settings menu when it is turned on, and end every settings menu with Save & close by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9102
* Add `_process_provider_details` hook to `OpenAIResponsesModel` by [@pydanty](https://github.com/apps/pydanty) in https://github.com/pydantic/pydantic-ai/pull/9094
* Add `clai2 --agent MODULE:ATTR` to chat with an existing `Agent` with plugins off by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9291
* Add a built-in `github` plugin to `clai2` with a settings menu and its token in `/keys` by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8904
* Add a built-in `pylon` plugin to CLAI2 with a settings menu and a named `/keys` entry by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8953
* Seed retained user audio on Gemini `gemini-3.1-flash-live-preview` and `gemini-3.8-live` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9047
* Support browser WebRTC on OpenAI GPT-Live with `answer_webrtc_offer` and a sideband session by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9059
* Add `SSHWorkspace` and `BubblewrapSandbox` harness capabilities by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8956
* Add a `pydantic-clai2` console script so `uvx pydantic-clai2` runs CLAI by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9304
* Add `azure_voice_live_voice` to choose an Azure voice for Azure AI Voice Live sessions by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9044
* Add `google_workspace` as a built-in `clai2` plugin backed by harness `GoogleWorkspace` by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8907
* Apply `thinking`, `openai_turn_detection`, `openai_input_noise_reduction` and a new `azure_voice_live_temperature` on Azure AI Voice Live by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9051
* Seed tool calls and results as native function parts on Gemini `gemini-3.8-live` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9058
* Emit identified response, turn, and input lifecycle events from the OpenAI-protocol realtime connection by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9064
* Add a built-in `day_ai` plugin to `clai2` with a settings menu and `/keys` or browser sign-in by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8940
* Warn on unexpected `RequestUsage.extract()` failures by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/8564
* Add a built-in `ordinal` plugin to `clai2` with token or keyring-backed browser sign-in by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8941
* feat(profiles): `default_cache_retention` + `prompt_cache_outlook()` cold-window helper; rename `resolve_prompt_cache_retention()` to `resolve_cache_retention()` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/6337
* Add a built-in `notion` plugin to `clai2` with a settings menu and its key in `/keys` by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8944
* Deliver images and text files returned from tools on Gemini 3.x Live by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9065
* Map the shared `thinking` and `parallel_tool_calls` settings to the GPT-Live backend model by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9040
* Accept `mxfp4`, `nvfp4`, and `mxfp8` OpenRouter `quantizations` and the `exacto` `sort` value by @harimaruthachalam in https://github.com/pydantic/pydantic-ai/pull/8888
* Add a built-in `slack` plugin to `pydantic-clai2` with a settings menu, `/keys` user token, or browser sign-in by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8908
* Add a `logfire_mcp` built-in plugin to `clai2` with `/keys`, `LOGFIRE_API_KEY`, and keyring-backed OAuth by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/8903
* Add OpenAI `gpt-6.1-sol` model support and allow image output on `gpt-6-astra` by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/9305
### 🐛 Bug Fixes
* Record realtime user turns in speaking order under push-to-talk, barge-in, and with input transcription off by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8764
* Stop tool docstring parsing from changing the root logger level by @adtyavrdhn in https://github.com/pydantic/pydantic-ai/pull/8872
* Treat `application/toml` as text-like for inline model inputs by @JoeyTan21 in https://github.com/pydantic/pydantic-ai/pull/8848
* Ask for one answer per batch of parallel realtime tool results, and stop `wait_for_reply()` hanging on merged or failed replies by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8765
* Move tool-forcing and thinking-default profile flags to `ModelProfile` so they apply on every provider route by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8808
* Stop Gemini Live tool rounds reporting `RealtimeTurnCompleteEvent` before the spoken answer by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8766
* Don't force output tools on Anthropic requests that think, so Claude keeps thinking with a structured `output_type` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8812
* Truncate the provider's copy of a realtime reply the user cut off after it finished generating by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8757
* Leave room for the extended thinking budget in Anthropic's default `max_tokens` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8986
* Settle Gemini tool calls and 2.5 typed turns a resumed realtime session lost, and stop OpenAI-protocol reconnects re-requesting a failed `response.create` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8763
* Keep a realtime microphone task alive across a reconnect by dropping audio sent while the link is re-dialed by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8806
* Raise `UserError` instead of `ModelRetry` for `Macroscope` setup failures by @DouweM in https://github.com/pydantic/pydantic-ai/pull/8999
* Give the first stage of a Playwright operation its full configured budget by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9029
* Make workspace concurrency deadlines robust under load by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9043
* Report OpenAI native web searches in `RequestUsage.details` and price them in `cost` by @dltsum in https://github.com/pydantic/pydantic-ai/pull/8310
* Stop blank lines and "settings unchanged" notices after closing `clai2` menus by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9101
* Terminate `!command` shell descendants on cancellation in `clai2` by @dafyy321-pixel in https://github.com/pydantic/pydantic-ai/pull/9092
* Quiet missing plugin modules and `UserWarning`s in `clai2`, and group `CodeMode` missing-return-schema warnings by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9099
* Handle Ctrl-C during `clai2` shell process startup by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9104
* Apply model concurrency limits to `compact_messages()` by @yang0228 in https://github.com/pydantic/pydantic-ai/pull/8241
* Keep Up/Down on prompt history when `clai2` recalls a slash command by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9297
* Allow `azure_voice_live=True` for `gpt-realtime-2` models on `AzureRealtimeModel` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9050
* Bound the Gemini Live handshake with `handshake_timeout` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9042
* Allow text output on Vertex `gemini-live-2.5-flash` and remove a stale Gemini Live docs claim by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9069
* Emit `DeferredToolRequestsEvent` in realtime sessions before the `HandleDeferredToolCalls` handler runs by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9057
* Map OpenAI response JSON decode errors to `ModelAPIError` by [@pydanty](https://github.com/apps/pydanty) in https://github.com/pydantic/pydantic-ai/pull/8846
* Map in-stream error objects to `ModelAPIError` in `OpenAIChatModel`, `GroqModel` and `HuggingFaceModel` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9313
* Raise `ModelAPIError` instead of `ValidationError` when an `OpenRouterModel` stream drops mid-response by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9312
* Read the `capabilities` docs topic from `capabilities/overview.md` in `PydanticAIDocs` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9011
* Apply `FileSystem` default `read_only_patterns` to nested `.env` and `.git/` paths by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9021
* Restore `CodeMode` discovery announcements after compaction or history loss by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9045
* Keep the original request in the `TrajectoryJudge` window when the transcript is clamped by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9012
* Raise `ContentFilterError` for a thinking-only response refused by the content filter, instead of retrying by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9355
* Sandbox file methods and block sockets without network in `BubblewrapSandbox` by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9349
* Give the current time to the hour in `LogfireMCP` instructions so they stop busting the prompt cache by @mpfaffenberger in https://github.com/pydantic/pydantic-ai/pull/9319
* Raise `ModelAPIError` when the OpenAI Responses API reports a failed response or an `error` stream event by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9321
* Map every `MistralError` from the Mistral SDK to `ModelHTTPError` or `ModelAPIError` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9307
* Map provider errors from `GoogleModel.count_tokens` and `XaiModel` file uploads by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9308
* Fix capability audit findings in `ClampOversizedMessages`, `SubAgents`, and `StepPersistence` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9026
* Root union output member `data` validation errors under `result.data` so retry feedback keeps the failing input by [@pydanty](https://github.com/apps/pydanty) in https://github.com/pydantic/pydantic-ai/pull/8669
* Read a `shell` job log deleted mid-read as empty instead of failing the call by @dsfaccini in https://github.com/pydantic/pydantic-ai/pull/9322
* Record Gemini Live `turn_complete_reason` as the realtime response's `finish_reason` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9390
* Remove the default ACP `request_limit` by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9380
* Report a realtime session's own usage on its span, not a carried total by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9389
* Count separately budgeted `SubAgent` usage toward parent budgets by @DouweM in https://github.com/pydantic/pydantic-ai/pull/9374
### 📦 Dependencies
* Bump the python-packages group across 1 directory with 14 updates by @dependabot[bot] in https://github.com/pydantic/pydantic-ai/pull/9076

## New Contributors
* @JoeyTan21 made their first contribution in https://github.com/pydantic/pydantic-ai/pull/8848
* @dltsum made their first contribution in https://github.com/pydantic/pydantic-ai/pull/8310
* @Jinzhengxu made their first contribution in https://github.com/pydantic/pydantic-ai/pull/8567
* @dafyy321-pixel made their first contribution in https://github.com/pydantic/pydantic-ai/pull/9092
* @yang0228 made their first contribution in https://github.com/pydantic/pydantic-ai/pull/8241
* @harimaruthachalam made their first contribution in https://github.com/pydantic/pydantic-ai/pull/8888

**Full Changelog**: https://github.com/pydantic/pydantic-ai/compare/v2.51.0...v2.52.0

Related Repositories