Skip to main content

Overview

The Anthropic provider connects to Claude models including Sonnet, Opus, and Haiku. It supports advanced features like extended thinking, prompt caching, and tool use. Source: crates/goose/src/providers/anthropic.rs

Configuration

Environment Variables

ANTHROPIC_API_KEY
string
required
Your Anthropic API key from https://console.anthropic.com
ANTHROPIC_HOST
string
default:"https://api.anthropic.com"
API endpoint URL (for proxy or alternative endpoints)

Setup

# Configure using the CLI
goose configure

# Or set environment variables
export ANTHROPIC_API_KEY="your-api-key"
export ANTHROPIC_HOST="https://api.anthropic.com"  # optional

Supported Models

Claude 4.6

  • claude-opus-4-6 - Most capable model
  • claude-sonnet-4-6 - Balanced performance

Claude 4.5 (Default)

  • claude-sonnet-4-5 (default) - Latest Sonnet with improved reasoning
  • claude-sonnet-4-5-20250929 - Dated version
  • claude-haiku-4-5 (fast model) - Fastest Claude 4.5
  • claude-haiku-4-5-20251001 - Dated version
  • claude-opus-4-5 - Most capable 4.5 model
  • claude-opus-4-5-20251101 - Dated version

Claude 4.0 (Legacy)

  • claude-sonnet-4-0
  • claude-sonnet-4-20250514 - Dated version
  • claude-opus-4-0
  • claude-opus-4-20250514 - Dated version
Context Limit: 200,000 tokens for all models Documentation: https://docs.anthropic.com/en/docs/about-claude/models

Usage

Basic Usage

use goose::providers::create;
use goose::model::ModelConfig;

// Create with default model (claude-sonnet-4-5)
let model_config = ModelConfig::new("claude-sonnet-4-5")?;
let provider = create("anthropic", model_config, vec![]).await?;

// Stream a response
let messages = vec![Message::user().with_text("Hello, Claude!")];
let stream = provider.stream(
    &provider.get_model_config(),
    "session-123",
    "You are a helpful assistant.",
    &messages,
    &[],
).await?;

Custom Configuration

use goose::model::ModelConfig;

let model_config = ModelConfig::new("claude-opus-4-6")?
    .with_temperature(0.7)
    .with_max_tokens(4096)
    .with_top_p(0.9);

let provider = create("anthropic", model_config, vec![]).await?;

Using Fast Models

The Anthropic provider automatically configures claude-haiku-4-5 as the fast model:
// Use fast model for quick operations
let (response, usage) = provider.complete_fast(
    "session-123",
    "You are a helpful assistant.",
    &messages,
    &[],
).await?;

Advanced Features

Extended Thinking

Claude 3.7 Sonnet supports extended thinking mode:
let model_config = ModelConfig::new("claude-3-7-sonnet-20250219")?
    .with_extended_thinking(true);
When enabled, the provider automatically adds the appropriate beta headers:
  • anthropic-beta: output-128k-2025-02-19
  • anthropic-beta: token-efficient-tools-2025-02-19

Prompt Caching

Anthropic supports prompt caching to reduce costs on repeated content:
// Check if caching is supported
if provider.supports_cache_control().await {
    // Caching is automatically applied to system prompts
    // and conversation history in long sessions
}

Streaming Responses

All Anthropic models support streaming:
use futures::StreamExt;

let mut stream = provider.stream(
    &model_config,
    "session-123",
    "You are a helpful assistant.",
    &messages,
    &tools,
).await?;

while let Some(result) = stream.next().await {
    let (message, usage) = result?;
    if let Some(msg) = message {
        // Process streaming message chunk
        println!("Received: {:?}", msg);
    }
}

Tool Use

Claude excels at tool use (function calling):
use rmcp::model::Tool;

let tools = vec![
    Tool {
        name: "get_weather".into(),
        description: Some("Get weather for a location".into()),
        input_schema: serde_json::json!({
            "type": "object",
            "properties": {
                "location": {"type": "string"},
            },
            "required": ["location"],
        }),
    },
];

let stream = provider.stream(
    &model_config,
    "session-123",
    "You are a helpful assistant.",
    &messages,
    &tools,
).await?;

Implementation Details

Provider Metadata

impl ProviderDef for AnthropicProvider {
    fn metadata() -> ProviderMetadata {
        ProviderMetadata::with_models(
            "anthropic",
            "Anthropic",
            "Claude and other models from Anthropic",
            "claude-sonnet-4-5",
            models,
            "https://docs.anthropic.com/en/docs/about-claude/models",
            vec![
                ConfigKey::new("ANTHROPIC_API_KEY", true, true, None, true),
                ConfigKey::new(
                    "ANTHROPIC_HOST",
                    true,
                    false,
                    Some("https://api.anthropic.com"),
                    false,
                ),
            ],
        )
    }
}

API Format

The provider uses the Messages API format:
{
  "model": "claude-sonnet-4-5",
  "max_tokens": 4096,
  "system": "You are a helpful assistant.",
  "messages": [
    {
      "role": "user",
      "content": "Hello, Claude!"
    }
  ],
  "stream": true
}

Authentication

Uses API key authentication via the x-api-key header:
let auth = AuthMethod::ApiKey {
    header_name: "x-api-key".to_string(),
    key: api_key,
};
API version is specified via header:
anthropic-version: 2023-06-01

Conditional Headers

The provider dynamically adds beta headers for certain models:
fn get_conditional_headers(&self) -> Vec<(&str, &str)> {
    let mut headers = Vec::new();
    
    if self.model.model_name.starts_with("claude-3-7-sonnet-") {
        if thinking_type(&self.model) == ThinkingType::Enabled {
            headers.push(("anthropic-beta", "output-128k-2025-02-19"));
        }
        headers.push(("anthropic-beta", "token-efficient-tools-2025-02-19"));
    }
    
    headers
}

Error Handling

The provider handles Anthropic-specific errors:
match provider.stream(...).await {
    Ok(stream) => { /* handle stream */ },
    Err(ProviderError::Authentication(msg)) => {
        eprintln!("Invalid API key: {}", msg);
    },
    Err(ProviderError::RateLimited { retry_after }) => {
        eprintln!("Rate limited, retry after: {:?}", retry_after);
    },
    Err(ProviderError::ContextLengthExceeded(msg)) => {
        eprintln!("Context too long: {}", msg);
    },
    Err(e) => eprintln!("Error: {}", e),
}

Fetching Available Models

// Get all available models from the API
let models = provider.fetch_supported_models().await?;

// Get recommended models (filtered and sorted)
let recommended = provider.fetch_recommended_models().await?;

Cost Tracking

The provider returns usage information with each response:
let (message, usage) = provider.complete(...).await?;

println!("Model: {}", usage.model);
println!("Input tokens: {:?}", usage.usage.input_tokens);
println!("Output tokens: {:?}", usage.usage.output_tokens);
println!("Total tokens: {:?}", usage.usage.total_tokens);

See Also

Build docs developers (and LLMs) love