ADK Go Agents (2.0)
ADK Go Agents (2.0)
Thesis
Google’s Agent Development Kit (ADK) for Go is a code-first toolkit for building, evaluating, and deploying AI agents — single LLM agents, multi-agent trees, and (in 2.0) graph-based workflows. The X post that sparked this chapter announced ADK Go 1.0 (31 March 2026): OpenTelemetry, plugins, human-in-the-loop tool confirmation, YAML agent configs. By the time you read this, ADK Go 2.0 is GA (announced 30 June 2026 on adk.dev/2.0) and the import path is google.golang.org/adk/v2.
Write new agents against 2.x. Treat 1.0 material as history and as a migration checklist. This chapter uses ADK Go v2.6.0 (current on the module proxy as of 2026-10-16) and Go 1.27.1.
Mental model
ADK Go 1.x ADK Go 2.x
────────── ──────────
google.golang.org/adk google.golang.org/adk/v2
hierarchical Agent.Run Workflow Graph: Agents/Tools as nodes
Sequential/Parallel/Loop helpers graph + dynamic + collaborative workflows
session.NewEvent(id) session.NewEvent(ctx, id)
custom Run overrides BeforeAgent / AfterAgent callbacks
| Fact | Consequence |
|---|---|
Module path embeds /v2 |
go get google.golang.org/adk/v2 — not a tag on the old path |
| Go 1.25+ required for 2.0 | Older toolchains fail module resolution |
| Agents are graph nodes | Bypassing the runner (manual session.events.append, old Run overrides) breaks routing and retries |
| HITL / retries are framework-owned | Broad except-style swallowing in tools hides failures from RetryConfig |
| X sparked on 1.0 | Features below are written for 2.0; 1.0 notes are called out |
Install
# Requires Go 1.25+ (this lab: go1.27.1 at /home/box/sdk/go1.27.1)
export PATH=/home/box/sdk/go1.27.1/bin:$PATH
mkdir -p /tmp/adk-hello && cd /tmp/adk-hello
go mod init example.com/adk-hello
go get google.golang.org/adk/v2@v2.6.0
grep adk go.modVerified on this lab (2026-10-16):
go: added google.golang.org/adk/v2 v2.6.0
go.mod contains a line like google.golang.org/adk/v2 v2.6.0 (exact pseudo-version / checksum from the proxy). Stay on 1.x only if you must:
go get google.golang.org/adk@v1 # legacy line — do not mix with /v2 importsWorked examples
Case 1: Minimal LLM agent (ADK Go 2.0 shape)
The official quickstart (adk.dev/get-started/go/) builds a Gemini-backed agent with the Google Search tool. Imports are under /v2:
// agent.go — ADK Go 2.0 quickstart shape (from adk.dev; needs GOOGLE_API_KEY to run)
package main
import (
"context"
"log"
"os"
"google.golang.org/adk/v2/agent"
"google.golang.org/adk/v2/agent/llmagent"
"google.golang.org/adk/v2/cmd/launcher"
"google.golang.org/adk/v2/cmd/launcher/full"
"google.golang.org/adk/v2/model/gemini"
"google.golang.org/adk/v2/tool"
"google.golang.org/adk/v2/tool/geminitool"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
model, err := gemini.NewModel(ctx, "gemini-flash-latest", &genai.ClientConfig{
APIKey: os.Getenv("GOOGLE_API_KEY"),
})
if err != nil {
log.Fatalf("Failed to create model: %v", err)
}
timeAgent, err := llmagent.New(llmagent.Config{
Name: "hello_time_agent",
Model: model,
Description: "Tells the current time in a specified city.",
Instruction: "You are a helpful assistant that tells the current time in a city.",
Tools: []tool.Tool{
geminitool.GoogleSearch{},
},
})
if err != nil {
log.Fatalf("Failed to create agent: %v", err)
}
config := &launcher.Config{
AgentLoader: agent.NewSingleLoader(timeAgent),
}
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())
}
}go mod tidy
# Interactive CLI (needs a real API key — not run in this scout sandbox):
# source .env && go run agent.go
# Dev UI:
# go run agent.go web api webui # http://localhost:8080 — development onlyVerification without an API key: the module downloaded, llmagent.Config fields Name, Model, Instruction, Tools match v2.6.0 source under the module cache, and gemini.NewModel / full.NewLauncher exist. Live Gemini calls were not made (no key in the scout environment).
Case 2: Module path migration (1.x → 2.x)
# Before (ADK Go 1.x)
import "google.golang.org/adk/agent/llmagent"
# After (ADK Go 2.x)
import "google.golang.org/adk/v2/agent/llmagent"
go get google.golang.org/adk/v2
# then rewrite imports, go mod tidy, fix compile breaks from the list belowCase 3: session.NewEvent needs a context
From the ADK Go 2.0 compatibility notes and README-v2.md in the module:
// Before (1.x)
ev := session.NewEvent(invocationID)
// or temporary helper:
ev := session.NewEventWithContext(ctx, invocationID)
// After (2.x) — context first; ID/timestamp come from platform providers on ctx
ev := session.NewEvent(ctx, invocationID)Thread the existing agent/tool/callback context. Do not invent context.Background() mid-stack unless you are in main or test setup. Deterministic replay installs time/UUID providers on ctx.
Case 4: What 2.0 adds beyond the 1.0 launch post
| 1.0 launch theme (Mar 2026) | Where it sits in 2.0 |
|---|---|
| OpenTelemetry tracing | Still first-class; wire a TraceProvider through the runner / telemetry helpers |
| Plugin system (retry-and-reflect, logging) | Prefer framework retries + callbacks; do not hide errors inside tools |
RequireConfirmation HITL tools |
Remains; 2.0 also models pause via event fields such as RequestedInput |
| YAML agent configs | Still supported for persona / tool lists without rebuilds |
| New in 2.0 | Graph workflows, dynamic branching/loops, collaborative coordinator+subagent graphs |
| New in 2.0 | Event schema fields: NodeInfo, Output, Routes, IsolationScope, RequestedInput |
Custom session stores that map events onto rigid SQL columns must grow those fields (or store JSON blobs). Strict API gateways with additionalProperties: false must allow them before you write 2.0 sessions into a shared store.
Case 5: Do not bypass the graph
// WRONG in 2.0 — mutates session behind the runner's back
// ctx.session.events = append(ctx.session.events, custom)
// RIGHT — yield / return events so the workflow engine persists and routes themLikewise, overrides of old internal Run entry points are ignored by the graph scheduler. Move telemetry and policy into BeforeAgentCallbacks / AfterAgentCallbacks on llmagent.Config.
The trap
- Copy-pasting 1.0 import paths from the March blog into a 2.0 module — compile errors or accidental dual-module graphs.
- Catching all errors inside a tool so the 2.0 retry / HITL machinery never sees a failure.
- Mixing
adkandadk/v2in one binary. - Shipping ADK Web (
go run … web api webui) to production — docs mark it development-only. - Assuming the X 1.0 announcement is current API — upgrade notes on adk.dev/2.0 win.
The boring rule
New Go agents: google.golang.org/adk/v2, Go ≥ 1.25, pin a minor (v2.6.0 or current), pass context into session.NewEvent, let the workflow runtime own events and retries, and keep secrets in the environment — not in the repo.
Try this
go get google.golang.org/adk/v2@latestin a throwaway module and openllmagent.Configin your editor.- Port one 1.x agent: rewrite imports, fix
NewEvent, run tests. - Add a
RequireConfirmation: truetool and exercise the pause path in the dev UI. - Read the graph-workflow guide on adk.dev and express a SequentialAgent as an explicit graph.
Sources
- ADK 2.0 overview
- Installation · Go quickstart
- ADK Go 1.0 blog (historical spark)
- github.com/google/adk-go · module
google.golang.org/adk/v2v2.6.0 - Inspiration: googledevs on X (ADK Go 1.0 thread; chapter written for 2.0)