Back to all prompts
ClaudeCoding
Free

Claude API Go SDK

Go SDK for Claude API, providing tools for client initialization, model constants, and message requests. Works best with Claude.

P
Piebald-AI
4.8

The Prompt

<!-- name: 'Data: Claude API reference — Go' description: Go SDK reference ccVersion: 2.1.128 --> # Claude API — Go > **Note:** The Go SDK supports the Claude API and beta tool use with `BetaToolRunner`. Agent SDK is not yet available for Go. ## Installation ```bash go get github.com/anthropics/anthropic-sdk-go ``` ## Client Initialization ```go import ( "github.com/anthropics/anthropic-sdk-go" "github.com/anthropics/anthropic-sdk-go/option" ) // Default (uses ANTHROPIC_API_KEY env var) client := anthropic.NewClient() // Explicit API key client := anthropic.NewClient( option.WithAPIKey("your-api-key"), ) ``` --- ## Model Constants The Go SDK provides typed model constants: `anthropic.ModelClaudeOpus4_7`, `anthropic.ModelClaudeOpus4_6`, `anthropic.ModelClaudeSonnet4_6`, `anthropic.ModelClaudeHaiku4_5_20251001`. Use `ModelClaudeOpus4_7` unless the user specifies otherwise. --- ## Basic Message Request ```go response, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{ Model: anthropic.ModelClaudeOpus4_7, MaxTokens: 16000, Messages: []anthropic.MessageParam{ anthropic.NewUserMessage(anthropic.NewTextBlock("What is the capital of France?")), }, }) if err != nil { log.Fatal(err) } for _, block := range response.Content { switch variant := block.AsAny().(type) { case anthropic.TextBlock: fmt.Println(variant.Text) } } ``` --- ## Streaming ```go stream := client.Messages.NewStreaming(context.Background(), anthropic.MessageNewParams{ Model: anthropic.ModelClaudeOpus4_6, MaxTokens: 64000, Messages: []anthropic.MessageParam{ anthropic.NewUserMessage(anthropic.NewTextBlock("Write a haiku")), }, }) for stream.Next() { event := stream.Current() switch eventVariant := event.AsAny().(type) { case anthropic.ContentBlockDeltaEvent: switch deltaVariant := eventVariant.Delta.AsAny().(type) { case anthropic.TextDelta: fmt.Print(deltaVariant.Text) } } } if err := stream.Err(); err != nil { log.Fatal(err) } ``` **Accumulating the final message** (there is no `GetFinalMessage()` on the stream): ```go stream := client.Messages.NewStreaming(ctx, params) message := anthropic.Message{} for stream.Next() { message.Accumulate(stream.Current()) } if err := stream.Err(); err != nil { log.Fatal(err) } // message.Content now has the complete response ``` --- ## Tool Use ### Tool Runner (Beta — Recommended) **Beta:** The Go SDK provides `BetaToolRunner` for automatic tool use loops via the `toolrunner` package. ```go import ( "context" "fmt" "log" "github.com/anthropics/anthropic-sdk-go" "github.com/anthropics/anthropic-sdk-go/toolrunner" ) // Define tool input with jsonschema tags for automatic schema generation type GetWeatherInput struct { City string `json:"city" jsonschema:"required,description=The city name"` } // Create a tool with automatic schema generation from struct tags weatherTool, err := toolrunner.NewBetaToolFromJSONSchema( "get_weather", "Get current weather for a city", func(ctx context.Context, input GetWeatherInput) (anthropic.BetaToolResultBlockParamContentUnion, error) { return anthropic.BetaToolResultBlockParamContentUnion{ OfText: &anthropic.BetaTextBlockParam{ Text: fmt.Sprintf("The weather in %s is sunny, 72°F", input.City), }, }, nil }, ) if err != nil { log.Fatal(err) } // Create a tool runner that handles the conversation loop automatically runner := client.Beta.Messages.NewToolRunner( []anthropic.BetaTool{weatherTool}, anthropic.BetaToolRunnerParams{ BetaMessageNewParams: anthropic.BetaMessageNewParams{ Model: anthropic.ModelClaudeOpus4_6, MaxTokens: 16000, Messages: []anthropic.BetaMessageParam{ anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("What's the weather in Paris?")), }, }, MaxIterations: 5, }, ) // Run until Claude produces a final response message, err := runner.RunToCompletion(context.Background()) if err != nil { log.Fatal(err) } // RunToCompletion returns *BetaMessage; content is []BetaContentBlockUnion. // Narrow via AsAny() switch — note the Beta-namespace types (BetaTextBlock, // not TextBlock): for _, block := range message.Content { switch block := block.AsAny().(type) { case anthropic.BetaTextBlock: fmt.Println(block.Text) } } ``` **Key features of the Go tool runner:** - Automatic schema generation from Go structs via `jsonschema` tags - `RunToCompletion()` for simple one-shot usage - `All()` iterator for processing each message in the conversation - `NextMessage()` for step-by-step iteration - Streaming variant via `NewToolRunnerStreaming()` with `AllStreaming()` ### Manual Loop For 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. Derived from `anthropic-sdk-go/examples/tools/main.go`. ```go package main import ( "context" "encoding/json" "fmt" "log" "github.com/anthropics/anthropic-sdk-go" ) func main() { client := anthropic.NewClient() // 1. Define tools. ToolParam.InputSchema uses a map, no struct tags needed. addTool := anthropic.ToolParam{ Name: "add", Description: anthropic.String("Add two integers"), InputSchema: anthropic.ToolInputSchemaParam{ Properties: map[string]any{ "a": map[string]any{"type": "integer"}, "b": map[string]any{"type": "integer"}, }, }, } // ToolParam must be wrapped in ToolUnionParam for the Tools slice tools := []anthropic.ToolUnionParam{{OfTool: &addTool}} messages := []anthropic.MessageParam{ anthropic.NewUserMessage(anthropic.NewTextBlock("What is 2 + 3?")), } for { resp, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{ Model: anthropic.ModelClaudeSonnet4_6, MaxTokens: 16000, Messages: messages, Tools: tools, }) if err != nil { log.Fatal(err) } // 2. Append the assistant response to history BEFORE processing tool calls. // resp.ToParam() converts Message → MessageParam in one call. messages = append(messages, resp.ToParam()) // 3. Walk content blocks. ContentBlockUnion is a flattened struct; // use block.AsAny().(type) to switch on the actual variant. toolResults := []anthropic.ContentBlockParamUnion{} for _, block := range resp.Content { switch variant := block.AsAny().(type) { case anthropic.TextBlock: fmt.Println(variant.Text) case anthropic.ToolUseBlock: // 4. Parse the tool input. Use variant.JSON.Input.Raw() to get the // raw JSON — block.Input is json.RawMessage, not the parsed value. var in struct { A int `json:"a"` B int `json:"b"` } if err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &in); err != nil { log.Fatal(err) } result := fmt.Sprintf("%d", in.A+in.B) // 5. NewToolResultBlock(toolUseID, content, isError) builds the // ContentBlockParamUnion for you. block.ID is the tool_use_id. toolResults = append(toolResults, anthropic.NewToolResultBlock(block.ID, result, false)) } } // 6. Exit when Claude stops asking for tools if resp.StopReason != anthropic.StopReasonToolUse { break } // 7. Tool results go in a user message (variadic: all results in one turn) messages = append(messages, anthropic.NewUserMessage(toolResults...)) } } ``` **Key API surface:** | Symbol | Purpose | |---|---| | `resp.ToParam()` | Convert `Message` response → `MessageParam` for history | | `block.AsAny().(type)` | Type-switch on `ContentBlockUnion` variants | | `variant.JSON.Input.Raw()` | Raw JSON string of tool input (for `json.Unmarshal`) | | `anthropic.NewToolResultBlock(id, content, isError)` | Build `tool_result` block | | `anthropic.NewUserMessage(blocks...)` | Wrap tool results as a user turn | | `anthropic.StopReasonToolUse` | `StopReason` constant to check loop termination | | `anthropic.ToolUnionParam{OfTool: &t}` | Wrap `ToolParam` in the union for `Tools:` | --- ## Thinking Enable Claude's internal reasoning by setting `Thinking` in `MessageNewParams`. The response will contain `ThinkingBlock` content before the final `TextBlock`. **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. Derived from `anthropic-sdk-go/message.go` (`ThinkingConfigParamUnion`, `ThinkingConfigAdaptiveParam`). ```go // There is no ThinkingConfigParamOfAdaptive helper — construct the union // struct-literal directly and take the address of the variant. adaptive := anthropic.ThinkingConfigAdaptiveParam{} params := anthropic.MessageNewParams{ Model: anthropic.ModelClaudeSonnet4_6, MaxTokens: 16000, Thinking: anthropic.ThinkingConfigParamUnion{OfAdaptive: &adaptive}, Messages: []anthropic.MessageParam{ anthropic.NewUserMessage(anthropic.NewTextBlock("How many r's in strawberry?")), }, } resp, err := client.Messages.New(context.Background(), params) if err != nil { log.Fatal(err) } // ThinkingBlock(s) precede TextBlock in content for _, block := range resp.Content { switch b := block.AsAny().(type) { case anthropic.ThinkingBlock: fmt.Println("[thinking]", b.Thinking) case anthropic.TextBlock: fmt.Println(b.Text) } } ``` > **Deprecated:** `ThinkingConfigParamOfEnabled(budgetTokens)` (fixed-budget extended thinking) still works on Claude 4.6 but is deprecated. Use adaptive thinking above. To disable: `anthropic.ThinkingConfigParamUnion{OfDisabled: &anthropic.ThinkingConfigDisabledParam{}}`. --- ## Prompt Caching `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`. ```go System: []anthropic.TextBlockParam{{ Text: longSystemPrompt, CacheControl: anthropic.NewCacheControlEphemeralParam(), // default 5m TTL }}, ``` For 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. Verify hits via `resp.Usage.CacheCreationInputTokens` / `resp.Usage.CacheReadInputTokens`. --- ## Server-Side Tools Version-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. ```go Tools: []anthropic.ToolUnionParam{ {OfWebSearchTool20260209: &anthropic.WebSearchTool20260209Param{}}, {OfBashTool20250124: &anthropic.ToolBash20250124Param{}}, {OfTextEditor20250728: &anthropic.ToolTextEditor20250728Param{}}, {OfCodeExecutionTool20260120: &anthropic.CodeExecutionTool20260120Param{}}, }, ``` Also available: `WebFetchTool20260209Param`, `MemoryTool20250818Param`, `ToolSearchToolBm25_20251119Param`, `ToolSearchToolRegex20251119Param`. For the advisor tool, use `BetaAdvisorTool20260301Param` in the beta namespace. --- ## Stop Details When `StopReason` is `anthropic.StopReasonRefusal`, the response includes structured `StopDetails`: ```go if resp.StopReason == anthropic.StopReasonRefusal { fmt.Println("Category:", resp.StopDetails.Category) // "cyber" | "bio" | "" fmt.Println("Explanation:", resp.StopDetails.Explanation) } ``` --- ## PDF / Document Input `NewDocumentBlock` generic helper accepts any source type. `MediaType`/`Type` are auto-set. ```go b64 := base64.StdEncoding.EncodeToString(pdfBytes) msg := anthropic.NewUserMessage( anthropic.NewDocumentBlock(anthropic.Base64PDFSourceParam{Data: b64}), anthropic.NewTextBlock("Summarize this document"), ) ``` Other sources: `URLPDFSourceParam{URL: "https://..."}`, `PlainTextSourceParam{Data: "..."}`. --- ## Files API (Beta) Under `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. ```go f, _ := os.Open("./upload_me.txt") defer f.Close() meta, err := client.Beta.Files.Upload(ctx, anthropic.BetaFileUploadParams{ File: anthropic.File(f, "upload_me.txt", "text/plain"), Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14}, }) // meta.ID is the file_id to reference in subsequent message requests ``` Other `Beta.Files` methods: `List`, `Delete`, `Download`, `GetMetadata`. --- ## Context Editing / Compaction (Beta) Use `Beta.Messages.New` with `ContextManagement` on `BetaMessageNewParams`. There is no `NewBetaAssistantMessage` — use `.ToParam()` for the round-trip. ```go params := anthropic.BetaMessageNewParams{ Model: anthropic.ModelClaudeOpus4_6, // also supported: ModelClaudeSonnet4_6 MaxTokens: 16000, Betas: []anthropic.AnthropicBeta{"compact-2026-01-12"}, ContextManagement: anthropic.BetaContextManagementConfigParam{ Edits: []anthropic.BetaContextManagementConfigEditUnionParam{ {OfCompact20260112: &anthropic.BetaCompact20260112EditParam{}}, }, }, Messages: []anthropic.BetaMessageParam{ /* ... */ }, } resp, err := client.Beta.Messages.New(ctx, params) if err != nil { log.Fatal(err) } // Round-trip: append response to history via .ToParam() params.Messages = append(params.Messages, resp.ToParam()) // Read compaction blocks from the response for _, block := range resp.Content { if c, ok := block.AsAny().(anthropic.BetaCompactionBlock); ok { fmt.Println("compaction summary:", c.Content) } } ``` Other edit types: `BetaClearToolUses20250919EditParam`, `BetaClearThinking20251015EditParam`.
#claude#api#go#sdk#coding

Source: Piebald-AI/claude-code-system-prompts by Piebald-AI · License: MIT