hieblmi/claude-agent-sdk-go

Go SDK for Claude Code – build AI agents with tool use, MCP integration, and streaming

★ 0Forks 0GitHub ↗Compare

README

claude-agent-sdk-go

License: MIT

A pure Go SDK for Claude's agentic capabilities.

Overview

claude-agent-sdk-go provides a native Go interface to Claude Code by managing the CLI as a subprocess. It communicates via line-delimited JSON over stdin/stdout, giving you access to Claude's tool use, extended thinking, session management, and hook system.

flowchart TB
    subgraph SDK[Go SDK]
        Client --> Protocol --> Transport
        MCP[SDK MCP] <-.->|tool calls| Protocol
    end
    Transport <-->|stream-json| CLI[Claude CLI]
    CLI <--> API[Claude API]
Loading

When you call Query() or Stream(), the SDK spawns the CLI, sends your prompt, and yields messages as they arrive. For MCP tools, the flow includes bidirectional control messages:

sequenceDiagram
    participant App as Go App
    participant CLI as Claude CLI
    participant API as Claude API

    App->>CLI: prompt (stdin)
    CLI->>API: API request
    API-->>CLI: response stream
    CLI-->>App: messages (stdout)
    CLI->>App: mcp_message (tool call)
    App-->>CLI: mcp_response
    CLI-->>App: result
Loading

Installation

go get github.com/roasbeef/claude-agent-sdk-go

Requirements:

  • Go 1.23+ (for iter.Seq)
  • Claude Code CLI: npm install -g @anthropic-ai/claude-code
  • ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN in your environment

Quick Start

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/roasbeef/claude-agent-sdk-go"
)

func main() {
    client, err := claudeagent.NewClient(
        claudeagent.WithSystemPrompt("You are a helpful assistant."),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    ctx := context.Background()
    for msg := range client.Query(ctx, "What is the capital of France?") {
        switch m := msg.(type) {
        case claudeagent.AssistantMessage:
            fmt.Println(m.ContentText())
        case claudeagent.ResultMessage:
            fmt.Printf("Cost: $%.4f\n", m.TotalCostUSD)
        }
    }
}

Streaming

For multi-turn conversations:

stream, _ := client.Stream(ctx)
defer stream.Close()

stream.Send(ctx, "Let's plan a trip to Japan.")

for msg := range stream.Messages() {
    if m, ok := msg.(claudeagent.AssistantMessage); ok {
        fmt.Println(m.ContentText())
    }
}

// Continue the conversation
stream.Send(ctx, "What about Kyoto?")

Configuration

client, _ := claudeagent.NewClient(
    claudeagent.WithModel("claude-sonnet-4-5-20250929"),
    claudeagent.WithSystemPrompt("You are an expert Go developer."),
    claudeagent.WithPermissionMode(claudeagent.PermissionModeAcceptEdits),
    claudeagent.WithMaxTurns(20),
)

Custom Tools (MCP)

Define tools that Claude can use during conversations:

type AddArgs struct {
    A int `json:"a"`
    B int `json:"b"`
}

server := claudeagent.CreateMcpServer(claudeagent.McpServerOptions{
    Name: "calculator",
    Tools: []claudeagent.ToolRegistrar{
        claudeagent.Tool("add", "Add two numbers",
            func(ctx context.Context, args AddArgs) (claudeagent.ToolResult, error) {
                return claudeagent.TextResult(fmt.Sprintf("%d", args.A+args.B)), nil
            },
        ),
    },
})

client, _ := claudeagent.NewClient(
    claudeagent.WithMcpServer("calculator", server),
)

See MCP Tools for typed responses, binary servers, and more.

Ralph Wiggum Loop

For complex iterative tasks, use the Ralph Wiggum loop. Claude works on a task repeatedly, seeing its previous work each iteration, until it outputs a completion signal:

loop := claudeagent.NewRalphLoop(claudeagent.RalphConfig{
    Task:              "Implement a Redis cache layer with tests",
    CompletionPromise: "TASK COMPLETE",
    MaxIterations:     10,
})

for iter := range loop.Run(ctx, claudeagent.WithModel("claude-sonnet-4-5-20250929")) {
    fmt.Printf("Iteration %d\n", iter.Number)
    if iter.Complete {
        fmt.Println("Task completed!")
        break
    }
}

fmt.Printf("Total cost: $%.4f\n", loop.TotalCost())

The loop intercepts session exit via a Stop hook and reinjects the task prompt if the completion promise (<promise>TASK COMPLETE</promise>) hasn't been detected. See Ralph Loop for details.

Documentation

For detailed guides and examples, see docs/examples/:

  • MCP Tools - Integrate custom tools via Model Context Protocol
  • Hooks - Intercept and modify Claude's execution
  • Subagents - Define and monitor specialized agents
  • Questions - Handle interactive questions from Claude
  • Sessions - Persist and resume conversations
  • Permissions - Control what Claude can do
  • Streaming - Real-time response handling
  • Skills - Filesystem-based capability extensions
  • Ralph Loop - Iterative task completion pattern
  • Task Lists - Multi-agent task coordination system

For internal architecture, see DESIGN.md. For CLI protocol details (how this and the official Typescript SDK actually work), see cli-protocol.md.

Testing

go test ./...

License

MIT

Contributors

Roasbeefjbrill

Issues