
Google ADK for Go でマルチエージェントを作る入門
Google の ADK for Go(Agent Development Kit)では、SequentialAgent と ParallelAgent を入れ子にするだけで「並列に調べて、まとめる」マルチエージェントが作れる。v2.5.0 で実際にビルドし、API キー無しで動く偽モデルで実行・テストした手順と、2.0 のグラフ型ワークフロー、Genkit Go との違いを解説する。

Google の ADK for Go(Agent Development Kit)では、SequentialAgent と ParallelAgent を入れ子にするだけで「並列に調べて、まとめる」マルチエージェントが作れる。v2.5.0 で実際にビルドし、API キー無しで動く偽モデルで実行・テストした手順と、2.0 のグラフ型ワークフロー、Genkit Go との違いを解説する。
Google の ADK for Go(Agent Development Kit for Go)を使うと、SequentialAgent(順番に実行)と ParallelAgent(同時に実行)を入れ子にするだけで、「複数のエージェントが並列に調べ、別のエージェントがまとめる」マルチエージェントを Go で書けます1。エージェント同士の結果の受け渡しは、OutputKey で session の state に保存し、次のエージェントの指示文に {キー} で埋め込むだけです。この記事では 2026 年 10 月時点の最新版 v2.5.0 で実際に go build・go test を通したコードを載せ、API キー無しで動く偽モデルでの実行結果、2.0 で入ったグラフ型ワークフロー、Genkit Go との使い分けまで説明します。
ADK for Go は、Google がオープンソースで公開している AI エージェント開発用のツールキットです2。README では「コードファーストで、AI エージェントを作り、評価し、デプロイするための Go のツールキット」と説明されています2。同じ ADK には Python・Java・TypeScript などの実装もあり、Go 版はそのうちの 1 つです2。
主な部品は次のとおりです。
| 部品 | パッケージ | 役割 |
|---|---|---|
| LLM エージェント | agent/ | モデルに指示文を渡して応答させる。ツールも持てる |
| ワークフローエージェント | agent/・parallelagent・loopagent | 子エージェントを順番・並列・繰り返しで動かす |
| モデル | model/・model/ ほか | LLM への接続。model.LLM インタフェースを満たせば差し替えられる |
| Runner | runner | session を管理しながらエージェントを実行する |
| グラフ型ワークフロー | workflow・agent/ | 2.0 で追加。ノードと辺でアプリの形を書く |
ワークフローエージェントは、子エージェントをどう動かすかを LLM に相談せず、決まった手順で動かします1。そのため実行の順番が毎回同じになり、予測しやすいのが特長です1。
ADK for Go は 2025 年 11 月 7 日に発表され3、2026 年 3 月 31 日に 1.0、2026 年 6 月 30 日に 2.0 が出ました45。2.0 ではグラフ型のワークフローエンジン、処理を止めて人に確認する仕組み(Human-in-the-Loop)、Go のコードで子ノードを動かす動的なオーケストレーションが入っています5。
公開 3 年目に入り、Go 版のリポジトリも GitHub のスター数で Java 版や TypeScript 版を上回っています。
| リポジトリ | スター数 |
|---|---|
| google/adk-python | 21,707 |
| google/adk-go | 8,847 |
| google/adk-java | 1,746 |
| google/adk-js | 1,430 |
検索の関心も上向きです。Google トレンド(日本・過去 90 日、2026-10-05 取得)の相対値で、「Go言語」は直近 4 週の平均が 2.0、その前の 8 週の平均が 0.3 でした。値は小さいものの上向きです6。Go で AI エージェントを書く理由そのものは Go 言語と AI エージェントの相性 で詳しく説明しています。
この記事で作るのは、テーマについて「利点」と「欠点」を 2 つのエージェントが同時に調べ、3 つ目のエージェントがまとめる構成です。

SequentialAgent が「調査 → まとめ」の順番を決めるParallelAgent が 2 つの調査エージェントを同時に動かすOutputKey で state の pros・cons に保存するWriter は指示文の {pros}・{cons} に state の値が埋め込まれた状態で呼ばれる2026 年 10 月時点の最新版は v2.5.0(2026 年 9 月 30 日公開)で7、モジュールパスは google.golang.org/ です2。v2.5.0 は go.mod で Go 1.26.6 以上を要求します。
mkdir adkdemo && cd adkdemo
go mod init example.com/adkdemo
go get google.golang.org/adk/v2@v2.5.0
筆者の手元の Go 1.26.2 では requires go >= 1.26.6 (running go 1.26.2; GOTOOLCHAIN=local) で止まりました。GOTOOLCHAIN が既定の auto なら必要なツールチェーンが自動で取得されます。この記事のコードは Go 1.27.1 でビルド・テストしました。
v1 の google.golang.org/ もまだ更新されています(2026 年 10 月時点で v1.8.0)。新しく始めるなら v2 を選び、v1 から移る場合は README-v2.md の破壊的変更(session.NewEvent が context.Context を取るなど)を確認します。
llmagent.New に名前・モデル・指示文・OutputKey を渡します。OutputKey を指定すると、エージェントの最終応答が state のそのキーに保存されます。
pros, err := llmagent.New(llmagent.Config{
Name: "ProsResearcher",
Model: m.Pros,
Description: "テーマの利点を調べる",
Instruction: "ユーザーのテーマについて、利点を 1 文で答えてください。",
OutputKey: "pros", // 応答を state["pros"] に保存する
})
if err != nil {
return nil, err
}
cons, err := llmagent.New(llmagent.Config{
Name: "ConsResearcher",
Model: m.Cons,
Description: "テーマの欠点を調べる",
Instruction: "ユーザーのテーマについて、欠点を 1 文で答えてください。",
OutputKey: "cons",
})
ワークフローエージェントは agent.Config の SubAgents に子を並べるだけです。
research, err := parallelagent.New(parallelagent.Config{
AgentConfig: agent.Config{
Name: "Research",
Description: "利点と欠点を同時に調べる",
SubAgents: []agent.Agent{pros, cons},
},
})
if err != nil {
return nil, err
}
writer, err := llmagent.New(llmagent.Config{
Name: "Writer",
Model: m.Writer,
Description: "調査結果をまとめる",
// {pros} と {cons} は実行時に session state の値で置き換わる。
Instruction: "次の調査結果を 3 行でまとめてください。\n{pros}\n{cons}",
OutputKey: "summary",
})
if err != nil {
return nil, err
}
return sequentialagent.New(sequentialagent.Config{
AgentConfig: agent.Config{
Name: "ReportPipeline",
Description: "並列で調べてから、まとめる",
SubAgents: []agent.Agent{research, writer},
},
})
指示文の {キー} は、実行時に state の値で置き換わります。キーが state に無いとエラーになり、{キー?} と書くと無くても無視されます(llmagent.Config の Instruction のドキュメントより)。
runner.NewInMemory は、session・artifact・memory をすべてメモリに持つ Runner を作ります。ドキュメント上は開発とテスト用で、本番では runner.New に自分のサービスを渡します。
func run(ctx context.Context, root agent.Agent, topic string, w io.Writer) error {
r, err := runner.NewInMemory("adkdemo", root)
if err != nil {
return err
}
msg := genai.NewContentFromText(topic, genai.RoleUser)
for ev, err := range r.Run(ctx, "user-1", "session-1", msg, agent.RunConfig{}) {
if err != nil {
return err
}
if ev.Content == nil || ev.Partial {
continue
}
for _, p := range ev.Content.Parts {
if p.Text != "" {
fmt.Fprintf(w, "[%s] %s\n", ev.Author, p.Text)
}
}
}
return nil
}
r.Run は Go 1.23 の range-over-func で回せるイテレータ(iter.Seq2[*session.Event, error])を返します。イベントの Author には、そのイベントを出したエージェントの名前が入ります。
本番のモデルには gemini.NewModel を使います。公式サンプルと同じ書き方です。
m, err := gemini.NewModel(ctx, "gemini-flash-latest", &genai.ClientConfig{})
if err != nil {
return Models{}, fmt.Errorf("gemini.NewModel: %w", err)
}
API キーは環境変数 GOOGLE_API_KEY で渡します。Vertex AI を使う場合は GOOGLE_GENAI_USE_VERTEXAI=true と GOOGLE_CLOUD_PROJECT・GOOGLE_CLOUD_LOCATION を設定します(adk-go の examples/workflow の README より)。キーを設定せずに実行すると、api key is required for Google AI backend で止まります。
ADK のモデルは model.LLM というインタフェースで、メソッドは Name と GenerateContent の 2 つだけです。決まった応答を返す偽のモデルを書けば、API キー無しでパイプライン全体を動かせます。
// FakeLLM は API を呼ばずに決まった応答を返す model.LLM の実装(テスト・動作確認用)。
type FakeLLM struct {
Reply string
EchoInstruction bool // true ならシステム指示(state を埋め込んだ後の文字列)をそのまま返す
}
func (f FakeLLM) Name() string { return "fake" }
func (f FakeLLM) GenerateContent(ctx context.Context, req *model.LLMRequest, stream bool) iter.Seq2[*model.LLMResponse, error] {
return func(yield func(*model.LLMResponse, error) bool) {
text := f.Reply
if f.EchoInstruction && req.Config != nil && req.Config.SystemInstruction != nil {
text = ""
for _, p := range req.Config.SystemInstruction.Parts {
text += p.Text
}
}
yield(&model.LLMResponse{
Content: genai.NewContentFromText(text, genai.RoleModel),
TurnComplete: true,
}, nil)
}
}
Writer には「受け取った指示文をそのまま返す」偽モデルを渡しました。こうすると、state の値が指示文に正しく埋め込まれたかを目で確かめられます。実行結果は次のとおりです。

[ProsResearcher] 利点: 単一バイナリで配布でき、goroutine で並行処理が書きやすい
[ConsResearcher] 欠点: Python に比べて AI 系ライブラリの数が少ない
[Writer] 次の調査結果を 3 行でまとめてください。
利点: 単一バイナリで配布でき、goroutine で並行処理が書きやすい
欠点: Python に比べて AI 系ライブラリの数が少ない
You are an agent. Your internal name is "Writer". The description about you is "調査結果をまとめる".
分かったことが 2 つあります。
{pros} と {cons} は、並列で動いた 2 つのエージェントの出力で置き換わっていたDescription を自動で足していた。Description は飾りではなく、モデルに渡る文章の一部になるこの偽モデルを使えば、ユニットテストも書けます。
func TestPipelinePassesStateToWriter(t *testing.T) {
root, err := buildPipeline(Models{
Pros: FakeLLM{Reply: "PROS"},
Cons: FakeLLM{Reply: "CONS"},
Writer: FakeLLM{EchoInstruction: true},
})
if err != nil {
t.Fatal(err)
}
var out strings.Builder
if err := run(t.Context(), root, "topic", &out); err != nil {
t.Fatal(err)
}
got := out.String()
for _, want := range []string{"[ProsResearcher] PROS", "[ConsResearcher] CONS", "[Writer] 次の調査結果を 3 行でまとめてください。\nPROS\nCONS"} {
if !strings.Contains(got, want) {
t.Errorf("output does not contain %q\n---\n%s", want, got)
}
}
}
=== RUN TestPipelinePassesStateToWriter
--- PASS: TestPipelinePassesStateToWriter (0.00s)
PASS
go test -race でも通りました。並列エージェントの出力の順番は実行ごとに変わりうるので、テストでは順番に依存しない比べ方(strings.Contains)にしています。
loopagent.Config の MaxIterations に回数を入れると、子エージェントをその回数まで繰り返します。0 の場合は、子エージェントが終了を伝える(escalate)まで回り続けます(loopagent.Config のドキュメントより)。ADK には、ループを抜けるためのツール tool/ も用意されています。書き手とレビュー役を交互に回す、といった使い方に向きます。MaxIterations を必ず入れておくと、費用が膨らむのを防げます。
ADK 2.0 では、アプリの形を「ノードと辺のグラフ」で書く workflow パッケージが加わりました5。LLM を使わない関数もノードにできます。次のコードは v2.5.0 で実行を確かめたものです。
trim := workflow.NewFunctionNode("trim", func(ctx agent.Context, in string) (string, error) {
return strings.TrimSpace(in), nil
}, workflow.NodeConfig{})
upper := workflow.NewFunctionNode("upper", func(ctx agent.Context, in string) (string, error) {
return strings.ToUpper(in), nil
}, workflow.NodeConfig{})
wf, err := workflowagent.New(workflowagent.Config{
Name: "normalize",
Edges: workflow.Chain(workflow.Start, trim, upper), // Start → trim → upper
})
[normalize] "hello adk go"
[normalize] "HELLO ADK GO"
関数ノードの戻り値は、イベントの Content ではなく Output に入ります。最初は Content だけを見ていたため、何も出力されませんでした。
公式の例では、ファンアウト・ファンイン(AddFanOut・AddFanIn)、文字列や数値での分岐(StringRoute・IntRoute)、人の入力を待つ RequestInput も扱っています(adk-go の examples/workflow の README より)。
| やりたいこと | 向いている書き方 |
|---|---|
| 固定の順番・並列でエージェントを動かす | SequentialAgent・ParallelAgent |
| 決まった回数か条件まで繰り返す | LoopAgent |
| 分岐・合流・人の承認・関数の処理を混ぜる | workflow のグラフ |
| 実行時にどの子を動かすか Go で決める | workflow.NewDynamicNode |
Google には Go 向けの AI フレームワークがもう 1 つあり、それが Genkit Go です。Genkit Go 1.0 は 2025 年 9 月に公開されました8。
| 項目 | ADK for Go | Genkit Go |
|---|---|---|
| 一言でいうと | エージェントを作り、組み合わせ、動かすためのツールキット2 | AI を使った機能を持つアプリを作るためのフレームワーク8 |
| 中心になる部品 | LLM エージェント、ワークフローエージェント、Runner、session | 型付きの flow、複数社のモデルを同じ API で呼ぶ仕組み8 |
| マルチエージェント | 逐次・並列・ループ、グラフ、A2A(エージェント間の通信プロトコル)35 | flow とツール呼び出しを組み合わせて作る |
| 開発ツール | console・web の launcher、Web UI | Developer UI でフローを試し、トレースを見る8 |
使い分けの目安です。
model.LLM を実装すれば差し替えられ、v2.5.0 には model/ openaimodel が入っていますAnthropic の Claude を Go から直接呼んでツール付きのエージェントを自作する方法は anthropic-sdk-go のツール呼び出し入門 で解説しています。
| 症状 | 原因 | 対処 |
|---|---|---|
go get が requires go >= 1.26.6 で止まる | v2.5.0 が Go 1.26.6 以上を要求している | Go を上げるか、GOTOOLCHAIN=auto のままにする |
指示文の {キー} でエラーになる | state にキーがまだ無い | 前のエージェントの OutputKey を確かめる。無くてよいなら {キー?} |
| 並列エージェントが互いの結果を見られない | 並列の子は別々のブランチで動く(Event.Branch のドキュメントより) | 受け渡しは state 経由にし、後ろの逐次ステップで読む |
| 関数ノードの結果が表示されない | 結果は Event.Output に入る | Content ではなく Output を読む |
| LLM の費用が読めない | LoopAgent の上限なし、並列での同時呼び出し | MaxIterations を入れる。並列の子の数を絞る |
ParallelAgent は子を同時に動かすので、LLM の呼び出しも同時に飛びます。API のレート制限が低いプランでは、並列にした分だけ制限に当たりやすくなります。
google.golang.org/ adk/ v2)SequentialAgent と ParallelAgent を入れ子にするだけで「並列に調べて、まとめる」構成が書けるOutputKey で state に保存し、指示文の {キー} で読むmodel.LLM を満たす偽モデルを書けば、API キー無しで実行もテストもできるworkflow、アプリに AI 機能を足すだけなら Genkit Go も候補次にやることは、偽モデルで組んだパイプラインに GOOGLE_API_KEY を設定し、gemini.NewModel に差し替えて動かすことです。テストを先に書いて Claude Code に実装を任せる進め方は Claude Code で Go のテスト駆動開発 で紹介しています。
2026 年 10 月時点の最新は v2.5.0 で、モジュールパスは google.golang.org/ です2。go get google.golang.org/ で入ります2。v2.5.0 は Go 1.26.6 以上が必要です。
使えます。モデルは model.LLM インタフェースで抽象化されていて、Name と GenerateContent を実装すれば差し替えられます。v2.5.0 には model/ パッケージも入っています。
使いません。SequentialAgent・ParallelAgent・LoopAgent は、決まった手順で子エージェントを動かします1。LLM に委任先を選ばせたい場合は、llmagent の SubAgents に子を並べます。
共有されません。並列の子は別々のブランチで動き、相手の会話の履歴は見えません。結果を受け渡すには、OutputKey で state に保存し、後ろの SequentialAgent のステップで読みます。
複数のエージェントを協調させたいなら ADK for Go、アプリに AI の機能を足すことが目的なら Genkit Go が向いています28。迷ったら、エージェントが 1 つで足りるかどうかで判断します。
Workflow Agents — Agent Development Kit Docs, Google(2026-10-05 参照) ↩ ↩2 ↩3 ↩4
google/adk-go — GitHub, Google(2026-10-05 参照) ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
Announcing the Agent Development Kit for Go — Google Developers Blog, 2025-11-07(2026-10-05 参照) ↩ ↩2
ADK Go 1.0 Arrives! — Google Developers Blog, 2026-03-31(2026-10-05 参照) ↩
Build reliable multi-agent applications with ADK Go 2.0 — Google Developers Blog, 2026-06-30(2026-10-05 参照) ↩ ↩2 ↩3 ↩4
Google トレンド「Go言語」(日本・過去 90 日) — Google(2026-10-05 参照) ↩
google.golang.org/adk/v2 のバージョン一覧 — Go Module Proxy(2026-10-05 参照) ↩
Announcing Genkit Go 1.0 and Enhanced AI-Assisted Development — Google Developers Blog, 2025-09-10(2026-10-05 参照) ↩ ↩2 ↩3 ↩4 ↩5 ↩6