stemedb/docs/references/go-adk/research.md
jordan 3cfaa1e1d3 feat: Complete Phase 1 (The Spine) - storage foundation
Phase 1 delivers the complete durability and storage layer:

- WAL with crash recovery: Append-only journal with BLAKE3 checksums,
  fsync guarantees, and proper seek-to-EOF on reopen
- Storage engine: sled-backed KVStore with scan_prefix for range queries
- Content-addressed storage: H:{hash}, V:{hash}, E:{hash} key patterns
- Ingestor: Background worker tailing WAL, writing to KV with 8-byte
  aligned record headers for rkyv zero-copy deserialization
- Comprehensive tests: 31 tests covering crash recovery, round-trips,
  and multi-cycle durability

New crates: stemedb-wal, stemedb-storage, stemedb-ingest

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 14:15:34 -07:00

16 KiB

Google ADK-Go: Complete reference for building AI agents in Go

Google's Agent Development Kit for Go (ADK-Go) enables developers to build sophisticated AI agents using Go's native concurrency, type safety, and performance characteristics. Released in November 2025 at version 0.2.0, ADK-Go brings Google's agent framework to the Go ecosystem, offering first-class support for Gemini models, multi-agent orchestration, and seamless Google Cloud deployment. The toolkit follows a code-first philosophy where agent logic, tools, and workflows are defined directly in Go code rather than configuration files.

Getting started with installation and setup

ADK-Go requires Go 1.24.4 or later and uses the module path google.golang.org/adk (not the GitHub path). Installation is straightforward:

go mod init example.com/my-agent
go get google.golang.org/adk

The minimal agent setup requires three components—a model, an agent configuration, and a launcher:

package main

import (
    "context"
    "log"
    "os"

    "google.golang.org/adk/agent/llmagent"
    "google.golang.org/adk/cmd/launcher/adk"
    "google.golang.org/adk/cmd/launcher/full"
    "google.golang.org/adk/model/gemini"
    "google.golang.org/adk/server/restapi/services"
    "google.golang.org/adk/tool"
    "google.golang.org/adk/tool/geminitool"
    "google.golang.org/genai"
)

func main() {
    ctx := context.Background()

    model, err := gemini.NewModel(ctx, "gemini-3-flash-preview", &genai.ClientConfig{
        APIKey: os.Getenv("GOOGLE_API_KEY"),
    })
    if err != nil {
        log.Fatalf("Failed to create model: %v", err)
    }

    agent, err := llmagent.New(llmagent.Config{
        Name:        "search_agent",
        Model:       model,
        Description: "An agent that searches the web for information.",
        Instruction: "You are a helpful assistant. Answer questions using web search.",
        Tools:       []tool.Tool{geminitool.GoogleSearch{}},
    })
    if err != nil {
        log.Fatalf("Failed to create agent: %v", err)
    }

    config := &adk.Config{
        AgentLoader: services.NewSingleAgentLoader(agent),
    }

    l := full.NewLauncher()
    if err := l.Execute(ctx, config, os.Args[1:]); err != nil {
        log.Fatalf("Run failed: %v\n\n%s", err, l.CommandLineSyntax())
    }
}

Running modes include console interaction (go run agent.go), web interface with API (go run agent.go web api webui), and production mode (go run agent.go web api a2a).

Repository architecture and package structure

The ADK-Go repository follows a modular structure designed for extensibility:

Package Purpose
agent/ Core agent interfaces and implementations
agent/llmagent/ LLM-powered agents with reasoning capabilities
agent/workflowagents/ Sequential, Parallel, and Loop agent orchestrators
model/gemini/ Gemini model implementation
tool/ Tool framework and interfaces
tool/geminitool/ Built-in Google Search and Code Execution tools
tool/mcptool/ Model Context Protocol adapter
session/ Session management and state tracking
memory/ Long-term memory and knowledge storage
server/restapi/ REST API handlers, routers, and services
cmd/launcher/ Launcher configurations (full, prod, console, web)

Core types and interfaces define the API

The foundation of ADK-Go rests on several key interfaces. The Agent interface defines what every agent must implement:

type Agent interface {
    Name() string
    Description() string
    Run(InvocationContext) iter.Seq2[*session.Event, error]
    SubAgents() []Agent
}

The InvocationContext provides runtime access to agent state and services:

type InvocationContext interface {
    context.Context
    Agent() Agent
    Artifacts() Artifacts
    Memory() Memory
    Session() session.Session
    InvocationID() string
    Branch() string
    UserContent() *genai.Content
    RunConfig() *RunConfig
    EndInvocation()
    Ended() bool
}

The LLM interface abstracts model interactions for provider flexibility:

type LLM interface {
    Name() string
    GenerateContent(ctx context.Context, req *LLMRequest, stream bool) iter.Seq2[*LLMResponse, error]
}

Agent configuration uses the llmagent.Config struct with fields including Name (required identifier), Model (LLM instance), Description (used for routing decisions), Instruction (system prompt), Tools (available capabilities), SubAgents (child agents for delegation), and OutputKey (state storage key).

Tool ecosystem spans built-in, custom, and MCP integrations

ADK-Go provides built-in tools via the geminitool package:

import "google.golang.org/adk/tool/geminitool"

Tools: []tool.Tool{
    geminitool.GoogleSearch{},   // Web search via Google
    geminitool.CodeExecution{},  // Code execution sandbox
}

Custom function tools use struct tags for schema generation:

import "google.golang.org/adk/tool/functiontool"

type GetWeatherParams struct {
    Location string `json:"location" jsonschema:"The city and state, e.g., San Francisco, CA"`
    Unit     string `json:"unit,omitempty" jsonschema:"Temperature unit: celsius or fahrenheit"`
}

type GetWeatherResult struct {
    Temperature float64 `json:"temperature"`
    Conditions  string  `json:"conditions"`
}

func getWeather(ctx tool.Context, input GetWeatherParams) GetWeatherResult {
    // Implementation here
    return GetWeatherResult{Temperature: 72.5, Conditions: "sunny"}
}

weatherTool, err := functiontool.New(
    functiontool.Config{
        Name:        "get_weather",
        Description: "Retrieves current weather for a location",
    },
    getWeather,
)

Fields without omitempty are treated as required parameters. The jsonschema tag provides descriptions for the LLM.

MCP (Model Context Protocol) support enables integration with external tool servers:

import "google.golang.org/adk/tool/mcptool"

// Connect to stdio-based MCP server
params := mcptool.StdioServerParams{
    Command: "npx",
    Args:    []string{"-y", "@modelcontextprotocol/server-filesystem"},
}
tools, closer, err := mcptool.FromServer(ctx, params)
defer closer.Close()

// Or connect via SSE/HTTP
sseParams := mcptool.SseServerParams{
    URL:            "http://localhost:8090/sse",
    Timeout:        5.0,
    SseReadTimeout: 300.0,
}

The MCP Toolbox for Databases provides out-of-the-box connectors for 30+ databases including BigQuery, AlloyDB, PostgreSQL, MySQL, Cloud SQL, and Redis.

Multi-agent orchestration uses workflow agents

ADK-Go provides three workflow agents for deterministic orchestration patterns:

SequentialAgent executes sub-agents in strict order, useful for pipelines where outputs feed into subsequent steps:

import "google.golang.org/adk/agent/sequentialagent"

pipeline, err := sequentialagent.New(sequentialagent.Config{
    AgentConfig: agent.Config{
        Name:        "DataPipeline",
        Description: "Three-step data processing workflow",
        SubAgents:   []agent.Agent{fetcher, transformer, validator},
    },
})

ParallelAgent executes sub-agents concurrently, with each operating in independent branches without shared conversation history:

import "google.golang.org/adk/agent/parallelagent"

parallel, err := parallelagent.New(parallelagent.Config{
    AgentConfig: agent.Config{
        Name:        "ParallelResearch",
        SubAgents:   []agent.Agent{webSearcher, docAnalyzer, factChecker},
    },
})

LoopAgent repeatedly executes sub-agents until a maximum iteration count or termination condition is met:

import "google.golang.org/adk/agent/loopagent"

refiner, err := loopagent.New(loopagent.Config{
    AgentConfig: agent.Config{
        Name:      "IterativeRefiner",
        SubAgents: []agent.Agent{writer, critic},
    },
    MaxIterations: 5,
})

Agent communication occurs through shared session state using the OutputKey configuration:

// Agent 1 writes output to state
agent1, _ := llmagent.New(llmagent.Config{
    Name:      "Fetcher",
    OutputKey: "fetched_data",  // Saves to state["fetched_data"]
})

// Agent 2 reads from state via instruction templating
agent2, _ := llmagent.New(llmagent.Config{
    Instruction: "Process the data from {fetched_data}",
})

Model integration centers on Gemini with extensibility

The primary model integration uses Gemini through the model/gemini package:

import (
    "google.golang.org/adk/model/gemini"
    "google.golang.org/genai"
)

// API Key authentication (AI Studio)
model, err := gemini.NewModel(ctx, "gemini-3-flash-preview", &genai.ClientConfig{
    APIKey: os.Getenv("GOOGLE_API_KEY"),
})

// Vertex AI authentication (Application Default Credentials)
model, err := gemini.NewModel(ctx, "gemini-3-flash-preview", &genai.ClientConfig{})

Supported models include gemini-3-flash-preview, gemini-2.0-flash, gemini-1.5-pro, and preview models like gemini-3-pro-preview. The architecture supports additional providers through the LLM interface, with community implementations available for other models.

Streaming responses use Go 1.23+ iterators (iter.Seq2) for real-time event processing:

for event, err := range runner.Run(ctx, userID, sessionID, userMsg, agent.RunConfig{
    StreamingMode: agent.StreamingModeSSE,
}) {
    if event.Partial {
        for _, p := range event.LLMResponse.Content.Parts {
            fmt.Print(p.Text)  // Stream partial content
        }
    }
}

Session and state management provides persistence options

ADK-Go supports three tiers of state management:

Session State manages per-conversation working memory:

import "google.golang.org/adk/session"

// In-memory for development
sessionService := session.InMemoryService()

// Create session
sess, err := sessionService.Create(ctx, &session.CreateRequest{
    AppName: "my_app",
    UserID:  "user123",
})

// Access state within agent Run method
func (a *MyAgent) Run(ctx agent.InvocationContext) iter.Seq2[*session.Event, error] {
    value := ctx.Session().State().Get("key")
    ctx.Session().State().Set("key", "value")
}

State prefixes control scope and persistence:

  • No prefix: App-scoped persistent state
  • user: prefix: User-scoped persistent state
  • app: prefix: Application-wide persistent state
  • temp: prefix: Temporary, per-invocation only

Memory services provide long-term knowledge storage with vector search:

import "google.golang.org/adk/memory"

// Development: In-memory
memoryService := memory.InMemoryService()

// Production: Vertex AI Memory Bank
// Provides semantic search across archived sessions

Database-backed sessions support PostgreSQL, MySQL, and SQLite for production persistence with automatic table creation.

Deployment spans local development to Google Cloud

Cloud Run deployment

ADK-Go includes a CLI tool for streamlined Cloud Run deployment:

go build ./cmd/adkgo

./adkgo deploy cloudrun \
  -p $GOOGLE_CLOUD_PROJECT \
  -r us-central1 \
  -s my-agent-service \
  -e ./main.go \
  --a2a --api --webui

The deployment process compiles the Go code to a statically linked Linux binary, auto-generates a Dockerfile, builds the container image, and deploys to Cloud Run with a local proxy for secure connections.

Vertex AI Agent Engine

For fully managed deployment, Agent Engine provides auto-scaling, managed sessions via VertexAiSessionService, and direct Vertex AI SDK integration.

Container configuration

Manual Docker deployment uses this pattern:

FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o agent main.go

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/agent .
EXPOSE 8080
CMD ["./agent", "web", "api", "a2a"]

A2A (Agent-to-Agent) Protocol

ADK-Go provides native support for the A2A protocol enabling secure multi-agent communication:

  • Agent Cards expose capabilities via /.well-known/agent-card.json
  • Secure delegation between agents without shared memory or tools
  • Signed security cards for enterprise identity verification
  • HTTP and gRPC transports for flexible connectivity

Testing and evaluation capabilities

Development UI provides interactive testing at http://localhost:8080:

go run agent.go web api webui

Features include chat interface, trace inspection with Event/Request/Response/Graph views, and session management.

HTTP Record/Replay (internal/httprr) enables deterministic testing of LLM interactions by recording and replaying HTTP exchanges.

Evaluation framework supports trajectory evaluation (steps and tools chosen) and final response evaluation (relevance and correctness) through both the CLI (adk eval) and programmatic integration.

Best practices for production deployments

Security hardening requires careful attention:

  • Use Google Cloud Secret Manager for API keys—never hardcode credentials
  • Implement before_model_callback to intercept and block forbidden topics
  • Use before_tool_callback to validate tool arguments before execution
  • Deploy with --no-allow-unauthenticated for private services
  • Sign A2A Agent Cards for identity verification

Error handling patterns include wrapping callbacks in error handlers, implementing timeouts for external API calls, and designing idempotent callbacks for external side effects.

Performance optimization leverages Go's strengths:

  • Use ParallelAgent for concurrent independent tasks
  • Filter available tools with tool_filter to prevent model overwhelm
  • Use compile-time type checking to catch errors early
  • Deploy to Cloud Run with appropriate memory (4Gi recommended) and CPU (2+) allocations

How ADK-Go differs from Python and Java versions

Aspect Go Python Java
Version v0.2.0 v1.19.0 v0.3.0
Async Pattern iter.Seq2[*Event, error] iterator AsyncGenerator[Event, None] Flowable<Event> (RxJava)
Schema Definition json + jsonschema struct tags Type hints + docstrings @Schema annotations
Concurrency Goroutines and channels async/await RxJava Flowables
Sample Agents 1 (llm-auditor) 25+ 2
Third-party Tools Limited LangChain integration Limited

Go's advantages include native concurrency for parallel agent interactions, compile-time type safety for robust error prevention, efficient memory management for resource-constrained deployments, and strong cloud-native support optimized for Cloud Run and containerized environments.

Enterprise adoption and ecosystem

Major companies using ADK in production include Renault Group, Box, SAP (via Joule AI assistant), Zoom, and Revionics. Google products powered by ADK include Agentspace and Customer Engagement Suite.

The community ecosystem spans the main repository (795+ stars), the samples repository with cross-language examples, and the Awesome ADK Agents collection with 80+ production-ready agents.

Conclusion

ADK-Go represents Google's commitment to bringing AI agent development to the Go ecosystem with a focus on performance, type safety, and cloud-native deployment. The framework excels in scenarios requiring high-throughput concurrent agent execution, strongly-typed tool definitions, and seamless Google Cloud integration. While the Python ADK offers broader model support and a larger example library, ADK-Go provides idiomatic patterns that align with Go's philosophy of simplicity and efficiency. For teams already invested in Go infrastructure or requiring the performance characteristics Go provides, ADK-Go offers a production-ready path to building sophisticated AI agents with full access to Gemini's capabilities and the broader Google Cloud ecosystem.