Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build LLM-powered apps with the Anthropic Claude API or SDK across Python, TypeScript, Java, Go, Ruby, C#, and PHP.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
go/claude-api.md
1# Claude API — Go23> **Note:** The Go SDK supports the Claude API and beta tool use with `BetaToolRunner`. Agent SDK is not yet available for Go.45## Installation67```bash8go get github.com/anthropics/anthropic-sdk-go9```1011## Client Initialization1213```go14import (15"github.com/anthropics/anthropic-sdk-go"16"github.com/anthropics/anthropic-sdk-go/option"17)1819// Default (uses ANTHROPIC_API_KEY env var)20client := anthropic.NewClient()2122// Explicit API key23client := anthropic.NewClient(24option.WithAPIKey("your-api-key"),25)26```2728---2930## Model Constants3132The Go SDK provides typed model constants: `anthropic.ModelClaudeFable5`, `anthropic.ModelClaudeOpus4_8`, `anthropic.ModelClaudeOpus4_7`, `anthropic.ModelClaudeSonnet4_6`, `anthropic.ModelClaudeHaiku4_5_20251001`. Use `ModelClaudeOpus4_8` unless the user specifies otherwise; if they ask for Fable or the most powerful model, use `anthropic.ModelClaudeFable5` (see `shared/models.md` for the full resolution table).3334---3536## Basic Message Request3738```go39response, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{40Model: anthropic.ModelClaudeOpus4_8,41MaxTokens: 16000,42Messages: []anthropic.MessageParam{43anthropic.NewUserMessage(anthropic.NewTextBlock("What is the capital of France?")),44},45})46if err != nil {47log.Fatal(err)48}49for _, block := range response.Content {50switch variant := block.AsAny().(type) {51case anthropic.TextBlock:52fmt.Println(variant.Text)53}54}55```5657---5859## Streaming6061```go62stream := client.Messages.NewStreaming(context.Background(), anthropic.MessageNewParams{63Model: anthropic.ModelClaudeOpus4_6,64MaxTokens: 64000,65Messages: []anthropic.MessageParam{66anthropic.NewUserMessage(anthropic.NewTextBlock("Write a haiku")),67},68})6970for stream.Next() {71event := stream.Current()72switch eventVariant := event.AsAny().(type) {73case anthropic.ContentBlockDeltaEvent:74switch deltaVariant := eventVariant.Delta.AsAny().(type) {75case anthropic.TextDelta:76fmt.Print(deltaVariant.Text)77}78}79}80if err := stream.Err(); err != nil {81log.Fatal(err)82}83```8485**Accumulating the final message** (there is no `GetFinalMessage()` on the stream):8687```go88stream := client.Messages.NewStreaming(ctx, params)89message := anthropic.Message{}90for stream.Next() {91message.Accumulate(stream.Current())92}93if err := stream.Err(); err != nil { log.Fatal(err) }94// message.Content now has the complete response95```969798---99100## Tool Use101102### Tool Runner (Beta — Recommended)103104**Beta:** The Go SDK provides `BetaToolRunner` for automatic tool use loops via the `toolrunner` package.105106```go107import (108"context"109"fmt"110"log"111112"github.com/anthropics/anthropic-sdk-go"113"github.com/anthropics/anthropic-sdk-go/toolrunner"114)115116// Define tool input with jsonschema tags for automatic schema generation117type GetWeatherInput struct {118City string `json:"city" jsonschema:"required,description=The city name"`119}120121// Create a tool with automatic schema generation from struct tags122weatherTool, err := toolrunner.NewBetaToolFromJSONSchema(123"get_weather",124"Get current weather for a city",125func(ctx context.Context, input GetWeatherInput) (anthropic.BetaToolResultBlockParamContentUnion, error) {126return anthropic.BetaToolResultBlockParamContentUnion{127OfText: &anthropic.BetaTextBlockParam{128Text: fmt.Sprintf("The weather in %s is sunny, 72°F", input.City),129},130}, nil131},132)133if err != nil {134log.Fatal(err)135}136137// Create a tool runner that handles the conversation loop automatically138runner := client.Beta.Messages.NewToolRunner(139[]anthropic.BetaTool{weatherTool},140anthropic.BetaToolRunnerParams{141BetaMessageNewParams: anthropic.BetaMessageNewParams{142Model: anthropic.ModelClaudeOpus4_6,143MaxTokens: 16000,144Messages: []anthropic.BetaMessageParam{145anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's the weather in Paris?")),146},147},148MaxIterations: 5,149},150)151152// Run until Claude produces a final response153message, err := runner.RunToCompletion(context.Background())154if err != nil {155log.Fatal(err)156}157158// RunToCompletion returns *BetaMessage; content is []BetaContentBlockUnion.159// Narrow via AsAny() switch — note the Beta-namespace types (BetaTextBlock,160// not TextBlock):161for _, block := range message.Content {162switch block := block.AsAny().(type) {163case anthropic.BetaTextBlock:164fmt.Println(block.Text)165}166}167```168169**Key features of the Go tool runner:**170171- Automatic schema generation from Go structs via `jsonschema` tags172- `RunToCompletion()` for simple one-shot usage173- `All()` iterator for processing each message in the conversation174- `NextMessage()` for step-by-step iteration175- Streaming variant via `NewToolRunnerStreaming()` with `AllStreaming()`176177### Manual Loop178179For fine-grained control over the agentic loop, define tools with `ToolParam`, check `StopReason`, execute tools yourself, and feed `tool_result` blocks back. This is the pattern when you need to intercept, validate, or log tool calls.180181Derived from `anthropic-sdk-go/examples/tools/main.go`.182183```go184package main185186import (187"context"188"encoding/json"189"fmt"190"log"191192"github.com/anthropics/anthropic-sdk-go"193)194195func main() {196client := anthropic.NewClient()197198// 1. Define tools. ToolParam.InputSchema uses a map, no struct tags needed.199addTool := anthropic.ToolParam{200Name: "add",201Description: anthropic.String("Add two integers"),202InputSchema: anthropic.ToolInputSchemaParam{203Properties: map[string]any{204"a": map[string]any{"type": "integer"},205"b": map[string]any{"type": "integer"},206},207},208}209// ToolParam must be wrapped in ToolUnionParam for the Tools slice210tools := []anthropic.ToolUnionParam{{OfTool: &addTool}}211212messages := []anthropic.MessageParam{213anthropic.NewUserMessage(anthropic.NewTextBlock("What is 2 + 3?")),214}215216for {217resp, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{218Model: anthropic.ModelClaudeSonnet4_6,219MaxTokens: 16000,220Messages: messages,221Tools: tools,222})223if err != nil {224log.Fatal(err)225}226227// 2. Append the assistant response to history BEFORE processing tool calls.228// resp.ToParam() converts Message → MessageParam in one call.229messages = append(messages, resp.ToParam())230231// 3. Walk content blocks. ContentBlockUnion is a flattened struct;232// use block.AsAny().(type) to switch on the actual variant.233toolResults := []anthropic.ContentBlockParamUnion{}234for _, block := range resp.Content {235switch variant := block.AsAny().(type) {236case anthropic.TextBlock:237fmt.Println(variant.Text)238case anthropic.ToolUseBlock:239// 4. Parse the tool input. Use variant.JSON.Input.Raw() to get the240// raw JSON — block.Input is json.RawMessage, not the parsed value.241var in struct {242A int `json:"a"`243B int `json:"b"`244}245if err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &in); err != nil {246log.Fatal(err)247}248result := fmt.Sprintf("%d", in.A+in.B)249// 5. NewToolResultBlock(toolUseID, content, isError) builds the250// ContentBlockParamUnion for you. block.ID is the tool_use_id.251toolResults = append(toolResults,252anthropic.NewToolResultBlock(block.ID, result, false))253}254}255256// 6. Exit when Claude stops asking for tools257if resp.StopReason != anthropic.StopReasonToolUse {258break259}260261// 7. Tool results go in a user message (variadic: all results in one turn)262messages = append(messages, anthropic.NewUserMessage(toolResults...))263}264}265```266267**Key API surface:**268269| Symbol | Purpose |270|---|---|271| `resp.ToParam()` | Convert `Message` response → `MessageParam` for history |272| `block.AsAny().(type)` | Type-switch on `ContentBlockUnion` variants |273| `variant.JSON.Input.Raw()` | Raw JSON string of tool input (for `json.Unmarshal`) |274| `anthropic.NewToolResultBlock(id, content, isError)` | Build `tool_result` block |275| `anthropic.NewUserMessage(blocks...)` | Wrap tool results as a user turn |276| `anthropic.StopReasonToolUse` | `StopReason` constant to check loop termination |277| `anthropic.ToolUnionParam{OfTool: &t}` | Wrap `ToolParam` in the union for `Tools:` |278279---280281## Thinking282283Enable Claude's internal reasoning by setting `Thinking` in `MessageNewParams`. The response will contain `ThinkingBlock` content before the final `TextBlock`.284285**Adaptive thinking is the recommended mode for Claude 4.6+ models.** Claude decides dynamically when and how much to think. Combine with the `effort` parameter for cost-quality control.286287Derived from `anthropic-sdk-go/message.go` (`ThinkingConfigParamUnion`, `ThinkingConfigAdaptiveParam`).288289```go290// There is no ThinkingConfigParamOfAdaptive helper — construct the union291// struct-literal directly and take the address of the variant.292adaptive := anthropic.ThinkingConfigAdaptiveParam{}293params := anthropic.MessageNewParams{294Model: anthropic.ModelClaudeSonnet4_6,295MaxTokens: 16000,296Thinking: anthropic.ThinkingConfigParamUnion{OfAdaptive: &adaptive},297Messages: []anthropic.MessageParam{298anthropic.NewUserMessage(anthropic.NewTextBlock("How many r's in strawberry?")),299},300}301302resp, err := client.Messages.New(context.Background(), params)303if err != nil {304log.Fatal(err)305}306307// ThinkingBlock(s) precede TextBlock in content308for _, block := range resp.Content {309switch b := block.AsAny().(type) {310case anthropic.ThinkingBlock:311fmt.Println("[thinking]", b.Thinking)312case anthropic.TextBlock:313fmt.Println(b.Text)314}315}316```317318> **Deprecated:** `ThinkingConfigParamOfEnabled(budgetTokens)` (fixed-budget extended thinking) still works on Claude 4.6 but is deprecated. Use adaptive thinking above.319320To disable: `anthropic.ThinkingConfigParamUnion{OfDisabled: &anthropic.ThinkingConfigDisabledParam{}}`.321322---323324## Prompt Caching325326`System` is `[]TextBlockParam`; set `CacheControl` on the last block to cache tools + system together. For placement patterns and the silent-invalidator audit checklist, see `shared/prompt-caching.md`.327328```go329System: []anthropic.TextBlockParam{{330Text: longSystemPrompt,331CacheControl: anthropic.NewCacheControlEphemeralParam(), // default 5m TTL332}},333```334335For 1-hour TTL: `anthropic.CacheControlEphemeralParam{TTL: anthropic.CacheControlEphemeralTTLTTL1h}`. There's also a top-level `CacheControl` on `MessageNewParams` that auto-places on the last cacheable block.336337Verify hits via `resp.Usage.CacheCreationInputTokens` / `resp.Usage.CacheReadInputTokens`.338339---340341## Server-Side Tools342343Version-suffixed struct names with `Param` suffix. `Name`/`Type` are `constant.*` types — zero value marshals correctly, so `{}` works. Wrap in `ToolUnionParam` with the matching `Of*` field.344345```go346Tools: []anthropic.ToolUnionParam{347{OfWebSearchTool20260209: &anthropic.WebSearchTool20260209Param{}},348{OfBashTool20250124: &anthropic.ToolBash20250124Param{}},349{OfTextEditor20250728: &anthropic.ToolTextEditor20250728Param{}},350{OfCodeExecutionTool20260120: &anthropic.CodeExecutionTool20260120Param{}},351},352```353354Also available: `WebFetchTool20260209Param`, `MemoryTool20250818Param`, `ToolSearchToolBm25_20251119Param`, `ToolSearchToolRegex20251119Param`. For the advisor tool, use `BetaAdvisorTool20260301Param` in the beta namespace.355356---357358## Stop Details359360When `StopReason` is `anthropic.StopReasonRefusal`, the response includes structured `StopDetails`:361362```go363if resp.StopReason == anthropic.StopReasonRefusal {364fmt.Println("Category:", resp.StopDetails.Category) // "cyber" | "bio" | ""365fmt.Println("Explanation:", resp.StopDetails.Explanation)366}367```368369---370371## PDF / Document Input372373`NewDocumentBlock` generic helper accepts any source type. `MediaType`/`Type` are auto-set.374375```go376b64 := base64.StdEncoding.EncodeToString(pdfBytes)377378msg := anthropic.NewUserMessage(379anthropic.NewDocumentBlock(anthropic.Base64PDFSourceParam{Data: b64}),380anthropic.NewTextBlock("Summarize this document"),381)382```383384Other sources: `URLPDFSourceParam{URL: "https://..."}`, `PlainTextSourceParam{Data: "..."}`.385386---387388## Files API (Beta)389390Under `client.Beta.Files`. Method is **`Upload`** (NOT `New`/`Create`), params struct is `BetaFileUploadParams`. The `File` field takes an `io.Reader`; use `anthropic.File()` to attach a filename + content-type for the multipart encoding.391392```go393f, _ := os.Open("./upload_me.txt")394defer f.Close()395396meta, err := client.Beta.Files.Upload(ctx, anthropic.BetaFileUploadParams{397File: anthropic.File(f, "upload_me.txt", "text/plain"),398Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14},399})400// meta.ID is the file_id to reference in subsequent message requests401```402403Other `Beta.Files` methods: `List`, `Delete`, `Download`, `GetMetadata`.404405---406407## Context Editing / Compaction (Beta)408409Use `Beta.Messages.New` with `ContextManagement` on `BetaMessageNewParams`. There is no `NewBetaAssistantMessage` — use `.ToParam()` for the round-trip.410411```go412params := anthropic.BetaMessageNewParams{413Model: anthropic.ModelClaudeOpus4_6, // also supported: ModelClaudeSonnet4_6414MaxTokens: 16000,415Betas: []anthropic.AnthropicBeta{"compact-2026-01-12"},416ContextManagement: anthropic.BetaContextManagementConfigParam{417Edits: []anthropic.BetaContextManagementConfigEditUnionParam{418{OfCompact20260112: &anthropic.BetaCompact20260112EditParam{}},419},420},421Messages: []anthropic.BetaMessageParam{ /* ... */ },422}423424resp, err := client.Beta.Messages.New(ctx, params)425if err != nil {426log.Fatal(err)427}428429// Round-trip: append response to history via .ToParam()430params.Messages = append(params.Messages, resp.ToParam())431432// Read compaction blocks from the response433for _, block := range resp.Content {434if c, ok := block.AsAny().(anthropic.BetaCompactionBlock); ok {435fmt.Println("compaction summary:", c.Content)436}437}438```439440Other edit types: `BetaClearToolUses20250919EditParam`, `BetaClearThinking20251015EditParam`.441