Skip to content

zidane/providers/anthropic

The Anthropic provider for the Messages API, with API keys, Claude OAuth credentials or Amazon Bedrock.

import { … } from 'zidane/providers/anthropic'src/providers/anthropic.ts

Use anthropic() when your agent talks to Claude. With no key passed, it reads ANTHROPIC_API_KEY, then the stored OAuth credentials. It sets prompt-cache breakpoints and maps thinking levels to Anthropic's effort and adaptive thinking. System notes (systemNotes on a run) go out as native role: "system" messages on the models that accept them, and as <system-reminder> text elsewhere. An effort note becomes a per-message effort setting, so changing effort mid-conversation keeps the prompt cache. The other exports are the pieces it is built from, for custom gateways and tests.

TypeScript
import { createAgent } from 'zidane'
import { anthropic } from 'zidane/providers/anthropic'

const agent = createAgent({ provider: anthropic({ defaultModel: 'claude-fable-5-1' }) })
const stats = await agent.run({ prompt: 'Summarize README.md in three bullets.' })
console.log(stats.turns)

Functions#

anthropicFunction#

Creates the Anthropic provider for the Messages API. Authenticates with an API key or Claude OAuth credentials, and can route through Amazon Bedrock via bedrock. Without apiKey, reads ANTHROPIC_API_KEY or stored OAuth credentials: a snapshot at construction, then again on every call. Outside Bedrock mode, throws at construction when no credential is found.

TypeScript
function anthropic(anthropicParams?: AnthropicParams): Provider
Parameters
NameTypeDescription
anthropicParams?AnthropicParams

API key or OAuth credentials, default model, Bedrock mode, base URL, headers and beta flags.

Example
import { createAgent } from 'zidane'
import { anthropic } from 'zidane/providers/anthropic'

const agent = createAgent({
  provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),
})
await agent.run({ prompt: 'Say hello.' })

src/providers/anthropic.ts:103

applyAnthropicCacheBreakpointsFunction#

Mutate an Anthropic request in place to add cache breakpoints on the three stable prefixes:

  1. System prompt — cache_control on the static prefix only (see below).
  2. Tool definitions — last tool.
  3. Conversation — last content block of the last message with content (an effort-only system message has none).

A fourth, lookback breakpoint goes on the message right before the latest assistant turn, whatever its role, when the request carries fewer than 4 markers (see the comment in the body).

Each breakpoint tells Anthropic to cache the prefix ending at that block; subsequent turns reuse the cached prefix and pay only for the delta. Safe no-op when any prefix is empty (no tools, empty system, etc.).

System-prompt boundary handling (SYSTEM_PROMPT_BOUNDARY):

  • When originalSystem is provided AND carries the marker, the system block is rewritten as a 2-block array: static (cached) then dynamic (uncached). The caller is expected to have already stripped the marker from params.system via renderSystemForWire — this helper only re-splits to apply cache_control cleanly.
  • When originalSystem is omitted or marker-free, the existing single- block treatment applies: cache_control on the whole system string.
  • Array system prompts: existing semantics — cache_control lands on the last block. Callers building their own multi-block layout own the breakpoint placement.
TypeScript
function applyAnthropicCacheBreakpoints(
  params: MessageCreateParamsStreaming,
  originalSystem?: string,
  ttl?: CacheTtl,
): void
Parameters
NameTypeDescription
paramsMessageCreateParamsStreaming

Streaming request to mutate.

originalSystem?string

System prompt before boundary rendering, used to split the static and dynamic parts.

ttl?CacheTtl

Cache lifetime for the breakpoints. Uses the API default when omitted.

src/providers/anthropic-cache.ts:58

buildAnthropicClientOptionsFunction#

SDK constructor options for a resolved credential — the single place that decides which auth header goes on the wire.

Exported (and pure) so the header shape is test-pinned without a network round-trip: authToken → Authorization: Bearer …, apiKey → x-api-key, and apiKey: null alongside authToken is what suppresses x-api-key so a gateway sees exactly one credential.

TypeScript
function buildAnthropicClientOptions(
  apiKey: string,
  auth: { bearer: boolean; claudeCode: boolean },
  baseURL?: string,
  extraBetas?: readonly string[],
  extraHeaders?: Record<string, string>,
): Record<string, unknown>
Parameters
NameTypeDescription
apiKeystring

Resolved API key or bearer token.

auth{ bearer: boolean; claudeCode: boolean }

Wire auth shape from resolveAnthropicAuthShape.

baseURL?string

Optional SDK base URL override.

extraBetas?readonly string[]

Extra anthropic-beta flags.

extraHeaders?Record<string, string>

Extra request headers. Reserved header names are dropped.

Record<string, unknown>

src/providers/anthropic-client.ts:282

cacheWriteTtlMultiplierFunction#

Returns the factor to apply to the cache write cost of a turn that wrote under the 1h TTL, or 1 when no 1h writes are reported.

TypeScript
function cacheWriteTtlMultiplier(
  usage: { cache_creation?: { ephemeral_1h_input_tokens?: number; ephemeral_5m_input_tokens?: number } | null; cache_creation_input_tokens?: number | null },
): number
Parameters
NameTypeDescription
usage{ cache_creation?: { ephemeral_1h_input_tokens?: number; ephemeral_5m_input_tokens?: number } | null; cache_creation_input_tokens?: number | null }

Usage block of the response, with the optional per-TTL cache write split.

number

src/providers/anthropic-usage.ts:56

classifyAnthropicErrorFunction#

Classify an Anthropic SDK / HTTP error for typed-error wrapping.

  • prompt is too long (400 invalid_request_error) → context_exceeded.
  • 'tool_use' ids were found without 'tool_result' blocks / 'tool_result must be preceded by a tool_call' (400) → tool_pairing_corruption. The local repair pass should have caught this — the typed error tells consumers their pre-send pipeline is shipping orphaned blocks somehow (custom context:transform hook, bypassed loop, mid-stream session edit) so they can patch the root cause instead of chasing 400s.
  • A rate limit, spent credit or overload (429, 529, billing_error, also mid-stream) → provider_error worded by describeProviderLimit, with the server's reset (see classifyProviderLimit for when it stops retrying).
  • Any other Anthropic APIError-shaped value → provider_error with the native status/type code.
  • Unknown errors → null (loop wraps in AgentProviderError generically).

Anthropic's wire error shape is { type: 'error', error: { type, message } } — the SDK stores the parsed body on err.error. We walk both levels so callers see the most specific providerCode we can find.

TypeScript
function classifyAnthropicError(err: unknown, label?: string): ClassifiedError | null
Parameters
NameTypeDefaultDescription
errunknown

Error thrown by the SDK or the HTTP layer.

label?string'Claude'

Product a limit's message names; providers built on this wire (Bolt) pass their own.

src/providers/anthropic-errors.ts:107

credentialIdentityFunction#

Credential-resolution identity for resolveOAuthApiKey. Anthropic's own unless the caller pointed the provider at a gateway with its own credentials via AnthropicParams.credentialSource.

TypeScript
function credentialIdentity(
  anthropicParams?: AnthropicParams,
): { envKey?: string; missingError: string; providerId: string; refreshError: (reason: string) => string }
Parameters
NameTypeDescription
anthropicParams?AnthropicParams

Provider params, read for credentialSource.

{ envKey?: string; missingError: string; providerId: string; refreshError: (reason: string) => string }

src/providers/anthropic-client.ts:162

defaultAnthropicMaxTokensFunction#

Conservative per-family output ceiling, used ONLY as a fallback when pi-ai's model registry doesn't know the model (or pi-ai is externalized) — see resolveAnthropicMaxOutput, which is the primary path. These are non-beta floors we can always send without a 400; the registry reports the real (often much higher, e.g. Opus 4.x = 128K native) max when available.

TypeScript
function defaultAnthropicMaxTokens(modelId: string): number
Parameters
NameTypeDescription
modelIdstring

Model id. Matched by family name (haiku, sonnet, other).

number

src/providers/anthropic-request.ts:35

planAnthropicThinkingFunction#

Decide how to translate a ThinkingLevel into Anthropic's request shape. Pure / synchronous — exported so tests can assert routing without standing up the SDK.

Routing rules:

  • 'off' → null (no thinking field, no effort hint).
  • 'adaptive' → adaptive thinking with no effort hint (model decides everything). When taskBudget is set, it is carried as taskBudgetTokens and emitted as output_config.task_budget — the native whole-task thinking cap. LEGACY: when customBudget is set, it is carried as maxTokensCap so the request builder caps max_tokens accordingly — this clamps the whole response envelope (text and tool-call JSON included), which is the wrong knob for bounding thinking now that taskBudget exists; kept only for callers who already depend on it. Prefer taskBudget.
  • Budgeted levels → adaptive thinking with an effort hint (plus taskBudgetTokens when taskBudget is set), unless customBudget is provided.
  • Any level + customBudget → explicit-budget enabled path, carrying the level's effort hint alongside the budget. The caller has opted into precise budget control and accepts the Anthropic deprecation warning that comes with it on opus 4.6+. 'adaptive' is the sole exception: it never falls back to enabled, since adaptive is the current Anthropic API surface for self-budgeted thinking. taskBudget is adaptive-only and ignored on this path.
  • effortHint: false (default true) strips the effort hint from every shape — budgeted levels plan plain adaptive and the customBudget path plans enabled with no output_config.effort — for Anthropic models that reject the effort field.
TypeScript
function planAnthropicThinking(
  level: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive',
  customBudget?: number,
  taskBudget?: number,
  effortHint?: boolean,
): AnthropicThinkingPlan | null
Parameters
NameTypeDefaultDescription
level'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'adaptive'

Thinking level.

customBudget?number

Explicit thinking token budget.

taskBudget?number

Whole-task thinking budget, for adaptive thinking.

effortHint?booleantrue

Set false to drop the effort hint.

src/providers/anthropic-thinking.ts:160

resolveAnthropicAuthShapeFunction#

Whether the wire auth is a bearer token, and whether the Claude Code persona (betas + x-app headers + system-prompt folding) applies. Only the default 'auto' mode infers both from the token shape — see AnthropicParams.authMode.

TypeScript
function resolveAnthropicAuthShape(
  apiKey: string,
  authMode: 'auto' | 'bearer' | 'api-key' | undefined,
): { bearer: boolean; claudeCode: boolean }
Parameters
NameTypeDescription
apiKeystring

Resolved credential. Tokens containing sk-ant-oat count as OAuth in auto mode.

authMode'auto' | 'bearer' | 'api-key' | undefined

Auth mode from the provider params. Defaults to auto when undefined.

{ bearer: boolean; claudeCode: boolean }

src/providers/anthropic-client.ts:194

resolveAnthropicBetasFunction#

Build the anthropic-beta header value — OAuth defaults plus caller-supplied extras, de-duped while preserving order. Returns undefined when no betas apply (non-OAuth, no extras).

TypeScript
function resolveAnthropicBetas(
  isOAuth: boolean,
  extraBetas?: readonly string[],
): string | undefined
Parameters
NameTypeDescription
isOAuthboolean

Whether the Claude Code persona applies, which adds the OAuth default betas.

extraBetas?readonly string[]

Extra beta flags to append.

string | undefined

src/providers/anthropic-client.ts:133

resolveAnthropicMaxOutputFunction#

Resolve a model's max output tokens. Prefers pi-ai's bundled registry — the authoritative source the SDK itself uses to build requests, so e.g. Opus 4.x reports its full native 128K (no extended-output beta required) — and falls back to defaultAnthropicMaxTokens only when the registry lacks the model. Used as BOTH the default (when the caller leaves maxTokens unset) and a hard clamp, since a max_tokens above the model's max would 400.

The clamp is only as good as the ceiling's provenance, so an explicit caller maxTokens can RAISE the fallback: models the registry doesn't know are mostly ids that never appear in pi-ai's anthropic registry — Bedrock ids (global.anthropic.claude-*) and non-Anthropic models served over the Anthropic wire (openai.gpt-* on Bedrock, gateway aliases). For the latter the fallback degrades to the 32000 catch-all; for the former the family match yields a deliberately conservative non-beta floor. Clamping a caller who knows the real ceiling down to either silently truncates long generations mid-write (observed as turns pinned at exactly 32000 tokens).

It can only raise, never lower: the caller's maxTokens is a cap on the VISIBLE response, already enforced as max_tokens itself, whereas this value is the model's physical ceiling. Letting it lower the ceiling would break the enabled thinking path's invariant that the budget sits ON TOP of the response cap — the budget would be shrunk to share the caller's cap, or dropped entirely once no satisfiable budget fits.

A registry-backed max always wins over the caller — above it the provider 400s. A CATALOG entry (behavior.modelCatalog / setModelCatalog) outranks even that: it's an explicit claim about a model whose registry entry may be absent, stale, or an alias for something else entirely.

TypeScript
function resolveAnthropicMaxOutput(
  modelId: string,
  explicitMaxTokens?: number,
  catalog?: ModelCatalog,
): Promise<number>
Parameters
NameTypeDescription
modelIdstring

Model id to resolve.

explicitMaxTokens?number

Caller token cap. Can raise the fallback ceiling, never lower it.

catalog?ModelCatalog

Per-run model catalog that outranks the registry.

Promise<number>

src/providers/anthropic-request.ts:97

resolveThinkingBindingFunction#

Effective AnthropicParams.thinkingBinding: the explicit param wins, then the shell's ZIDANE_THINKING_BINDING, then the chat host's setting channel (THINKING_BINDING_SETTING_ENV), then 'drop_block'. Read per request so a flip lands on the next call without rebuilding the provider (the factory is no-arg in the chat host). Unrecognized values are ignored at each level.

TypeScript
function resolveThinkingBinding(
  param: ThinkingBindingBehavior | undefined,
  env?: ProcessEnv,
): ThinkingBindingBehavior
Parameters
NameTypeDefaultDescription
paramThinkingBindingBehavior | undefined

Explicit thinkingBinding param.

env?ProcessEnvprocess.env

Environment to read the fallbacks from.

src/providers/anthropic-thinking.ts:30

Constants#

EXTENDED_CACHE_TTL_BETAConstant#

Beta flag Anthropic requires before it honors ttl: '1h' on cache_control.

TypeScript
const EXTENDED_CACHE_TTL_BETA = 'extended-cache-ttl-2025-04-11'

src/providers/anthropic-cache.ts:20

THINKING_BINDING_SETTING_ENVConstant#

Env channel the chat host writes the user's thinkingBinding SETTING to. Distinct from ZIDANE_THINKING_BINDING (the shell override) so the two never read each other back: a host recreated in-process must not mistake an earlier host's setting write for a shell value.

TypeScript
const THINKING_BINDING_SETTING_ENV = 'ZIDANE_THINKING_BINDING_SETTING'

src/providers/anthropic-thinking.ts:17

Interfaces#

AnthropicBedrockConfigInterface#

Amazon Bedrock mode for the anthropic provider.

Routes the identical Messages wire shape through @anthropic-ai/bedrock-sdk (AnthropicBedrock), which signs requests with SigV4 instead of an Anthropic API key. Credentials resolve through the standard AWS chain — AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY (+ AWS_SESSION_TOKEN) env vars, shared config, instance roles — so no ANTHROPIC_API_KEY is needed or consulted.

Model ids are Bedrock-shaped (e.g. global.anthropic.claude-haiku-4-5-20251001-v1:0); pass one as defaultModel or per run.

TypeScript
interface AnthropicBedrockConfig
AnthropicBedrockConfig properties
NameTypeDescription
region?string

AWS region for the Bedrock runtime endpoint. Resolution order: this field → AWS_REGION env → us-west-2.

sdk?(options: Record<string, unknown>) => unknown

Bring-your-own client constructor. The default lazily imports @anthropic-ai/bedrock-sdk (an optional peer dependency); override for runtimes where that default cannot work — edge workers needing a custom providerChainResolver, pre-configured credentials objects — or to inject a fake in tests without module-level mocking (Bun's mock.module leaks across test files).

Receives the resolved client options (awsRegion, plus baseURL / defaultHeaders passthrough) and must return an object exposing the Anthropic messages surface.

src/providers/anthropic-params.ts:34

AnthropicContextManagementInterface#

Server-side context-management config — the body of context_management on the Messages API. Typed loosely (Record-of-unknown) so we don't pin a specific SDK schema version: the SDK's non-beta Messages types do not include this field, but the wire format is stable behind the context-management-2025-06-27 beta.

See: https://docs.anthropic.com/en/docs/build-with-claude/context-management

TypeScript
interface AnthropicContextManagement
AnthropicContextManagement properties
NameTypeDescription
edits?Record<string, unknown>[]

Context-editing strategies the API applies server-side, such as clearing old tool results.

src/providers/anthropic-params.ts:14

AnthropicParamsInterface#

Options of the anthropic provider: Anthropic API, Claude subscription OAuth, gateway or Bedrock.

TypeScript
interface AnthropicParams extends OAuthParams
AnthropicParams properties
NameTypeDefaultDescription
access?from OAuthParamsstring

OAuth access token supplied at runtime. Used together with refresh and expires to refresh without a credentials file.

account?from OAuthParamsstring

Run on ONE stored account of the provider instead of its active one: the credential's stable id (ProviderCredential.id, see chat/credentials). Resolved to the slot holding it on every token read and refresh, so promoting another account mid-session never moves this provider to it. The provider's env key is ignored while pinned (it is the active credential's, not this account's). A missing account fails the call with pinnedAccountMissingError — never a silent fallback to another account.

apiKey?from OAuthParamsstring

Static API key or OAuth access token sent as is, bypassing credential lookup and refresh.

authMode?'auto' | 'bearer' | 'api-key'

How the resolved credential reaches the wire.

  • 'auto' (default) — bearer iff the token is an Anthropic OAuth access token (sk-ant-oat…), which also turns on the Claude Code persona (claude-code-* betas, x-app: cli, the canonical Claude Code system block). Otherwise x-api-key.
  • 'bearer' — always Authorization: Bearer <token>, WITHOUT the Claude Code persona. This is the mode for an Anthropic-Messages-compatible gateway behind AnthropicParams.baseURL that authenticates with its own bearer token (Bolt's bex_…, an internal router, …).
  • 'api-key' — always x-api-key, no persona. Forces a proxy that expects Anthropic's native header even when the token happens to look like an OAuth one.

Only 'auto' can enable the persona: an explicit mode means "this is not Anthropic's own OAuth", and sending Claude Code's betas / system block to a third-party gateway is at best noise and at worst a 400.

baseURL?string

Optional override for the Anthropic SDK base URL. Honored end-to-end — headers and routing pass through to the forwarded host. Useful for proxies (e.g. corporate gateways, internal router).

bedrock?boolean | AnthropicBedrockConfig

Run against Amazon Bedrock instead of the Anthropic API. true uses env-resolved AWS credentials and region defaults; pass an AnthropicBedrockConfig to set the region or inject a client constructor. See the config type for credential resolution and model-id shape.

Bedrock has no count_tokens endpoint (the provider's countTokens returns null and callers fall back to the heuristic) and no Claude Code persona; beta headers are not sent. Thinking degrades to the legacy explicit-budget shape — Bedrock rejects the 4.6 surface (output_config.effort, adaptive) — with per-effort budgets from BEDROCK_THINKING_BUDGETS clamped under the model's output ceiling; an explicit thinkingBudget wins. Server-side web search (nativeWebSearch) is not advertised: AWS doesn't host Anthropic's search tool, so the canonical web_search ToolDef runs client-side like on other non-Anthropic routes.

Caveats: AnthropicParams.contextManagement is DROPPED in bedrock mode — Bedrock's translation layer rejects the field, so sending it would guarantee a 400. Any extraBodyParams from the 4.6+ API surface are forwarded verbatim and will fail the same way; don't combine them with bedrock mode. baseURL is honored but must point at a genuine Bedrock endpoint (e.g. a VPC endpoint): SigV4 signs the request for that host, so a rewriting proxy breaks the signature.

capabilities?Partial<ProviderCapabilities>

Override advertised capabilities (merged over the Anthropic defaults). For gateways behind AnthropicParams.baseURL that don't implement a native affordance — e.g. { nativeWebSearch: undefined } to fall back to the client-side web_search tool when the proxy rejects Anthropic's web_search_20250305 server tool.

contextManagement?AnthropicContextManagement

Server-side context-management directive. Sent on the request body as context_management. Requires the context-management-2025-06-27 beta — add it to AnthropicParams.extraBetas.

Typed loosely so future Anthropic schema additions land without an SDK bump. A typical compaction edit:

Text
contextManagement: {
  edits: [{
    type: 'clear_tool_uses_20250919',
    trigger: { type: 'input_tokens', value: 180_000 },
    clear_at_least: { type: 'input_tokens', value: 140_000 },
    clear_tool_inputs: ['Read', 'Bash', 'Grep'],
  }],
}
credentialSource?{ envKey?: string; missingError?: string; providerId: string; refreshError?: (reason: string) => string }

Override the credential identity used to resolve (and lazily refresh) the token on every call. Defaults to Anthropic's own (providerId: 'anthropic', env ANTHROPIC_API_KEY).

Set this when AnthropicParams.baseURL points at a gateway that issues its own OAuth credentials under a different key in credentials.json. The whole shared machinery — refresh-on-expiry, cross-process lock, atomic persist, the onOAuthRefresh callback — then applies to that provider instead, with no reimplementation. Pair with authMode: 'bearer' for a bearer-token gateway.

providerId must be registered in zidane's OAuth registry (registerOAuthProvider) for refresh to resolve.

defaultModel?stringDEFAULT_MODEL_PICK.modelId

Model used when a request does not set one.

expires?from OAuthParamsnumber

Expiry of access as a Unix timestamp in milliseconds.

extraBetas?readonly string[]

Additional anthropic-beta flags to opt into. Merged with the OAuth-path defaults (the Claude Code set, CLAUDE_CODE_BETAS); duplicates are de-duped. Examples:

  • 'context-management-2025-06-27' — server-side context compaction (token-accurate; pair with AnthropicParams.contextManagement).
  • 'token-efficient-tools-2026-03-28' — terser tool_use wire format.
  • 'interleaved-thinking-2025-05-14' — think between tool calls within one turn.
  • 'redact-thinking-2026-02-12' — replace large thinking blocks with stubs server-side.
  • 'prompt-caching-scope-2026-01-05' — extended prompt-cache scope.

Honored on both the OAuth and API-key paths.

extraBodyParams?Record<string, unknown>

Generic pass-through for fields on the Messages API request body that the SDK does not yet type. Spread into the request before the typed fields, so explicit options (AnthropicParams.contextManagement and the built-in fields like model / tools / messages) win on collision.

Forward-compat escape hatch for new Anthropic betas — when a future flag ships before zidane has a dedicated typed knob, set it here without waiting on a release. Most fields will still need the matching beta in AnthropicParams.extraBetas.

extraHeaders?Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>)

Extra HTTP headers sent on every request, merged into the SDK's defaultHeaders. Honored on both the OAuth and API-key paths.

Use for routing/attribution headers a proxy or gateway in front of the baseURL consumes (e.g. a target-provider selector). On the OAuth path the Claude Code client headers (anthropic-beta, user-agent, x-app, x-stainless-*, accept and others) take precedence on collision. On other paths only anthropic-beta is reserved.

May be a function resolved per request (awaited) instead of a static map — the seam for gateways minting short-lived/signed auth tokens that a long, suspended, or replayed durable run outlives. The resolver runs on every stream() / countTokens() call, so it can return a freshly-minted token each turn (e.g. { authorization: \Bearer ${await mintWorkToken()}` }`) without rebuilding the provider.

label?string'Claude'

Product a rate-limit, quota or overload message names, for services that speak this wire (Bolt).

promptCacheKey?PromptCacheKeyOption

Prompt-cache affinity key — an opt-in routing hint carried on the request as metadata.user_id. See PromptCacheKeyOption for the shapes and ./prompt-cache-key.ts for which routes honor it.

On 1P Anthropic this is effectively a no-op: cache entries are scoped per organization/workspace and matched purely by prefix, with no client-side routing knob, and metadata.user_id's documented purpose is abuse detection. It is plumbed here for the case AnthropicParams.baseURL already serves — a proxy or AI gateway in front of the Messages API, which CAN route on a stable session key — and so a host sets one flag regardless of which provider is behind it.

The derived default is a hash, which also satisfies Anthropic's guidance that this field not carry PII.

Default: unset — no metadata is added and requests stay byte-identical.

promptCacheKeyHeader?string

Additionally send the affinity key as this HTTP header, for gateways that route on a header rather than a body field. Defers to any same-named entry in AnthropicParams.extraHeaders.

Default: unset — no header is added.

refresh?from OAuthParamsstring

OAuth refresh token supplied at runtime.

thinkingBinding?ThinkingBindingBehavior

Preserved-thinking prefix binding (thinking.block_binding). Newer models validate that nothing before a replayed thinking block — system, tools, earlier messages — changed since the block was produced; an edited prefix invalidates that block and every later one. This picks what the API does with invalid blocks:

  • 'drop_block' (default): drop them server-side, unbilled, and report each in input_transformations (surfaced via StreamCallbacks.onInputTransformations). History stays intact for a later model that can read the blocks again.
  • 'error': the API rejects the request with a 400 and that 400 PROPAGATES — the signature-scrub ladder deliberately stands down for the prefix-mismatch shape here, since the caller asked to see the failure, not to have history rewritten around it. Fail-loud for CI.
  • 'off': send nothing; the account default applies ('error' on accounts created after 2026-08-31, silent tolerance before).

Unset falls back to the ZIDANE_THINKING_BINDING env var (shell), then ZIDANE_THINKING_BINDING_SETTING (written by the chat host from the user's setting), then 'drop_block' — see resolveThinkingBinding.

Rides with the thinking-binding-controls-2026-08-01 beta, injected only on requests that enable thinking so thinking-off requests stay byte-stable. Not sent on Bedrock (its translation layer rejects unknown thinking fields).

src/providers/anthropic-params.ts:56

Types#

AnthropicThinkingPlanType#

Description of the Anthropic-side thinking configuration derived from a ThinkingLevel. null means no thinking-related field should be set on the request.

Two shapes:

  • adaptive — thinking.type='adaptive'. The model self-budgets per turn. When effort is set, also emits output_config.effort to hint at the level of reasoning the caller wants. This is the post-Claude-4.6 default for level-based control and avoids the thinking.type='enabled' deprecation warning. When maxTokensCap is set, the request builder reduces max_tokens to min(max_tokens, maxTokensCap) — adaptive thinks and replies inside one envelope, so capping the envelope soft-bounds the thinking too.
  • enabled — explicit-budget path: thinking.type='enabled' with an explicit budget_tokens. maxTokensBump is added to the request's max_tokens so the budget sits on top of the response cap. When the caller's level maps to an effort tier, effort is carried too and emitted as output_config.effort alongside the explicit budget — both fields are valid together on 4.6+ models. The only way to pin a precise token budget; Anthropic emits a deprecation warning for this shape on opus 4.6+, so we only route here when the caller explicitly sets behavior.thinkingBudget.

In both shapes Anthropic requires temperature to be 1.

TypeScript
type AnthropicThinkingPlan =
  | { budgetTokens: number; effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max'; kind: 'enabled'; maxTokensBump: number }
  | { effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max'; kind: 'adaptive'; maxTokensCap?: number; taskBudgetTokens?: number }

src/providers/anthropic-thinking.ts:120

ThinkingBindingBehaviorType#

What the API does with replayed thinking blocks whose prefix changed: drop_block, error or off. See AnthropicParams.thinkingBinding.

TypeScript
type ThinkingBindingBehavior = 'drop_block' | 'error' | 'off'

src/providers/anthropic-thinking.ts:7