Documentation
¶
Overview ¶
Package anthropic is a minimal HTTP client for the Anthropic Messages API with tool-use support. Modeled on internal/pipeline/voyage_client.go — raw HTTP, no SDK, retry on 429/5xx with exponential backoff.
Used by internal/locagent for the LocAgent-style agent loop on top of our MCP graph primitives.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrAuthFailed wraps 401 / 403 responses from the Anthropic API. // Typical cause: ANTHROPIC_API_KEY missing, rotated, or scope-revoked. // Not retried — auth failures are deterministic until the key changes. ErrAuthFailed = errors.New("anthropic: authentication failed") // ErrRateLimitExhausted wraps 429 responses after all retry attempts // have been exhausted. Typical cause: high-volume batch run on a // rate-limited key. Caller should back off significantly or use a // different key tier. ErrRateLimitExhausted = errors.New("anthropic: rate limit exhausted after retries") // ErrServerError wraps 5xx responses after all retry attempts have // been exhausted. Typical cause: transient Anthropic-side issue. // Caller may retry after a longer pause. ErrServerError = errors.New("anthropic: server error after retries") // ErrTimeoutExhausted wraps connection / timeout errors after all // retry attempts. Typical cause: operator network issue, DNS, or // firewall. Caller should investigate environment, not retry. ErrTimeoutExhausted = errors.New("anthropic: timeout exhausted after retries") )
Functions ¶
func SanitizeModelID ¶
SanitizeModelID strips Claude Code session-notation suffixes from an inherited model id. Claude Code launchers pin ANTHROPIC_MODEL for the host session using bracket beta markers (e.g. "claude-sonnet-5[1m]" for the 1M-context variant); MCP servers spawned by that session inherit the env verbatim, and the raw string 404s against the Messages API (observed live 2026-07-04: not_found_error "model: claude-sonnet-5[1m]" broke every code_localize_agent call on the host). The base id before the bracket is the valid API model.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client wraps the Anthropic Messages API.
func NewClient ¶
func NewClient() *Client
NewClient returns a configured client. Returns nil if ANTHROPIC_API_KEY is not set, matching the VoyageClient nil-on-missing-key pattern so callers can degrade gracefully instead of crashing.
func (*Client) CreateMessage ¶
func (c *Client) CreateMessage(ctx context.Context, req MessagesRequest) (*MessagesResponse, error)
CreateMessage sends a request and returns the response, with retry on 429/5xx (4 attempts, exponential backoff).
type ContentBlock ¶
type ContentBlock struct {
Type string `json:"type"`
// type=text
Text string `json:"text,omitempty"`
// type=tool_use
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Input json.RawMessage `json:"input,omitempty"`
// type=tool_result
ToolUseID string `json:"tool_use_id,omitempty"`
IsError bool `json:"is_error,omitempty"`
ToolResultContent string `json:"content,omitempty"`
}
ContentBlock is one element of message content. Either Text, ToolUse, or ToolResult — at most one of these is non-zero in a given block.
Note on tool_result content: the Anthropic API expects `content` to be a string OR an array of content blocks (with type="text" or "image"). We use a string (the simplest encoding); callers should JSON-marshal any structured tool output and pass the resulting string.
type Message ¶
type Message struct {
Role string `json:"role"` // "user" | "assistant"
Content []ContentBlock `json:"content"`
}
Message is a single conversation turn.
type MessagesRequest ¶
type MessagesRequest struct {
Model string `json:"model"`
MaxTokens int `json:"max_tokens"`
System string `json:"system,omitempty"`
Messages []Message `json:"messages"`
Tools []Tool `json:"tools,omitempty"`
}
MessagesRequest is the request body.
type MessagesResponse ¶
type MessagesResponse struct {
ID string `json:"id"`
Type string `json:"type"`
Role string `json:"role"`
Model string `json:"model"`
StopReason string `json:"stop_reason"` // "end_turn", "tool_use", "max_tokens", ...
Content []ContentBlock `json:"content"`
Usage struct {
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
} `json:"usage"`
}
MessagesResponse is the response body.