docker-agent is available as a Go library. You can import it directly into your application to build, configure, and run AI agents programmatically — without the CLI or TUI.
Installation
Add the module to your project
go get github.com/docker/docker-agent
Import the packages you need
import (
" github.com/docker/docker-agent/pkg/agent "
" github.com/docker/docker-agent/pkg/runtime "
" github.com/docker/docker-agent/pkg/session "
" github.com/docker/docker-agent/pkg/team "
)
The module path is github.com/docker/docker-agent. All public packages live under pkg/.
Core packages
Package Purpose pkg/agentAgent creation and configuration pkg/runtimeAgent execution and event streaming pkg/sessionConversation state management pkg/teamMulti-agent team composition pkg/toolsTool interface and utilities pkg/tools/builtinBuilt-in tools (shell, filesystem, etc.) pkg/model/provider/*Model provider clients pkg/config/latestConfiguration types pkg/environmentEnvironment and secrets
Basic example
Create a simple agent, run it with a message, and print the response:
package main
import (
" context "
" fmt "
" log "
" os/signal "
" syscall "
" github.com/docker/docker-agent/pkg/agent "
" github.com/docker/docker-agent/pkg/config/latest "
" github.com/docker/docker-agent/pkg/environment "
" github.com/docker/docker-agent/pkg/model/provider/openai "
" github.com/docker/docker-agent/pkg/runtime "
" github.com/docker/docker-agent/pkg/session "
" github.com/docker/docker-agent/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 a model provider
llm , err := openai . NewClient (
ctx ,
& latest . ModelConfig {
Provider : "openai" ,
Model : "gpt-4o" ,
},
environment . NewDefaultProvider (),
)
if err != nil {
return err
}
// Create an agent
assistant := agent . New (
"root" ,
"You are a helpful assistant." ,
agent . WithModel ( llm ),
agent . WithDescription ( "A helpful assistant" ),
)
// Wrap in a team and create the runtime
t := team . New ( team . WithAgents ( assistant ))
rt , err := runtime . NewLocalRuntime ( t )
if err != nil {
return err
}
defer rt . Close ()
// Create a session with a user message
sess := session . New (
session . WithUserMessage ( "What is 2 + 2?" ),
)
// Run and collect messages
messages , err := rt . Run ( ctx , sess )
if err != nil {
return err
}
fmt . Println ( messages [ len ( messages ) - 1 ]. Message . Content )
return nil
}
Streaming responses
Use RunStream to process events as they arrive. This is useful when you want to print tokens progressively or react to tool calls in real time.
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 tokens 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 ( " \n Stream stopped" )
case * runtime . ErrorEvent :
return fmt . Errorf ( "stream error: %s " , e . Error )
}
}
return nil
}
Define your own tools by implementing a handler function and describing the input schema:
import (
" context "
" encoding/json "
" fmt "
" github.com/docker/docker-agent/pkg/tools "
)
type AddNumbersArgs struct {
A int `json:"a"`
B int `json:"b"`
}
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
}
return tools . ResultSuccess ( fmt . Sprintf ( " %d " , args . A + args . B )), nil
}
// Create the tool definition
addTool := tools . Tool {
Name : "add" ,
Category : "math" ,
Description : "Add two numbers together" ,
Parameters : tools . MustSchemaFor [ AddNumbersArgs ](),
Handler : addNumbers ,
}
// Attach the tool to an agent
calculator := agent . New (
"root" ,
"You are a calculator. Use the add tool for arithmetic." ,
agent . WithModel ( llm ),
agent . WithTools ( addTool ),
)
The pkg/tools/builtin package provides ready-made toolsets you can attach to any agent:
import (
" os "
" github.com/docker/docker-agent/pkg/config "
" github.com/docker/docker-agent/pkg/tools/builtin "
)
rtConfig := & config . RuntimeConfig {
Config : config . Config {
WorkingDir : "/path/to/workdir" ,
},
}
developer := agent . New (
"root" ,
"You are a developer assistant." ,
agent . WithModel ( llm ),
agent . WithToolSets (
builtin . NewShellTool ( os . Environ (), rtConfig , nil ), // Run shell commands
builtin . NewFilesystemTool ( rtConfig . Config . WorkingDir ), // Read/write files
builtin . NewThinkTool (), // Internal reasoning scratchpad
builtin . NewTodoTool (), // Task tracking
),
)
Multi-agent teams
Create hierarchical agents where a root agent delegates work to specialists:
import (
" github.com/docker/docker-agent/pkg/agent "
" github.com/docker/docker-agent/pkg/team "
" github.com/docker/docker-agent/pkg/tools/builtin "
)
func createTeam ( llm provider . Provider ) * team . Team {
researcher := agent . New (
"researcher" ,
"You research topics thoroughly." ,
agent . WithModel ( llm ),
agent . WithDescription ( "Research specialist" ),
)
coordinator := agent . New (
"root" ,
"You coordinate research tasks and delegate to specialists." ,
agent . WithModel ( llm ),
agent . WithDescription ( "Team coordinator" ),
agent . WithSubAgents ( researcher ),
agent . WithToolSets ( builtin . NewTransferTaskTool ()),
)
return team . New ( team . WithAgents ( coordinator , researcher ))
}
Model providers
Switch between providers by importing the appropriate package:
import (
" github.com/docker/docker-agent/pkg/model/provider/anthropic "
" github.com/docker/docker-agent/pkg/model/provider/gemini "
" github.com/docker/docker-agent/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
session.New accepts functional options to configure conversation behavior:
sess := session . New (
session . WithTitle ( "Code Review Task" ),
session . WithUserMessage ( "Review this code for bugs" ),
session . WithMaxIterations ( 20 ),
)
Runtime options
runtime.NewLocalRuntime accepts options for more advanced configurations:
rt , err := runtime . NewLocalRuntime (
t ,
runtime . WithSessionStore ( myStore ), // Persistent session storage
runtime . WithWorkingDir ( "/workspace" ), // Working directory for hooks
runtime . WithRetryOnRateLimit (), // Retry on HTTP 429 with backoff
runtime . WithTracer ( myTracer ), // OpenTelemetry tracing
)
Error handling
messages , err := rt . Run ( ctx , sess )
if err != nil {
switch {
case errors . Is ( err , context . Canceled ):
log . Println ( "Operation cancelled" )
return nil
case errors . Is ( err , context . DeadlineExceeded ):
log . Println ( "Operation timed out" )
return nil
default :
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 examples
The examples/golibrary directory contains working programs for each use case:
simple/ Basic agent with no tools — the minimal working example.
tool/ Custom tool implementation with schema generation.
stream/ Full streaming event loop with typed event handling.
multi/ Multi-agent team with coordinator and sub-agents.
builtintool/ Using the built-in filesystem, shell, think, and todo tools.