0.6.3

A Claude API error now closes the turn as an error

A peer-and-model cohort whose headline is, again, a wrong mapping of ours. When a Claude turn ends on an API error, @silverprotocol/claude-agent-sdk now closes it exactly once, as turn.error, with its usage. Four new models are live-verified, @google/adk moves to 2.1.0, and several upstream signals get a lossless home. The wire vocabulary is untouched — AGJSON_VERSION stays 1.0.0-draft.3.

Fixed: a Claude API error folded as a successful turn

When a Claude turn ends on an API error, the Agent SDK ends it with two frames (after any api_retry notices): an assistant message carrying error (for example authentication_failed), then a result with subtype: "success" and is_error: true. Through 0.6.2 the facet closed the turn on the first frame and then closed it again on the second — turn.error followed by turn.done{outcome: success} on the same turnId — which breaks the rule that every turn closes exactly once. The reducer kept the last close, so the folded turn read as a success whose result was the error text.

We confirmed the sequence on the live wire with a deliberately invalid API key, and folded the same frames through both versions:

0.6.2   turn.error, turn.done{success}   →  folded: success, result "Failed to authenticate. API Error: 401 API key is invalid."
0.6.3   turn.error{authentication_failed, retriable: false}   →  folded: error

From 0.6.3 the assistant error frame no longer closes the turn; the result frame emits the single turn.error, and it now carries the result’s usage, so a long agentic turn that fails on its last round keeps the cost of the rounds before it. The same change removes a second double close: an assistant error followed by an error-subtype result used to emit turn.error twice. If a stream ends before its result frame, the turn still closes as turn.error at flush.

The same release also changes a second, rarer shape. A result that reports is_error: true with no assistant error frame before it was folded by 0.6.2 as a plain success; it now closes as turn.error too, with code api_error_code (or "api_error" when absent), retriable only for HTTP status 429 or 5xx.

Apart from these and the startup-failure change below, turns that do not end on an API error are byte-identical to 0.6.2.

Two consequences to check. The error close for these turns now arrives at the result frame, after ext.anthropic.result-meta, rather than at the assistant frame. And if you persist AgJSON streams: a stored 0.6.2-or-earlier stream in which one turnId has a turn.error followed by a turn.done is the two-frame case, its folded success is wrong, and the turn.error before it carries the real code. The rarer result-only case cannot be recovered from the AgJSON alone — it is a lone turn.done{success} whose result is the API error’s text.

Vercel AI SDK: denied tool calls reach their home, and one upstream shape changed

  • ai 7.0.102 emits tool-output-denied inside the step when a tool approval is denied automatically. The facet used to pass it through as a raw frame; it now becomes tool.done{outcome: "denied"}, the event the spec defines for it.
  • ai 7.0.108 changed what happens when a model violates toolChoice by calling a different tool: that tool is no longer executed, and the run ends as turn.error, now carrying its usage. The facet follows the new behaviour.

Neither path is reachable unless you use tool approvals or a forced toolChoice.

New models, live-verified

  • Claude Opus 5.5 (claude-opus-5-5, GA 2026-09-22) needs @anthropic-ai/claude-agent-sdk 0.3.280 or later. Older versions still send the id to the API, but price it, set its default effort and report its model as Opus 5. Claude Opus 5 (claude-opus-5), GA since July, had no seed until now; it is also the model Claude Code falls back to after certain refusals, so its frames can appear in sessions that never asked for it.
  • GPT-6 Sol and GPT-6 Luna (GA 2026-09-22) on both the OpenAI Agents SDK and the Vercel AI SDK. The Agents SDK has no model-specific settings for either, so both run at the API’s default reasoning effort, medium.

Thinking on Claude: set the display mode if you want summaries

With thinking.display unset, Claude Code (2.1.272 and 2.1.280 alike, on the first-party API) asks the API for between-tool narration only. No thinking summary reaches the stream: at most an empty reasoning.* block that carries only its signature, whichever model you use. That is upstream behaviour, not a facet change, but it explains an empty reasoning panel. To stream summaries, pass thinking: { type: "adaptive", display: "summarized" } to the Agent SDK. The corpus now carries a seed that does exactly that.

Signals that no longer fall on the floor

Additive — absent, every stream is byte-identical to 0.6.2 — except that a present startupFailureReason now also changes retriable, as described:

  • Claude: api_error, api_error_params (whose remedy names the fix a host should offer) and api_error_code on the API-error frame; usage_report on /usage results; startupFailureReason in ext.anthropic.result-meta, which also marks the turn non-retriable unless the reason is one upstream calls retriable, so an auto-retry loop no longer spins on a failure that cannot clear; and decisionReasonCode on permission denials.
  • Google ADK: Part.speechMetadata (new in @google/genai 2.24.0). Parts missing a field the genai types mark optional — inlineData without mimeType, code without code, a file without fileUri — now pass through verbatim instead of throwing or producing an invalid block.

@google/adk 2.1.0

The event and response types we normalize are unchanged, but the package’s dependencies grew. It adds dockerode as an optional dependency, which brings in ssh2 and cpu-features, both of which run install scripts: with pnpm’s strict build approval you will need to allow or deny them explicitly. Its @types/dockerode dependency also adds a second @types/node (18.x) to your type program, which matters only if you compile with skipLibCheck: false.

One ADK change we have not mapped yet: when a model calls a tool name that is not registered, ADK 2.1.0 now answers with a {error: "Function … is not found in the toolsDict."} function response instead of throwing, and the facet reports that tool call as outcome: "ok".

Known gap: OpenAI reasoning items

GPT-6 Sol is the first model in our OpenAI Agents SDK corpus that actually reasons on a simple prompt (the Agents SDK pins GPT-5.6 Sol to effort none and GPT-6 Astra to low, but runs Sol at the API default, medium), and it shows a limitation of @silverprotocol/openai-agents: reasoning items reach you as ext.openai.late-reasoning { itemId, encryptedContent } rather than as first-class reasoning.* blocks, because the Agents SDK announces them only after the response has closed. The encrypted content is the correct one to send back for stateless replay — OpenAI re-encrypts at each stage, and the facet carries the final blob.

Peers and security

  • @anthropic-ai/claude-agent-sdk 0.3.280, @google/adk 2.1.0 with @google/genai 2.24.0, ai 7.0.111 with @ai-sdk/openai 4.0.72, and the openai client 7.22.0 under an unchanged @openai/agents 0.18.0.
  • The @opentelemetry/core override is retired: @google/adk 2.1.0 moved to exporters that already require a patched version. The adm-zip 0.6.1 floor stays, because @google/adk 2.1.0 still asks for 0.5.x; 0.6.1 also fixes a third advisory published since 0.6.2. Neither package is a runtime dependency of any @silverprotocol package.

The compatibility tables on each npm page carry the dated evidence.