Go SDK
Use cagent as a Go library to embed AI agents in your applications.
Overview
cagent can be used as a Go library, allowing you to build AI agents directly into your Go applications. This gives you full programmatic control over agent creation, tool integration, and execution.
ℹ️ Import Path
import "github.com/docker/cagent/pkg/..."
Core Packages
| Package | Purpose |
|---|---|
pkg/agent |
Agent creation and configuration |
pkg/runtime |
Agent execution and event streaming |
pkg/session |
Conversation state management |
pkg/team |
Multi-agent team composition |
pkg/tools |
Tool interface and utilities |
pkg/tools/builtin |
Built-in tools (shell, filesystem, etc.) |
pkg/model/provider/* |
Model provider clients |
pkg/config/latest |
Configuration types |
pkg/environment |
Environment and secrets |
Basic Example
Create a simple agent and run it:
package main
import (
"context"
"fmt"
"log"
"os/signal"
"syscall"
"github.com/docker/cagent/pkg/agent"
"github.com/docker/cagent/pkg/config/latest"
"github.com/docker/cagent/pkg/environment"
"github.com/docker/cagent/pkg/model/provider/openai"
"github.com/docker/cagent/pkg/runtime"
"github.com/docker/cagent/pkg/session"
"github.com/docker/cagent/pkg/team"
)
func main() {
ctx, cancel := signal.NotifyContext(context.Background(),
syscall.SIGINT, syscall.SIGTERM)
defer cancel()
if err := run(ctx); err != nil {
log.Fatal(err)
}
}
func run(ctx context.Context) error {
// Create model provider
llm, err := openai.NewClient(
ctx,
&latest.ModelConfig{
Provider: "openai",
Model: "gpt-4o",
},
environment.NewDefaultProvider(),
)
if err != nil {
return err
}
// Create agent
assistant := agent.New(
"root",
"You are a helpful assistant.",
agent.WithModel(llm),
agent.WithDescription("A helpful assistant"),
)
// Create team and runtime
t := team.New(team.WithAgents(assistant))
rt, err := runtime.New(t)
if err != nil {
return err
}
// Run with a user message
sess := session.New(
session.WithUserMessage("What is 2 + 2?"),
)
messages, err := rt.Run(ctx, sess)
if err != nil {
return err
}
// Print the response
fmt.Println(messages[len(messages)-1].Message.Content)
return nil
}
Custom Tools
Define custom tools for your agent:
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/docker/cagent/pkg/tools"
)
// Define the tool's input schema
type AddNumbersArgs struct {
A int `json:"a"`
B int `json:"b"`
}
// Implement the tool handler
func addNumbers(_ context.Context, toolCall tools.ToolCall) (*tools.ToolCallResult, error) {
var args AddNumbersArgs
if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args); err != nil {
return nil, err
}
result := args.A + args.B
return tools.ResultSuccess(fmt.Sprintf("%d", result)), nil
}
func main() {
// Create the tool definition
addTool := tools.Tool{
Name: "add",
Category: "math",
Description: "Add two numbers together",
Parameters: tools.MustSchemaFor[AddNumbersArgs](),
Handler: addNumbers,
}
// Use with an agent
calculator := agent.New(
"root",
"You are a calculator. Use the add tool for arithmetic.",
agent.WithModel(llm),
agent.WithTools(addTool),
)
// ...
}
Streaming Responses
Process events as they happen:
func runStreaming(ctx context.Context, rt runtime.Runtime, sess *session.Session) error {
events := rt.RunStream(ctx, sess)
for event := range events {
switch e := event.(type) {
case *runtime.StreamStartedEvent:
fmt.Println("Stream started")
case *runtime.AgentChoiceEvent:
// Print response chunks as they arrive
fmt.Print(e.Content)
case *runtime.ToolCallEvent:
fmt.Printf("\n[Tool call: %s]\n", e.ToolCall.Function.Name)
case *runtime.ToolCallConfirmationEvent:
// Auto-approve tool calls
rt.Resume(ctx, runtime.ResumeRequest{
Type: runtime.ResumeTypeApproveSession,
})
case *runtime.ToolCallResponseEvent:
fmt.Printf("[Tool response: %s]\n", e.Response)
case *runtime.StreamStoppedEvent:
fmt.Println("\nStream stopped")
case *runtime.ErrorEvent:
return fmt.Errorf("error: %s", e.Error)
}
}
return nil
}
Multi-Agent Teams
Create agents that delegate to sub-agents:
package main
import (
"github.com/docker/cagent/pkg/agent"
"github.com/docker/cagent/pkg/team"
"github.com/docker/cagent/pkg/tools/builtin"
)
func createTeam(llm provider.Provider) *team.Team {
// Create a child agent
researcher := agent.New(
"researcher",
"You research topics thoroughly.",
agent.WithModel(llm),
agent.WithDescription("Research specialist"),
)
// Create root agent with sub-agents
coordinator := agent.New(
"root",
"You coordinate research tasks.",
agent.WithModel(llm),
agent.WithDescription("Team coordinator"),
agent.WithSubAgents(researcher),
agent.WithToolSets(builtin.NewTransferTaskTool()),
)
return team.New(team.WithAgents(coordinator, researcher))
}
Built-in Tools
Use cagent’s built-in tools:
import (
"github.com/docker/cagent/pkg/config"
"github.com/docker/cagent/pkg/tools/builtin"
)
func createAgentWithBuiltinTools(llm provider.Provider) *agent.Agent {
// Runtime config for tools that need it
rtConfig := &config.RuntimeConfig{
Config: config.Config{
WorkingDir: "/path/to/workdir",
},
}
return agent.New(
"root",
"You are a developer assistant.",
agent.WithModel(llm),
agent.WithToolSets(
// Shell tool for running commands
builtin.NewShellTool(os.Environ(), rtConfig, nil),
// Filesystem tools
builtin.NewFilesystemTool(rtConfig.Config.WorkingDir),
// Think tool for reasoning
builtin.NewThinkTool(),
// Todo tool for task tracking
builtin.NewTodoTool(),
),
)
}
Using Different Providers
import (
"github.com/docker/cagent/pkg/model/provider/anthropic"
"github.com/docker/cagent/pkg/model/provider/gemini"
"github.com/docker/cagent/pkg/model/provider/openai"
)
// OpenAI
openaiClient, _ := openai.NewClient(ctx, &latest.ModelConfig{
Provider: "openai",
Model: "gpt-4o",
}, env)
// Anthropic
anthropicClient, _ := anthropic.NewClient(ctx, &latest.ModelConfig{
Provider: "anthropic",
Model: "claude-sonnet-4-0",
}, env)
// Google Gemini
geminiClient, _ := gemini.NewClient(ctx, &latest.ModelConfig{
Provider: "google",
Model: "gemini-2.5-flash",
}, env)
Session Options
import "github.com/docker/cagent/pkg/session"
sess := session.New(
// Set a title for the session
session.WithTitle("Code Review Task"),
// Add user message
session.WithUserMessage("Review this code for bugs"),
// Limit iterations
session.WithMaxIterations(20),
)
Error Handling
messages, err := rt.Run(ctx, sess)
if err != nil {
if errors.Is(err, context.Canceled) {
// User cancelled
log.Println("Operation cancelled")
return nil
}
if errors.Is(err, context.DeadlineExceeded) {
// Timeout
log.Println("Operation timed out")
return nil
}
// Other error
return fmt.Errorf("runtime error: %w", err)
}
// Check for errors in the event stream
for event := range rt.RunStream(ctx, sess) {
if errEvent, ok := event.(*runtime.ErrorEvent); ok {
return fmt.Errorf("stream error: %s", errEvent.Error)
}
}
Complete Example
See the examples/golibrary directory for complete working examples:
simple/— Basic agent with no toolstool/— Custom tool implementationstream/— Streaming event handlingmulti/— Multi-agent with sub-agentsbuiltintool/— Using built-in tools