Tools Guide
Learn advanced tool calling patterns. Tools →
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)}# Store in the encrypted keystore (recommended)iris keys set anthropic# Prompts for: Enter API key for anthropic: sk-ant-...export ANTHROPIC_API_KEY=sk-ant-...import "github.com/petal-labs/iris/providers/anthropic"// From an API key stringprovider := anthropic.New("sk-ant-...")
// From the ANTHROPIC_API_KEY environment variableprovider, 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()| Option | Description | Default |
|---|---|---|
WithBaseURL(url) | Override the API base URL | https://api.anthropic.com |
WithHTTPClient(client) | Use a custom *http.Client | Default client |
WithVersion(version) | Set the Anthropic API version | 2023-06-01 |
WithFilesAPIBeta(beta) | Set the Files API beta version | files-api-2025-04-14 |
WithHeader(key, value) | Add a custom HTTP header | None |
WithTimeout(duration) | Set the request timeout | 60 seconds |
provider := anthropic.New("sk-ant-...", anthropic.WithVersion("2023-06-01"), anthropic.WithTimeout(120 * time.Second), anthropic.WithHeader("X-Custom-Header", "value"),)| Feature | Supported | Notes |
|---|---|---|
| Chat | ✓ | All Claude models |
| Streaming | ✓ | Real-time token streaming |
| Tool calling | ✓ | Parallel and sequential |
| Vision | ✓ | Image analysis with all Claude 3+ models |
| Extended thinking | ✓ | Deep reasoning with Claude 3.5+ |
| Files API | ✓ | PDF and document processing |
| Image generation | Not supported | |
| Embeddings | Not supported |
| Model | Context | Best For |
|---|---|---|
claude-sonnet-4-20250514 | 200K | Best balance of speed, quality, and cost |
claude-opus-4-20250514 | 200K | Complex analysis, nuanced tasks |
| Model | Context | Best For |
|---|---|---|
claude-3-5-sonnet-20241022 | 200K | General purpose, coding, analysis |
claude-3-5-haiku-20241022 | 200K | Fast responses, cost-effective |
| Model | Context | Best For |
|---|---|---|
claude-3-opus-20240229 | 200K | Complex reasoning, research |
claude-3-sonnet-20240229 | 200K | Balanced performance |
claude-3-haiku-20240307 | 200K | Speed, 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 errorsif err := <-stream.Err; err != nil { log.Fatal(err)}
// Get final response with usage statsfinal := <-stream.Finalfmt.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 URLresp, 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)| Format | MIME Type | Max Size |
|---|---|---|
| PNG | image/png | 5 MB |
| JPEG | image/jpeg | 5 MB |
| GIF | image/gif | 5 MB |
| WebP | image/webp | 5 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 processif resp.Thinking != "" { fmt.Println("=== Reasoning Process ===") fmt.Println(resp.Thinking) fmt.Println()}
fmt.Println("=== Final Answer ===")fmt.Println(resp.Output)| Use Case | Recommended |
|---|---|
| Math proofs | Yes |
| Code debugging | Yes |
| Complex analysis | Yes |
| Multi-step reasoning | Yes |
| Simple Q&A | No (adds latency) |
| Creative writing | No |
Define and use tools with Claude:
// Define a toolsearchTool := 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 toolresp, 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 toolresp, err := client.Chat("claude-sonnet-4-20250514"). User("What's the weather?"). Tools(weatherTool). ToolChoice(core.ToolChoiceRequired). GetResponse(ctx)
// Or specify a specific toolresp, 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 PDFpdfData, err := os.ReadFile("document.pdf")if err != nil { log.Fatal(err)}
// Analyze the PDFresp, 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 promptresp, err := client.Chat("claude-sonnet-4-20250514"). System("You are a helpful assistant."). User("Hello!"). GetResponse(ctx)
// Detailed system promptresp, err := client.Chat("claude-sonnet-4-20250514"). System(`You are an expert Go developer and code reviewer.
Your responsibilities:1. Provide accurate, idiomatic Go code2. Explain your reasoning3. Point out potential issues4. Suggest improvements
Always use Go 1.21+ features when appropriate.`). User("Review this code: ..."). GetResponse(ctx)Build conversation history for multi-turn interactions:
// First turnresp1, _ := client.Chat("claude-sonnet-4-20250514"). System("You are a helpful Go tutor."). User("What is a goroutine?"). GetResponse(ctx)
// Second turn with historyresp2, _ := 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 conversationresp3, _ := 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 CodeReviewjson.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 codebasecodebase := 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 patterns2. Potential issues3. Improvement suggestions
Codebase:%s`, codebase)). GetResponse(ctx)| Task | Recommended Model |
|---|---|
| General chat | claude-3-5-haiku |
| Code generation | claude-sonnet-4 |
| Complex reasoning | claude-opus-4 with extended thinking |
| Fast responses | claude-3-5-haiku |
| Long documents | claude-sonnet-4 (200K context) |
| Vision tasks | claude-sonnet-4 |
// Good - specific and structuredSystem(`You are an expert Go developer specializing in concurrent systems.
When reviewing code:1. Check for race conditions2. Verify proper channel usage3. Suggest idiomatic improvements
Format your response as:- Summary- Issues found- Recommendations`)
// Less effective - vagueSystem("You are helpful")// For complex reasoning - use extended thinkingresp, err := client.Chat("claude-sonnet-4-20250514"). User("Debug this race condition..."). ExtendedThinking(true). ThinkingBudget(5000). GetResponse(ctx)
// For simple tasks - skip extended thinkingresp, 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}, }),)x-api-key header for authentication (not Authorization: Bearer)Tools Guide
Learn advanced tool calling patterns. Tools →
Streaming Guide
Master streaming responses. Streaming →
Images Guide
Work with vision capabilities. Images →
Providers Overview
Compare all available providers. Providers →