Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agent-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1756,7 +1756,7 @@
"additionalProperties": true
}
},
"description": "Provider-specific options. Anthropic: thinking_prefix_mismatch (error or drop_block; defaults to drop_block on Claude models whose server checks thinking prefixes: Haiku 5.5, Opus 5.5, Sonnet 5.5 and Fable 5.1, plus Fable 5.2+ by name), strict_tools (true for eligible schemas or a tool-name array requiring strict mode), cache_diagnostics (boolean; Claude API only), native_compaction (boolean; synchronous whole-history signed compaction on Claude API), cache_preserving_updates (boolean; native system/tool/effort changes with turn-scoped reminders on supported models), thinking_display: updates (progress updates beta on Fable 5+ and Mythos 5.1). Sampling parameters: top_k (integer, supported by anthropic, google, amazon-bedrock, and custom OpenAI-compatible providers like vLLM/Ollama), repetition_penalty (float, forwarded to custom OpenAI-compatible providers), min_p (float, forwarded to custom providers), seed (integer, forwarded to OpenAI). Lifecycle: unload_api (string) overrides the unload endpoint inherited from the provider config (relative path resolved against base_url's scheme+host, or an absolute URL); used by the runtime's `unload` on_agent_switch builtin hook to release model resources between agent switches. Infrastructure options: http_headers (map of string to string, adds custom HTTP headers to every request; used for OpenAI-compatible providers like github-copilot which requires Copilot-Integration-Id). dmr: runtime_flags; supports_images (boolean) and supports_pdf (boolean) declare which document attachment types the local model accepts. DMR-hosted models are not in the models.dev catalog, so attachment capabilities cannot be detected automatically and default to text-only; set supports_images: true for a vision model so image attachments are forwarded instead of silently dropped. anthropic/amazon-bedrock (Claude): interleaved_thinking (boolean, default true). anthropic: thinking_display ('summarized', 'omitted', 'updates', or 'display') controls whether thinking blocks are returned in responses when thinking is enabled. Claude Opus 4.7 hides thinking by default ('omitted'); set thinking_display: summarized to receive thinking blocks. 'display' (full thinking blocks) is only accepted by pre-4.6 token-thinking models (e.g. Sonnet 4.5, Haiku 4.5); models from the adaptive-thinking generation onward (Opus/Sonnet 4.6+, Sonnet 5, Fable 5) reject it, and docker-agent fails fast with a configuration error (fallbacks models are validated too); fallbacks (\"default\" for the server's recommended routing, or an array of up to three distinct model ID strings in priority order; enables the server-side-fallback-2026-07-01 beta so refused requests are retried in a single round trip; Claude API only, rejected on Vertex AI, Bedrock, gateways and other base_url hosts; a list is rejected for Claude Haiku 5.5; rejected when the primary or any fallback is a Claude 5.x model until issue #4584). OpenAI-compatible APIs: service_tier (string, forwarded unchanged to Chat Completions and Responses, including WebSocket and reranking; 'fast' or 'priority' enables Fast mode at premium pricing on supported models; omitted or empty leaves the API default, non-string values are ignored). openai/chatgpt: preserve_reasoning (boolean, default false) preserves ordered Responses output and encrypted reasoning for stateless continuation; native_tool_search also enables output replay. Any OpenAI-compatible destination: replay_reasoning (boolean) replays the reasoning stored on assistant turns back as a reasoning_content field on later Chat Completions requests, so a reasoning model sees its own earlier reasoning instead of re-deriving it after each tool call (distinct from preserve_reasoning, which replays encrypted reasoning items on the Responses API and does not apply to Chat Completions); default true for Chat Completions; set replay_reasoning to false for an endpoint that rejects or must not receive the non-standard field; a non-boolean value also disables replay. openai: cache_diagnostics (boolean, default false) logs Responses prompt-cache comparison results with --debug on GPT-5.6+; comparisons are scoped to the current session and resolved model; ignored for chatgpt and custom base_url endpoints. transport ('sse' or 'websocket') to choose between SSE and WebSocket streaming for the Responses API; native_tool_search (boolean, default false; also enables ordered output replay) declares the agent's deferred tools with defer_loading and a server-executed tool_search tool so OpenAI's hosted tool search discovers them (only openai models supporting deferred tools, gpt-5.4+; ignored on chatgpt, OpenAI-compatible endpoints including a custom base_url, and Chat Completions requests). openai/anthropic/google: rerank_prompt (string) to fully override the system prompt used for RAG reranking (advanced - prefer using results.reranking.criteria for domain-specific guidance). Google: google_search (boolean) enables Google Search grounding, google_maps (boolean) enables Google Maps grounding, code_execution (boolean) enables server-side code execution, url_context (boolean) enables reading public URLs during generation, output_dimensionality (positive integer) truncates Gemini embedding vectors to that size when the model is used as a RAG embedding_model; service_tier (string, forwarded unchanged as the top-level serviceTier of every generateContent request, including reranking, title generation, and compaction, on the Gemini API, Vertex AI, and the Docker models gateway; 'flex' for discounted, queued processing that may wait up to 15 minutes before the first byte, 'standard' for the default tier, 'priority' for premium processing; omitted or empty leaves the API default, non-string values are ignored; cost estimates are not tier-adjusted, set the model's cost override).",
"description": "Provider-specific options. Anthropic: thinking_prefix_mismatch (error or drop_block; defaults to drop_block on Claude models whose server checks thinking prefixes: Haiku 5.5, Opus 5.5, Sonnet 5.5 and Fable 5.1, plus Fable 5.2+ by name), strict_tools (true for eligible schemas or a tool-name array requiring strict mode), cache_diagnostics (boolean; Claude API only), native_compaction (boolean; synchronous whole-history signed compaction on Claude API), cache_preserving_updates (boolean; native system/tool/effort changes with turn-scoped reminders on supported models), thinking_display: updates (progress updates beta on Fable 5+ and Mythos 5.1). Sampling parameters: top_k (integer, supported by anthropic, google, amazon-bedrock, and custom OpenAI-compatible providers like vLLM/Ollama), repetition_penalty (float, forwarded to custom OpenAI-compatible providers), min_p (float, forwarded to custom providers), seed (integer, forwarded to OpenAI). Lifecycle: unload_api (string) overrides the unload endpoint inherited from the provider config (relative path resolved against base_url's scheme+host, or an absolute URL); used by the runtime's `unload` on_agent_switch builtin hook to release model resources between agent switches. Infrastructure options: http_headers (map of string to string, adds custom HTTP headers to every request; used for OpenAI-compatible providers like github-copilot which requires Copilot-Integration-Id). dmr: runtime_flags; supports_images (boolean) and supports_pdf (boolean) declare which document attachment types the local model accepts. DMR-hosted models are not in the models.dev catalog, so attachment capabilities cannot be detected automatically and default to text-only; set supports_images: true for a vision model so image attachments are forwarded instead of silently dropped. anthropic/amazon-bedrock (Claude): interleaved_thinking (boolean, default true). anthropic: thinking_display ('summarized', 'omitted', 'updates', or 'display') controls whether thinking blocks are returned in responses when thinking is enabled. Claude Opus 4.7 hides thinking by default ('omitted'); set thinking_display: summarized to receive thinking blocks. 'display' (full thinking blocks) is only accepted by pre-4.6 token-thinking models (e.g. Sonnet 4.5, Haiku 4.5); models from the adaptive-thinking generation onward (Opus/Sonnet 4.6+, Sonnet 5, Fable 5) reject it, and docker-agent fails fast with a configuration error (fallbacks models are validated too); fallbacks (\"default\" for the server's recommended routing, or an array of up to three distinct model ID strings in priority order; enables the server-side-fallback-2026-07-01 beta so refused requests are retried in a single round trip; Claude API only, rejected on Vertex AI, Bedrock, gateways and other base_url hosts; a list is rejected for Claude Haiku 5.5, which has no server-side fallback). OpenAI-compatible APIs: service_tier (string, forwarded unchanged to Chat Completions and Responses, including WebSocket and reranking; 'fast' or 'priority' enables Fast mode at premium pricing on supported models; omitted or empty leaves the API default, non-string values are ignored). openai/chatgpt: preserve_reasoning (boolean, default false) preserves ordered Responses output and encrypted reasoning for stateless continuation; native_tool_search also enables output replay. Any OpenAI-compatible destination: replay_reasoning (boolean) replays the reasoning stored on assistant turns back as a reasoning_content field on later Chat Completions requests, so a reasoning model sees its own earlier reasoning instead of re-deriving it after each tool call (distinct from preserve_reasoning, which replays encrypted reasoning items on the Responses API and does not apply to Chat Completions); default true for Chat Completions; set replay_reasoning to false for an endpoint that rejects or must not receive the non-standard field; a non-boolean value also disables replay. openai: cache_diagnostics (boolean, default false) logs Responses prompt-cache comparison results with --debug on GPT-5.6+; comparisons are scoped to the current session and resolved model; ignored for chatgpt and custom base_url endpoints. transport ('sse' or 'websocket') to choose between SSE and WebSocket streaming for the Responses API; native_tool_search (boolean, default false; also enables ordered output replay) declares the agent's deferred tools with defer_loading and a server-executed tool_search tool so OpenAI's hosted tool search discovers them (only openai models supporting deferred tools, gpt-5.4+; ignored on chatgpt, OpenAI-compatible endpoints including a custom base_url, and Chat Completions requests). openai/anthropic/google: rerank_prompt (string) to fully override the system prompt used for RAG reranking (advanced - prefer using results.reranking.criteria for domain-specific guidance). Google: google_search (boolean) enables Google Search grounding, google_maps (boolean) enables Google Maps grounding, code_execution (boolean) enables server-side code execution, url_context (boolean) enables reading public URLs during generation, output_dimensionality (positive integer) truncates Gemini embedding vectors to that size when the model is used as a RAG embedding_model; service_tier (string, forwarded unchanged as the top-level serviceTier of every generateContent request, including reranking, title generation, and compaction, on the Gemini API, Vertex AI, and the Docker models gateway; 'flex' for discounted, queued processing that may wait up to 15 minutes before the first byte, 'standard' for the default tier, 'priority' for premium processing; omitted or empty leaves the API default, non-string values are ignored; cost estimates are not tier-adjusted, set the model's cost override).",
"additionalProperties": true
},
"track_usage": {
Expand Down
36 changes: 22 additions & 14 deletions docs/providers/anthropic/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,10 @@ make two endpoints interchangeable.
| Bedrock runtime | `amazon-bedrock`; **`ConverseStream`** | Regional Bedrock runtime endpoint | AWS SigV4 credentials or Bedrock bearer token | Exact AWS model or inference-profile ID |
| OpenAI-compatible aggregators | OpenAI client, Chat Completions for Claude | Alias/custom endpoint (e.g. OpenRouter, Vercel, Azure, OpenCode) | Host-specific key | Host's catalogue ID, not necessarily a Claude API ID |

These are existing adapter paths, not a guarantee of complete Claude 5.x
compatibility. Model-specific request rules, signed history, thinking and fallback
compatibility remain the subject of the planned [core work (#4583)](https://github.com/docker/docker-agent/issues/4583)
and [fallback work (#4584)](https://github.com/docker/docker-agent/issues/4584).
This guide does not mark those changes as implemented.
These are the adapter paths Docker Agent uses. Claude 5.x request rules, signed
history and thinking ([#4583](https://github.com/docker/docker-agent/issues/4583))
and server-side fallback ([#4584](https://github.com/docker/docker-agent/issues/4584))
are described in the sections below.

- The built-in `opencode` alias is OpenAI-compatible; the
[custom OpenCode Messages provider](../opencode-zen/index.md#anthropic-compatible-messages-api)
Expand Down Expand Up @@ -262,7 +261,7 @@ Docker Agent recognizes nine Claude 5.x models by ID: `claude-haiku-5-5`, `claud
- An integer token budget becomes adaptive thinking with the model's default effort; `max_tokens` is not raised.
- `temperature`, `top_p` and `top_k` are never sent.
- `thinking_budget: none` (or `0`) sends `thinking: disabled` on Haiku 5.5, Opus 5 and Sonnet 5. The other six cannot disable thinking: they get adaptive thinking with `low` effort, and Docker Agent logs a warning at startup.
- Server-side `fallbacks` involving any of these models are rejected at startup until [#4584](https://github.com/docker/docker-agent/issues/4584).
- Server-side `fallbacks` work with these models on the Claude API, except Haiku 5.5, which has none (see [Server-Side Fallbacks](#server-side-fallbacks)).
- A request that ends on an assistant message (a response prefill) is rejected before it is sent. Tool-mode structured output therefore fails after the first plain-text answer instead of retrying with a reminder.

Other Claude IDs keep the existing name-based rules.
Expand Down Expand Up @@ -369,10 +368,12 @@ Or list up to three distinct models, tried in order:
- claude-sonnet-4-6
```

> [!WARNING]
> **Not yet available with Claude 5.x**
>
> A fallback can change the serving model mid-response, which Docker Agent does not handle yet. `fallbacks` is rejected at startup when the primary model or any listed fallback is a Claude 5.x model (Haiku 5.5, Opus 5/5.5, Sonnet 5/5.5, Fable 5/5.1, Mythos 5/5.1). Support is tracked in [#4584](https://github.com/docker/docker-agent/issues/4584).
When a model declines mid-response, the turn continues on the fallback model.
Docker Agent never runs a tool call the declining model made, stores the turn
under the model that served it, and replays it on the next request as the API
requires. The turn's cost adds up each attempt at its own model's rates; a
declined attempt that produced no output is billed only in the refusal
categories Anthropic bills.

Docker Agent sends the `server-side-fallback-2026-07-01` beta header, which
accepts both forms, through the beta Messages API. The response's `model`
Expand All @@ -386,15 +387,22 @@ Rules checked at startup:
Vertex AI, Bedrock, a gateway, or a base URL (`base_url` or
`ANTHROPIC_BASE_URL`) whose host isn't `api.anthropic.com`. It isn't
available on the Message Batches API either.
- Claude Haiku 5.5 has no server-side fallback. Once Claude 5.x chains are
supported, a list will be rejected and `default` will only log that it has
no effect.
- Claude Haiku 5.5 has no server-side fallback: a list is rejected, and
`default` only logs that it has no effect.
- The request must be valid for every listed model, or the API rejects it up
front. A configuration is rejected when a listed fallback (such as a Claude
5.x model) refuses what the request sends: `temperature` or `top_p` (sent
only with thinking off), `top_k`, or token-budget thinking, including an
effort level that an older model without adaptive thinking turns into a
token budget.

Fallback models receive the exact same request as the primary model
(thinking configuration, task budget, beta features, ...), so list only
models that accept the same request shape. With `default` the server picks
the fallback, so per-model options such as `thinking_display` are checked
against the primary model only.
against the primary model only. The API makes one exception itself: when a Claude
Sonnet 5.5 request with `between_tools` thinking falls back to Claude Sonnet 5,
that attempt runs with thinking disabled ([fallback list rules](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#naming-your-own-fallback-models)).

See [Refusals and fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#server-side-fallback).

Expand Down
3 changes: 0 additions & 3 deletions examples/anthropic-fallbacks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
# model in a single round trip. `fallbacks: default` uses the model Anthropic
# recommends for the refusal's category; a list (up to three) is tried in
# order.
#
# Fallback chains that include a Claude 5.x model are rejected until
# https://github.com/docker/docker-agent/issues/4584 lands.
models:
opus:
provider: anthropic
Expand Down
22 changes: 22 additions & 0 deletions pkg/chat/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ type MessageStreamResponse struct {
Model string `json:"model"`
Choices []MessageStreamChoice `json:"choices"`
Usage *Usage `json:"usage,omitempty"`
// UsageAttempts lists each model that ran when a server fallback spread
// the response across models; Usage describes only the last one.
UsageAttempts []UsageAttempt `json:"usage_attempts,omitempty"`
}

type Usage struct {
Expand All @@ -237,6 +240,25 @@ type Usage struct {
ServiceTier string `json:"service_tier,omitempty"`
}

// UsageAttempt is one attempt of a response a server fallback spread across
// models, billed at that model's rates unless Billed is false.
type UsageAttempt struct {
Model string `json:"model"`
Billed bool `json:"billed"`
// Dispatched marks the attempt of the requested model, whose reported ID
// may be a resolved form of the configured one.
Dispatched bool `json:"dispatched,omitempty"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CachedInputTokens int64 `json:"cached_input_tokens"`
CacheWriteTokens int64 `json:"cached_write_tokens"`
}

// Usage returns the attempt's token counts as a Usage.
func (a UsageAttempt) Usage() *Usage {
return &Usage{InputTokens: a.InputTokens, OutputTokens: a.OutputTokens, CachedInputTokens: a.CachedInputTokens, CacheWriteTokens: a.CacheWriteTokens}
}

// PromptTokens sums the disjoint fresh, cache-read, and cache-write input buckets.
func (u *Usage) PromptTokens() int64 {
return u.InputTokens + u.CachedInputTokens + u.CacheWriteTokens
Expand Down
Loading
Loading