Opus 4.8 on Vertex (CLAUDE_CODE_USE_VERTEX) returns empty thinking — display:"summarized" honored on direct but dropped on Vertex

Resolved 💬 2 comments Opened Jun 29, 2026 by BilalAtique Closed Jul 3, 2026

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-sdk 0.3.177
  • @anthropic-ai/claude-code 2.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 → many thinking_deltareasoning-end → text deltas → reasoning summary is visible. ✅

Vertex (CLAUDE_CODE_USE_VERTEX=1), Opus 4.8, same prompt/config:

  • reasoning-start0 thinking_delta (only a signature_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 (empty thinking, signature_delta only) — 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 the display field; 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.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗