Skip to content

Anthropic

The Anthropic provider connects Iris to the Claude model family. Claude excels at nuanced understanding, long-context processing, careful instruction following, and complex reasoning with extended thinking.

package main
import (
"context"
"fmt"
"os"
"github.com/petal-labs/iris/core"
"github.com/petal-labs/iris/providers/anthropic"
)
func main() {
provider := anthropic.New(os.Getenv("ANTHROPIC_API_KEY"))
client := core.NewClient(provider)
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a concise technical writer.").
User("Explain Go's defer statement in two sentences.").
GetResponse(context.Background())
if err != nil {
panic(err)
}
fmt.Println(resp.Output)
}
Terminal window
# Store in the encrypted keystore (recommended)
iris keys set anthropic
# Prompts for: Enter API key for anthropic: sk-ant-...
import "github.com/petal-labs/iris/providers/anthropic"
// From an API key string
provider := anthropic.New("sk-ant-...")
// From the ANTHROPIC_API_KEY environment variable
provider, err := anthropic.NewFromEnv()
if err != nil {
log.Fatal("ANTHROPIC_API_KEY not set:", err)
}
// From the Iris keystore (falls back to environment)
provider, err := anthropic.NewFromKeystore()
OptionDescriptionDefault
WithBaseURL(url)Override the API base URLhttps://api.anthropic.com
WithHTTPClient(client)Use a custom *http.ClientDefault client
WithVersion(version)Set the Anthropic API version2023-06-01
WithFilesAPIBeta(beta)Set the Files API beta versionfiles-api-2025-04-14
WithHeader(key, value)Add a custom HTTP headerNone
WithTimeout(duration)Set the request timeout60 seconds
provider := anthropic.New("sk-ant-...",
anthropic.WithVersion("2023-06-01"),
anthropic.WithTimeout(120 * time.Second),
anthropic.WithHeader("X-Custom-Header", "value"),
)
FeatureSupportedNotes
ChatAll Claude models
StreamingReal-time token streaming
Tool callingParallel and sequential
VisionImage analysis with all Claude 3+ models
Extended thinkingDeep reasoning with Claude 3.5+
Files APIPDF and document processing
Image generationNot supported
EmbeddingsNot supported
ModelContextBest For
claude-sonnet-4-20250514200KBest balance of speed, quality, and cost
claude-opus-4-20250514200KComplex analysis, nuanced tasks
ModelContextBest For
claude-3-5-sonnet-20241022200KGeneral purpose, coding, analysis
claude-3-5-haiku-20241022200KFast responses, cost-effective
ModelContextBest For
claude-3-opus-20240229200KComplex reasoning, research
claude-3-sonnet-20240229200KBalanced performance
claude-3-haiku-20240307200KSpeed, simple tasks
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful coding assistant specialized in Go.").
User("Write a concurrent-safe counter in Go.").
Temperature(0.3).
MaxTokens(1000).
GetResponse(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Output)
fmt.Printf("Tokens: %d input, %d output\n", resp.Usage.InputTokens, resp.Usage.OutputTokens)

Stream responses for real-time output:

stream, err := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful assistant.").
User("Explain Go's concurrency model.").
GetStream(ctx)
if err != nil {
log.Fatal(err)
}
for chunk := range stream.Ch {
fmt.Print(chunk.Content)
}
fmt.Println()
// Check for streaming errors
if err := <-stream.Err; err != nil {
log.Fatal(err)
}
// Get final response with usage stats
final := <-stream.Final
fmt.Printf("Total tokens: %d\n", final.Usage.TotalTokens)

When using extended thinking, you can access the reasoning process:

stream, err := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful assistant.").
User("Solve this complex problem step by step...").
ExtendedThinking(true).
ThinkingBudget(5000). // Tokens for reasoning
GetStream(ctx)
for chunk := range stream.Ch {
if chunk.IsThinking {
fmt.Print("[Thinking] ", chunk.Content)
} else {
fmt.Print(chunk.Content)
}
}

Claude 3+ models support image analysis:

// Image from URL
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful image analyst.").
UserMultimodal().
Text("What's in this image? Describe it in detail.").
ImageURL("https://example.com/photo.jpg").
Done().
GetResponse(ctx)
imageData, err := os.ReadFile("screenshot.png")
if err != nil {
log.Fatal(err)
}
base64Data := base64.StdEncoding.EncodeToString(imageData)
resp, err := client.Chat("claude-sonnet-4-20250514").
UserMultimodal().
Text("Analyze this screenshot and identify any UI issues.").
ImageBase64(base64Data, "image/png").
Done().
GetResponse(ctx)
resp, err := client.Chat("claude-sonnet-4-20250514").
UserMultimodal().
Text("Compare these two diagrams. What are the differences?").
ImageURL("https://example.com/diagram-v1.png").
ImageURL("https://example.com/diagram-v2.png").
Done().
GetResponse(ctx)
FormatMIME TypeMax Size
PNGimage/png5 MB
JPEGimage/jpeg5 MB
GIFimage/gif5 MB
WebPimage/webp5 MB

Extended thinking enables Claude to reason through complex problems:

resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a world-class mathematician.").
User("Prove that the square root of 2 is irrational.").
ExtendedThinking(true).
ThinkingBudget(10000). // Max tokens for reasoning
GetResponse(ctx)
// Access the thinking process
if resp.Thinking != "" {
fmt.Println("=== Reasoning Process ===")
fmt.Println(resp.Thinking)
fmt.Println()
}
fmt.Println("=== Final Answer ===")
fmt.Println(resp.Output)
Use CaseRecommended
Math proofsYes
Code debuggingYes
Complex analysisYes
Multi-step reasoningYes
Simple Q&ANo (adds latency)
Creative writingNo

Define and use tools with Claude:

// Define a tool
searchTool := core.Tool{
Name: "search_documents",
Description: "Search through the document database for relevant information",
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"query": map[string]interface{}{
"type": "string",
"description": "The search query",
},
"limit": map[string]interface{}{
"type": "integer",
"description": "Maximum number of results to return",
},
},
"required": []string{"query"},
},
}
// First request - Claude decides to call tool
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful research assistant with access to a document database.").
User("Find information about Go's garbage collector.").
Tools(searchTool).
GetResponse(ctx)
if len(resp.ToolCalls) > 0 {
call := resp.ToolCalls[0]
// Execute the search (your implementation)
results := searchDocuments(call.Arguments)
// Continue with tool result
finalResp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful research assistant with access to a document database.").
User("Find information about Go's garbage collector.").
Tools(searchTool).
Assistant(resp.Output).
ToolCall(call.ID, call.Name, call.Arguments).
ToolResult(call.ID, results).
GetResponse(ctx)
fmt.Println(finalResp.Output)
}
// Force Claude to use a specific tool
resp, err := client.Chat("claude-sonnet-4-20250514").
User("What's the weather?").
Tools(weatherTool).
ToolChoice(core.ToolChoiceRequired).
GetResponse(ctx)
// Or specify a specific tool
resp, err := client.Chat("claude-sonnet-4-20250514").
User("What's the weather?").
Tools(weatherTool, searchTool).
ToolChoiceTool("get_weather").
GetResponse(ctx)

Process PDFs and documents using the Files API:

// Upload a PDF
pdfData, err := os.ReadFile("document.pdf")
if err != nil {
log.Fatal(err)
}
// Analyze the PDF
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a document analyst.").
UserWithFile().
Text("Summarize the key points in this document.").
PDF(pdfData, "document.pdf").
Done().
GetResponse(ctx)
fmt.Println(resp.Output)
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a legal document analyst.").
UserWithFile().
Text("Compare these two contracts and highlight the differences.").
PDF(contract1Data, "contract_v1.pdf").
PDF(contract2Data, "contract_v2.pdf").
Done().
GetResponse(ctx)

Claude uses system prompts to set behavior and context:

// Basic system prompt
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful assistant.").
User("Hello!").
GetResponse(ctx)
// Detailed system prompt
resp, err := client.Chat("claude-sonnet-4-20250514").
System(`You are an expert Go developer and code reviewer.
Your responsibilities:
1. Provide accurate, idiomatic Go code
2. Explain your reasoning
3. Point out potential issues
4. Suggest improvements
Always use Go 1.21+ features when appropriate.`).
User("Review this code: ...").
GetResponse(ctx)

Build conversation history for multi-turn interactions:

// First turn
resp1, _ := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful Go tutor.").
User("What is a goroutine?").
GetResponse(ctx)
// Second turn with history
resp2, _ := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful Go tutor.").
User("What is a goroutine?").
Assistant(resp1.Output).
User("How do I create one?").
GetResponse(ctx)
// Continue the conversation
resp3, _ := client.Chat("claude-sonnet-4-20250514").
System("You are a helpful Go tutor.").
User("What is a goroutine?").
Assistant(resp1.Output).
User("How do I create one?").
Assistant(resp2.Output).
User("Show me an example with channels.").
GetResponse(ctx)

Force structured JSON responses:

type CodeReview struct {
Summary string `json:"summary"`
Issues []Issue `json:"issues"`
Suggestions []string `json:"suggestions"`
OverallScore int `json:"overall_score"`
}
type Issue struct {
Line int `json:"line"`
Severity string `json:"severity"`
Description string `json:"description"`
}
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a code reviewer. Always respond with valid JSON.").
User("Review this Go code and provide structured feedback: ...").
ResponseFormat(core.ResponseFormatJSON).
GetResponse(ctx)
var review CodeReview
json.Unmarshal([]byte(resp.Output), &review)
fmt.Printf("Overall Score: %d/10\n", review.OverallScore)
resp, err := client.Chat("claude-sonnet-4-20250514").User(prompt).GetResponse(ctx)
if err != nil {
var apiErr *core.APIError
if errors.As(err, &apiErr) {
switch apiErr.StatusCode {
case 400:
log.Printf("Bad request: %s", apiErr.Message)
case 401:
log.Fatal("Invalid API key")
case 429:
if apiErr.Type == "rate_limit_error" {
log.Printf("Rate limited. Retry after: %s", apiErr.RetryAfter)
} else {
log.Printf("Overloaded: %s", apiErr.Message)
}
case 529:
log.Println("Anthropic API is overloaded, please retry")
default:
log.Printf("API error %d: %s", apiErr.StatusCode, apiErr.Message)
}
return
}
if errors.Is(err, context.DeadlineExceeded) {
log.Println("Request timed out")
} else if errors.Is(err, context.Canceled) {
log.Println("Request canceled")
}
}

Claude’s 200K context window enables processing large documents:

// Process a large codebase
codebase := loadCodebase() // May be 100K+ tokens
resp, err := client.Chat("claude-sonnet-4-20250514").
System("You are a senior software architect.").
User(fmt.Sprintf(`Analyze this codebase and identify:
1. Architectural patterns
2. Potential issues
3. Improvement suggestions
Codebase:
%s`, codebase)).
GetResponse(ctx)
TaskRecommended Model
General chatclaude-3-5-haiku
Code generationclaude-sonnet-4
Complex reasoningclaude-opus-4 with extended thinking
Fast responsesclaude-3-5-haiku
Long documentsclaude-sonnet-4 (200K context)
Vision tasksclaude-sonnet-4
// Good - specific and structured
System(`You are an expert Go developer specializing in concurrent systems.
When reviewing code:
1. Check for race conditions
2. Verify proper channel usage
3. Suggest idiomatic improvements
Format your response as:
- Summary
- Issues found
- Recommendations`)
// Less effective - vague
System("You are helpful")
// For complex reasoning - use extended thinking
resp, err := client.Chat("claude-sonnet-4-20250514").
User("Debug this race condition...").
ExtendedThinking(true).
ThinkingBudget(5000).
GetResponse(ctx)
// For simple tasks - skip extended thinking
resp, err := client.Chat("claude-3-5-haiku").
User("Format this JSON").
GetResponse(ctx)
client := core.NewClient(provider,
core.WithRetryPolicy(&core.RetryPolicy{
MaxRetries: 3,
InitialInterval: 2 * time.Second,
MaxInterval: 60 * time.Second,
BackoffMultiplier: 2.0,
RetryOn: []int{429, 529},
}),
)
  • Anthropic uses the x-api-key header for authentication (not Authorization: Bearer)
  • The Files API (PDF processing) requires the beta header, enabled by default
  • Extended thinking is available on Claude 3.5 Sonnet and newer models
  • All Claude 3+ models support vision capabilities
  • The provider is safe for concurrent use after construction

Tools Guide

Learn advanced tool calling patterns. Tools →

Images Guide

Work with vision capabilities. Images →

Providers Overview

Compare all available providers. Providers →