Anthropic Provider

AnthropicProvider implements the Anthropic Messages API with SSE streaming.

Usage

#![allow(unused)]
fn main() {
use yoagent::provider::ModelConfig;

let agent = Agent::from_config(ModelConfig::anthropic("claude-sonnet-5", "Claude Sonnet 5"));
}

Features

Streaming SSE

Uses reqwest-eventsource to parse Anthropic's SSE stream. Events handled:

  • message_start — Input token usage, cache stats
  • content_block_start — Text, thinking, or tool_use block
  • content_block_delta — Text, thinking, input JSON, or signature deltas
  • content_block_stop — Block complete
  • message_delta — Stop reason, output usage
  • message_stop — Stream complete

Thinking

Set thinking_level to enable thinking. By default the provider sends adaptive thinking (thinking: {"type": "adaptive"}), which the current model generation requires (Claude Fable 5, Opus 5, Opus 4.7/4.8, Sonnet 5 reject budget-based thinking with a 400). The level maps to an output_config.effort hint:

LevelEffort
Minimal, Lowlow
Mediummedium
Highhigh

For pre-4.6 models, opt into legacy budget-based thinking via AnthropicCompat::legacy():

#![allow(unused)]
fn main() {
let mut config = ModelConfig::anthropic("claude-sonnet-4-5", "Claude Sonnet 4.5");
config.anthropic = Some(AnthropicCompat::legacy());
}

Legacy budgets: Minimal/Low 1,024 (the API minimum), Medium 2,048, High 8,192. max_tokens is automatically raised above the budget when needed.

Thinking content is streamed as Content::Thinking with a cryptographic signature for verification.

Stop Reasons

Every documented Anthropic stop_reason maps explicitly:

Wire valueStopReasonNotes
end_turn, stop_sequenceStop
tool_useToolUse
max_tokensLength
refusalRefusalSets error_message; see below
model_context_window_exceededErrorIn-stream overflow; keeps the phrase Message::is_context_overflow() matches, so compaction-retry hooks still fire
pause_turnErrorThe model stopped mid-turn expecting the conversation to be re-sent. This transport cannot resume, so reporting it as a normal stop would return a truncated answer as though it were complete

Anything unrecognized maps to Stop and is logged at warn, so a stop reason added by Anthropic later is visible rather than silently treated as a finish.

Refusals. Models with safety classifiers (e.g. Claude Fable 5) can decline a request with stop_reason: "refusal". The agent loop stops the turn like a normal Stop, and callers can match on the variant to retry on a fallback model.

Tool Calls With Unusable Arguments

A tool call's arguments arrive as input_json_delta fragments and are assembled at content_block_stop. When that assembly cannot happen — the accumulated text is not valid JSON, or the content_block_stop event itself is unusable — the turn fails with StopReason::Error and an error_message naming each affected tool and quoting its input.

This matters because the alternative is silent: a tool executed with empty arguments falls back to its defaults, so list_files asked for /etc would list the working directory instead, with nothing in the response indicating the model's actual input was dropped.

agent_loop returns on StopReason::Error before extracting tool calls, so nothing executes. Every tool call in the message is replaced with a text block — not just the unusable one — because the turn runs none of them, and a tool_use block with no matching tool_result is rejected by the API on the next request.

Cache Control

Automatic prompt caching via cache_control markers:

  • System prompt: Always cached with {"type": "ephemeral"}
  • Second-to-last message: Gets cache_control on its last content block, creating a cache breakpoint

This means on repeated calls, only the latest message is processed at full price.

Configuration

SettingValue
API URL{base_url}/messages (default https://api.anthropic.com/v1/messages)
API Version2023-06-01
Auth Headerx-api-key (or Authorization: Bearer with AnthropicCompat { bearer_auth: true } / a custom authorization header in ModelConfig.headers)
Default Max Tokensrequest max_tokens, else ModelConfig.max_tokens, else 8,192

Setting ModelConfig.base_url retargets the provider at any gateway that speaks the Anthropic Messages protocol (e.g. OpenCode Zen/Go — see OpenCode Zen & Go).

Environment Variables

VariablePurpose
ANTHROPIC_API_KEYAPI key