Anthropic SDK for Go: Install, First Request, Streaming and Errors (2026)
The Anthropic SDK for Go is the official Go client for the Claude API, published at github.com/anthropics/anthropic-sdk-go. It wraps the Messages API with typed request and response structs, handles retries and streaming, and lets you point requests at any compatible base URL. This guide covers installation, a first request, streaming, error handling and the client options that matter in production.
What the Anthropic SDK for Go gives you
Calling the Claude API from Go with net/http works, but the SDK saves you from re-implementing the parts that are easy to get wrong:
- Typed parameters and responses for the Messages API, so a misspelled field fails at compile time instead of returning a 400.
- Automatic retries on connection errors and retryable status codes such as 429 and 5xx, with backoff.
- Streaming helpers that read server-sent events and can accumulate them into a complete message.
- Client options for the API key, base URL, timeouts and retry count.
If you work in other languages, the same concepts appear in the Anthropic SDK for Python and the Anthropic SDK for TypeScript.
Install the Anthropic SDK for Go
Inside a Go module, add the package:
go get github.com/anthropics/anthropic-sdk-goThe SDK follows semantic versioning. Check the repository's releases before upgrading across a major version, because type names and helpers can change between majors. Pin the version in go.mod for production services.
First request with the Go client
By default the client reads the ANTHROPIC_API_KEY environment variable, so the minimal program needs no explicit key:
package main
import (
"context"
"fmt"
"log"
"github.com/anthropics/anthropic-sdk-go"
)
func main() {
client := anthropic.NewClient() // reads ANTHROPIC_API_KEY
msg, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
Model: "claude-sonnet-5-5", // replace with the model you use
MaxTokens: 1024,
Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock("Explain Go channels in two sentences.")),
},
})
if err != nil {
log.Fatal(err)
}
for _, block := range msg.Content {
if block.Type == "text" {
fmt.Println(block.Text)
}
}
}Three things to note:
MaxTokensis required. It caps the length of the reply, not the size of the prompt.- The response
Contentis a list of blocks. Text is the common case, but tool calls arrive as separate blocks, so check the block type instead of assuming the first block is text. msg.Usagereports input and output tokens, which is what billing is based on. Log it from day one.
Streaming responses
For chat interfaces and long outputs, stream the response so users see text as it is generated:
stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
Model: "claude-sonnet-5-5",
MaxTokens: 1024,
Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock("Write a haiku about latency.")),
},
})
message := anthropic.Message{}
for stream.Next() {
event := stream.Current()
if err := message.Accumulate(event); err != nil {
log.Fatal(err)
}
// Inspect event here to print text deltas as they arrive.
}
if err := stream.Err(); err != nil {
log.Fatal(err)
}
// message now holds the complete response, including usage.The pattern is always Next() → Current() → check Err() after the loop. Forgetting the final Err() check is the most common streaming bug: the loop ends quietly on a dropped connection and the program treats a partial answer as complete. For how the event sequence works at the HTTP level, see our guide to Claude API streaming.
Handling errors, retries and timeouts
API errors are returned as *anthropic.Error, which carries the HTTP status code:
import "errors"
_, err := client.Messages.New(ctx, params)
var apiErr *anthropic.Error
if errors.As(err, &apiErr) {
log.Printf("status %d", apiErr.StatusCode)
}How to treat the common statuses:
|
Status |
Meaning |
What to do |
|---|---|---|
|
400 |
Invalid request (missing field, bad parameter) |
Fix the request; retrying will not help |
|
401 / 403 |
Key missing, invalid or not permitted |
Check which key the process actually loaded |
|
429 |
Rate limit reached |
The SDK retries; if it persists, reduce concurrency or raise limits |
|
500 / 529 |
Server error or overloaded |
Retried automatically; add your own fallback for user-facing paths |
The client retries retryable errors a small number of times by default. Adjust retries and timeouts with options rather than wrapping every call yourself:
import (
"time"
"github.com/anthropics/anthropic-sdk-go/option"
)
client := anthropic.NewClient(
option.WithMaxRetries(4),
option.WithRequestTimeout(60*time.Second),
)Rate limits are set per organisation and model, so they are worth understanding before you add concurrency. Our overview of Anthropic API rate limits explains how they are measured.
Client options: API key and base URL
Two options cover most configuration needs:
option.WithAPIKey("...")sets the key explicitly instead of reading the environment. Load it from your secret store; never hard-code it.option.WithBaseURL("https://...")sends requests to a different endpoint, such as an internal gateway, a regional relay or a compatible proxy. The SDK appends the usual API paths, so pass the base URL only.
client := anthropic.NewClient(
option.WithAPIKey(os.Getenv("MY_CLAUDE_KEY")),
option.WithBaseURL(os.Getenv("CLAUDE_BASE_URL")),
)When you change the base URL, verify that the endpoint supports the features you rely on, such as streaming and tool use, before switching production traffic. The Claude API proxy guide lists what to check.
FAQ
Is there an official Anthropic SDK for Go?
Yes. Anthropic maintains github.com/anthropics/anthropic-sdk-go, which covers the Messages API, streaming, tool use and client configuration. Install it with go get inside a Go module.
How do I set the API key in the Go SDK?
By default the client reads ANTHROPIC_API_KEY from the environment. To set it explicitly, pass option.WithAPIKey(...) to anthropic.NewClient, loading the value from a secret store.
Can the Go SDK use a custom endpoint?
Yes. Pass option.WithBaseURL(...) when creating the client. This is how you route through an internal gateway or a compatible relay without changing the rest of your code.
Does the Anthropic Go SDK retry failed requests?
Yes. It retries connection errors and retryable statuses such as 429 and 5xx a few times with backoff. Change the count with option.WithMaxRetries and set a per-request limit with option.WithRequestTimeout.
The short version
Install github.com/anthropics/anthropic-sdk-go, create a client that reads ANTHROPIC_API_KEY, and call client.Messages.New with a model, MaxTokens and messages. Use NewStreaming with a final Err() check for streamed output, inspect *anthropic.Error for status codes, and configure retries, timeouts and base URL through client options.