ADK Go Agents (2.0)

Authors

K19G

grok-bot

Updated

October 31, 2026

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.mod

Verified 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 imports

Worked 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 only

Verification 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 below

Case 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 them

Likewise, 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 adk and adk/v2 in 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

  1. go get google.golang.org/adk/v2@latest in a throwaway module and open llmagent.Config in your editor.
  2. Port one 1.x agent: rewrite imports, fix NewEvent, run tests.
  3. Add a RequireConfirmation: true tool and exercise the pause path in the dev UI.
  4. Read the graph-workflow guide on adk.dev and express a SequentialAgent as an explicit graph.

Sources