Skip to content
Merged
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 (array of model ID strings, in priority order; enables the server-side-fallback beta so refused requests are retried with the listed models in a single round trip; 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; 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).",
"additionalProperties": true
},
"track_usage": {
Expand Down
41 changes: 31 additions & 10 deletions docs/providers/anthropic/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,16 +347,23 @@ See the full schema on the [Model Configuration](../../configuration/models/inde

## Server-Side Fallbacks

When the primary model refuses a request (stop reason `refusal`), Anthropic
can retry the request with backup models in a single round trip. Set
`fallbacks` in `provider_opts` to a list of model IDs, in priority order:
When the primary model refuses a request (stop reason `refusal`), the Claude
API can retry it on a fallback model in a single round trip. Set `fallbacks`
in `provider_opts` to `default`, to use the fallback Anthropic recommends for
the refusal's category:

```yaml
models:
opus:
provider: anthropic
model: claude-opus-4-8
provider_opts:
fallbacks: default
```

Or list up to three distinct models, tried in order:

```yaml
fallbacks:
- claude-opus-4-7
- claude-sonnet-4-6
Expand All @@ -365,17 +372,31 @@ models:
> [!WARNING]
> **Not yet available with Claude 5.x**
>
> A fallback can change the serving model mid-response, which Docker Agent does not handle yet. A `fallbacks` list is rejected at startup when the primary model or any 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).
> 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).

Docker Agent automatically attaches the required
`server-side-fallback-2026-06-01` beta header and forwards the option as
`fallbacks: [{"model": "..."}]`. The response's `model` field reports which
model actually served the request.
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`
field reports which model actually served the request.

Rules checked at startup:

- A list holds at most three models, each distinct and different from the
primary model. Any other value is a configuration error.
- Server-side fallback is a Claude API feature: `fallbacks` is rejected on
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.

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. Not available on Bedrock, Vertex
AI, or the Message Batches API.
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.

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

## Native Compaction

Expand Down
17 changes: 14 additions & 3 deletions examples/anthropic-fallbacks.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Demonstrates Anthropic's server-side fallbacks (beta): when the primary
# model refuses a request, the API retries with the listed fallback models in
# order, in a single round trip.
# Demonstrates Anthropic's server-side fallbacks (beta, Claude API only):
# when the primary model refuses a request, the API retries on a fallback
# 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.
Expand All @@ -11,9 +13,18 @@ models:
provider_opts:
fallbacks:
- claude-opus-4-7
opus-default:
provider: anthropic
model: claude-opus-4-8
provider_opts:
fallbacks: default

agents:
root:
model: opus
description: Assistant on Claude Opus 4.8 with a server-side fallback model
instruction: You are a helpful assistant.
default-routing:
model: opus-default
description: Assistant whose refused requests use Anthropic's recommended fallback
instruction: You are a helpful assistant.
32 changes: 20 additions & 12 deletions pkg/model/provider/anthropic/beta_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"strings"

"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/option"
"github.com/anthropics/anthropic-sdk-go/packages/param"
"github.com/anthropics/anthropic-sdk-go/packages/ssestream"

Expand Down Expand Up @@ -65,9 +64,11 @@ func (c *Client) createBetaStream(

sys, transient := c.betaSystemContext(messages)

betas := []anthropic.AnthropicBeta{
anthropic.AnthropicBetaInterleavedThinking2025_05_14,
"fine-grained-tool-streaming-2025-05-14",
betas := []anthropic.AnthropicBeta{"fine-grained-tool-streaming-2025-05-14"}
// Requests reach this path for other reasons (fallbacks, structured
// output, ...); an explicit interleaved_thinking: false still holds.
if _, set := c.ModelConfig.ProviderOpts["interleaved_thinking"]; !set || c.interleavedThinkingEnabled() {
betas = append([]anthropic.AnthropicBeta{anthropic.AnthropicBetaInterleavedThinking2025_05_14}, betas...)
}

params := anthropic.BetaMessageNewParams{
Expand Down Expand Up @@ -98,6 +99,17 @@ func (c *Client) createBetaStream(
c.applyBetaThinkingConfig(&params, maxTokens)
c.applyThinkingBinding(&params)

// As on the standard path: sampling only applies with thinking off.
thinkingEnabled := params.Thinking.OfEnabled != nil || params.Thinking.OfAdaptive != nil
if !thinkingEnabled && !rejectsSampling(c.ModelConfig.Model) {
if c.ModelConfig.Temperature != nil {
params.Temperature = param.NewOpt(*c.ModelConfig.Temperature)
}
if c.ModelConfig.TopP != nil {
params.TopP = param.NewOpt(*c.ModelConfig.TopP)
}
}

// Forward task_budget via `output_config.task_budget` (Anthropic
// Opus 4.7+) and enable the corresponding beta header. Older Claude
// models will reject the field — docker-agent does not gate by model.
Expand All @@ -118,13 +130,9 @@ func (c *Client) createBetaStream(
slog.DebugContext(ctx, "Anthropic Beta provider_opts: set top_k", "value", topK)
}

// Enable server-side fallbacks when the fallbacks provider_opt is set;
// the beta is appended to params.Betas so the SDK composes a single
// anthropic-beta header.
var requestOpts []option.RequestOption
if fallbacks := fallbackModels(c.ModelConfig.ProviderOpts); len(fallbacks) > 0 {
if spec, _ := parseFallbacks(c.ModelConfig.ProviderOpts); spec.enabled() {
params.Betas = append(params.Betas, serverSideFallbackBeta)
requestOpts = append(requestOpts, fallbacksBody(fallbacks))
params.Fallbacks = spec.param()
}

configureCacheDiagnostics(&params, messages, c.ModelConfig.ProviderOpts)
Expand All @@ -139,7 +147,7 @@ func (c *Client) createBetaStream(
}
requestContext = updates.RequestContext
}
stream := client.Beta.Messages.NewStreaming(ctx, params, requestOpts...)
stream := client.Beta.Messages.NewStreaming(ctx, params)
trackUsage := c.TrackUsageEnabled()
ad := c.newBetaStreamAdapter(stream, trackUsage)
ad.requestContext = requestContext
Expand All @@ -159,7 +167,7 @@ func (c *Client) createBetaStream(
slog.WarnContext(ctx, "Retrying with clamped max_tokens after context length error", "original", maxTokens, "clamped", newMaxTokens, "used", used)
retryParams := params
retryParams.MaxTokens = newMaxTokens
return client.Beta.Messages.NewStreaming(ctx, retryParams, requestOpts...)
return client.Beta.Messages.NewStreaming(ctx, retryParams)
}

slog.DebugContext(ctx, "Anthropic Beta API chat completion stream created successfully", "model", c.ModelConfig.Model)
Expand Down
Loading
Loading