Opus 4.8 on Vertex (CLAUDE_CODE_USE_VERTEX) returns empty thinking — display:"summarized" honored on direct but dropped on Vertex
Summary
When the Agent SDK runs Claude Opus 4.8 through the Vertex AI backend (CLAUDE_CODE_USE_VERTEX=1), requesting thinking: { type: "adaptive", display: "summarized" } produces an empty thinking block — content_block_start (type thinking) immediately followed by content_block_stop, with zero thinking_delta events and a signature_delta only. Text deltas stream normally.
The identical request on the direct Anthropic API (ANTHROPIC_API_KEY, same SDK, same model, same flags) streams thinking_delta summary text correctly.
So display: "summarized" appears to be honored on the direct path but dropped / defaulted to "omitted" on the Vertex path for Opus 4.8.
Environment
@anthropic-ai/claude-agent-sdk0.3.177@anthropic-ai/claude-code2.1.177- Model:
claude-opus-4-8 - Backends compared: direct Anthropic API vs. Google Vertex AI (
CLAUDE_CODE_USE_VERTEX=1,ANTHROPIC_VERTEX_PROJECT_ID,CLOUD_ML_REGION=global, WIF/ADC creds),anthropic_version: vertex-2023-10-16 - Invoked via
claudeSdk.query({ thinking: { type: "adaptive", display: "summarized" }, includePartialMessages: true, ... })(stream-json mode)
What the SDK forwards (confirmed correct)
The Agent SDK builds the CLI args correctly for { type: "adaptive", display: "summarized" }:
--thinking adaptive --thinking-display summarized
(verified in sdk.mjs: if (u.type !== "disabled" && u.display) V.push("--thinking-display", u.display))
So the JS layer hands --thinking-display summarized to the CLI on both backends. The divergence happens inside the CLI's backend request construction — the Vertex path does not surface summarized thinking deltas, while the direct path does.
Repro (streamed events)
Same SDK config, only the backend differs.
Direct (ANTHROPIC_API_KEY), Opus 4.8, a prompt that requires multi-step reasoning:
reasoning-start→ manythinking_delta→reasoning-end→ text deltas → reasoning summary is visible. ✅
Vertex (CLAUDE_CODE_USE_VERTEX=1), Opus 4.8, same prompt/config:
reasoning-start→ 0thinking_delta(only asignature_delta) →reasoning-end→ text deltas. Thinking block is empty. ❌
Observed frame counts on the Vertex turn (from our bridge's on-disk event log):
reasoning-start: 1
reasoning-delta: 0 <-- empty thinking, no summary text
reasoning-end: 1
text-delta: 412 <-- final answer streams fine
Expected
display: "summarized" should stream summarized thinking_delta text on the Vertex backend the same way it does on the direct backend (extended/adaptive thinking + streaming are documented as GA on Vertex).
Notes / related
- This is the
display: "omitted"signature (emptythinking,signature_deltaonly) — but we explicitly request"summarized", and the direct path honors it. So the override isn't taking effect on the Vertex path specifically. - Related (same default-omitted mechanism, but direct/IDE scope, not Vertex): #49268.
- Possible angles we couldn't confirm from outside the CLI binary: Vertex's pinned
anthropic_version(vertex-2023-10-16) predating summarized-thinking display; a Vertex request transformer dropping thedisplayfield; or a beta-header that's attached on direct but not on the Vertex path. An effective thinking-token budget collapsing to ~0 on Vertex would produce the same empty-block signature — happy to provide more instrumentation if useful.
Impact
Any harness that surfaces a reasoning/activity timeline from thinking_delta shows an empty reasoning panel for Opus 4.8 on Vertex, while the same code shows reasoning correctly on the direct backend.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗