依据:Google ADK 官方文档(google.github.io/adk-docs / adk.wiki 中文镜像)、Google Developers Blog《Why we built ADK 2.0》《Announcing ADK Go 2.0》《What Google I/O '26 means for developing agents on Google Cloud》、Google Codelabs《ADK 2 Orchestration: Graph, Collaborative & Dynamic Workflows》
版本基线:ADK Python v2.0.0 / Go v2.0.0 / TypeScript v2.0.0(Java、Kotlin 亦有支持,Kotlin 为 Android Beta)
整理时间:2026-10-14
目录
- ADK2 是什么
- 第一层:智能体与多智能体基础
- 第二层:编排的本质与 ADK 2.0 设计哲学
- 第三层:ADK 2.0 四大编排方式
- 第四层:协作工作流深入(多智能体协作核心)
- 第五层:生产级能力(HITL / 韧性 / 可观测)
- 第六层:数据与上下文管理
- 第七层:选型决策指南
1. ADK2 是什么
-
"ADK2" = Google Agent Development Kit 2.0,Google 官方的开源智能体(AI Agent)开发框架。
-
定位:模型无关、部署无关、框架可互操作,"让智能体开发感觉更像软件开发"。
-
多语言:Python(主力)、Go、TypeScript、Java、Kotlin(Android Beta)。
-
安装:
- Python:pip install google-adk
- TypeScript:npm install @google/adk
- Go: go getgoogle.golang.org/adk
- Java:Maven `com.google.adk:google-adk
-
ADK 1.x 已具备:模型实例化、回调控制、上下文抽象、模板工作流(Sequential/Parallel/Loop)、LLM 动态转移。
-
ADK 2.0 的核心新增:结构化工作流运行时(Workflow runtime)+ 任务协作模型(Task Collaboration) ,即"图工作流 / 动态工作流 / 协作工作流"三大件。
2. 第一层:智能体与多智能体基础
2.1 智能体的五要素
一个 ADK 智能体 = 模型(Model)+ 指令(Instruction)+ 工具(Tools)+ 会话/上下文(Session)+ 执行循环(Runner / Event loop) 。模型负责推理,工具负责行动,会话承载历史与状态,Runner 驱动"思考→行动→观察"的循环。
2.2 单体智能体的四个瓶颈
把所有职责塞进一个智能体(一个大 prompt + 一堆工具)时:
| 瓶颈 | 表现 |
|---|---|
| 提示词膨胀 | 系统提示越来越长,指令互相干扰 |
| 上下文污染 | 所有子任务的历史混在同一会话,互相干扰 |
| 工具过载 | 工具越多,模型选择越困难、越容易选错 |
| 不可评估 | 无法对单一能力独立测试与度量 |
2.3 多智能体的核心收益与代价
收益:
- 职责分离:每个智能体只干一件事,指令短而清晰
- 上下文隔离:每个子智能体只携带自己需要的上下文(ADK 2.0 中 task/single_turn 子智能体跑在独立会话分支)
- 独立开发/测试/评估:可单测、可灰度、可复用
- 可组合:子团队可嵌进更大的团队(图可嵌套)
代价: 协调复杂度上升、多跳带来延迟与 token 成本、错误会在链路中传播。

2.4 常见多智能体拓扑(ADK 1.x 起沿用)
- 协调者/调度器(Coordinator / Dispatcher) :根智能体把请求分发给专家
- 层级团队(Hierarchical teams) :团队的子节点还是团队
- 交接(Handoff / transfer_to_agent) :把对话控制权整体移交给另一个智能体
- 智能体即工具(Agent as tool) :把子智能体包装成工具调用,结果返回给调用方
3. 第二层:编排的本质与 ADK 2.0 设计哲学
3.1 编排是什么
编排(Orchestration)= 决定控制流:谁在什么时候运行、数据怎么流转、失败了怎么办。 多智能体系统的全部难点都收敛到这一个问题。
3.2 两种极端路线
| LLM 自主编排 | 确定性代码编排 | |
|---|---|---|
| 做法 | 把流程写进 prompt,模型自己决定下一步 | 用代码/图显式定义流程 |
| 优点 | 灵活,能处理没预料到的情况 | 可预测、快、便宜、错误处理干净 |
| 缺点 | 非确定性(官方原文 exhibit variance):同一业务流程跑 100 次可能 95 次对;慢且贵(每步都要推理) | 覆盖所有边缘情况很复杂 |
Google 的论点(《Why we built ADK 2.0》):
路由、调度、错误处理是传统代码擅长的事,不该让 LLM 做。如果 B 必须跟在 A 后面,就没有理由等模型去推断------那是白烧的 token 和秒数。
"The model makes the decision; the graph makes it reliable, observable, and resumable." (模型做决策,图保证可靠、可观测、可恢复。)
设计原则:能用确定性就用确定性,把 LLM 留给真正需要认知推理的步骤。
3.3 控制光谱(Spectrum of Control)
ADK 2.0 给出一个从"完全自主"到"完全确定"的滑杆:
完全自主 ←────────────────────────────────────────→ 完全确定
① 单体 Agent + 提示词编排 LLM 决定一切
② 协作工作流(coordinator+模式) LLM 委派 + 模式约束
③ 动态工作流 代码编排(内含 LLM 节点)
④ 图工作流 声明式确定性图
⑤ 纯函数链 / 工具调用 全确定

4. 第三层:ADK 2.0 四大编排方式
4.0 总览

| 编排方式 | 引入 | 控制流归属 | 典型场景 |
|---|---|---|---|
| 模板工作流(Sequential/Parallel/Loop) | 1.x(2.0 中 Python/Go 已被图/动态取代) | 固定模板 | 简单流水线 |
| 基于图的工作流(Graph Workflows) | 2.0 | 声明式边 + 路由 | 分支、扇出/扇入、循环 |
| 动态工作流(Dynamic Workflows) | 2.0 | 编程代码 | 迭代循环、复杂分支、递归 |
| 协作工作流(Collaborative Workflows) | 2.0(原 Task-based Agent Collaboration API) | LLM 协调者 + 运行模式 | 自管理智能体团队 |
官方定位:三者互补------图 最适合确定性结构化流程;动态 最适合控制流过于复杂/需要迭代;模板是常见模式的高层构建块。
4.1 模板工作流(1.x 遗产)
- SequentialAgent:子智能体一个接一个跑
- ParallelAgent:子智能体全部并行(注意:是"全部",不是"选子集")
- LoopAgent:反复执行直到终止条件
- 2.0 文档明确:Python/Go 中模板工作流已被图工作流与动态工作流"superseded"(取代),能力更强。简单场景仍可用。
- transfer_to_agent 是串行 交接;ParallelAgent 是全部并行------二者都做不到"LLM 选子集 + 并行",这个缺口正是 2.0 协作工作流补上的。
4.2 基于图的工作流(Graph Workflows)------ 2.0 新核心
核心概念
节点(Node)= 任何工作单元,ADK 提供类型化构造函数:
| 节点类型 | 作用 |
|---|---|
| Function node | 包装普通类型化函数(泛型自动推导输入/输出 schema) |
| Emitting function node | 函数节点 + emit 回调,可流式发事件、可暂停请求人工输入 |
| Agent node | 把任意 Agent(如 LlmAgent)放进图 |
| Tool node | 把工具变成图的一步 |
| Join node | 扇入屏障:等所有前驱完成,把各前驱输出组成 map 交给你 |
| Dynamic node | 在代码里编排(见 3.3) |
| Workflow node | 把整个子工作流嵌成一个节点------图可组合 |
| Parallel workers | 对列表逐项并发执行并聚合结果 |
| State-bound node | 从 session state 按 "state:" 标签拉值进类型化 Params |
边(Edge)连接节点,可携带路由条件:节点发一个 routing value,匹配的边触发。由此得到全部控制流形态:
- 顺序链:A → B → C
- 条件路由:一个节点按值分发到不同分支(StringRoute / IntRoute / BoolRoute / MultiRoute / Default)
- 扇出(Fan-out):一个节点触发多个下游同时开始
- 扇入(Fan-in):JoinNode 等所有分支完成后才放行
- 嵌套子图:Workflow node
- 循环:已完成的节点可被重新触发,回边让 cycle 成为一等公民
- LLM 当路由器:LlmAgent 分类 → 普通函数发 route → 图分发。模型只做"决策",执行交给图

Python 示例(分类路由)
ini
from google.adk import Agent, Workflow, Event
process_message = Agent(
name="process_message",
model="gemini-flash-latest",
instruction="""Classify user message into either "BUG", "CUSTOMER_SUPPORT",
or "LOGISTICS"...""",
)
def router(node_input: str):
routes = [r.strip() for r in node_input.split(",")]
return Event(route=routes)
root_agent = Workflow(
name="routing_workflow",
edges=[
("START", process_message, router),
(router, {
"BUG": response_1_bug,
"CUSTOMER_SUPPORT": response_2_support,
"LOGISTICS": response_3_logistics,
})
],
)
Go 示例(链 + 条件边 + Join)
css
edges := workflow.Concat(
workflow.Chain(workflow.Start, classifyNode),
[]workflow.Edge{
{From: classifyNode, To: bugNode, Route: workflow.StringRoute("BUG")},
{From: classifyNode, To: supportNode, Route: workflow.StringRoute("CUSTOMER_SUPPORT")},
},
)
wf, _ := workflowagent.New(workflowagent.Config{Name: "pipeline", Edges: edges})
// 扇出/扇入:b.AddFanOut(planner, researchA, researchB, researchC); b.AddFanIn(join, ...)
数据处理
- 每个节点可声明 input_schema / output_schema(Python 用 Pydantic,TS 用 Zod)做类型化契约
- 节点返回值经 event.Output 自动 传给下一节点,无需手动读写 session state
- 动态工作流中 RunNode 直接以类型化值返回子节点输出
官方优势与已知限制
- 优势:精确定义逻辑 / 支持分支与状态 / 无需调用模型即可跑函数链 / 结构化定义提升可靠性
- 限制:某些第三方集成与图工作流不兼容
4.3 动态工作流(Dynamic Workflows)
抛开图的路径结构,用编程语言的全部能力写编排:循环、条件、递归、对动态列表 fan-out。
- Python:@node(rerun_on_resume=True) 装饰器 + await ctx.run_node(child, node_input=...)
- Go:workflow.NewDynamicNode + workflow.RunNodeT(nc, node, in)
- 编排主体就是普通代码:while / async-await / for,而不是图路由
Python 示例(代码修复循环)
ini
@node
async def code_workflow(ctx: Context, user_request: str):
code = await ctx.run_node(coder_agent, user_request)
check_resp = await ctx.run_node(compile_lint_check, code)
while check_resp.findings:
yield Event(state={"code": code, "findings": check_resp.findings})
code = await ctx.run_node(fixer_agent, {"code": code, "findings": check_resp.findings})
check_resp = await ctx.run_node(compile_lint_check, code)
yield Event(output=code)
动态 vs 图
| 图工作流 | 动态工作流 | |
|---|---|---|
| 结构 | 声明式,Dev UI 可 1:1 可视化 | 代码,不可视化但无表达限制 |
| 适合 | 静态、分支/并行/循环 | 迭代循环、递归、运行时才知的路径 |
| 循环表达 | 回边 | 普通 while |
| 数据传递 | event.Output 自动流转 | RunNode 直接返回类型化值 |
| 学习成本 | 需理解节点/边/路由 | 会用语言就行 |
rerun_on_resume语义:动态节点默认在恢复后重跑 ;FunctionNode 是交接(handoff)语义。
4.4 协作工作流(Collaborative Workflows)
见第四层深入。一句话:一个 LLM 协调者 + 一组带运行模式的子智能体 = 自管理的智能体团队。
5. 第四层:协作工作流深入(多智能体协作核心)
5.1 定位
"某些复杂任务可能需要多个具有特定职责的智能体,并从较松散的程序中获益,特别是对于包含多个重要子任务的迭代过程。"
一个协调者智能体 负责向一个或多个子智能体 委派任务;子智能体处理特定任务,完成后自动返回父智能体。
5.2 声明方式(Python)
ini
weather_agent = Agent(
name="weather_checker",
mode="single_turn", # 无用户交互
tools=[get_weather, user_info, geocode_address],
)
flight_agent = Agent(
name="flight_booker",
mode="task", # 可以向用户提问
input_schema=FlightInput,
output_schema=FlightResult,
tools=[search_flights, book_flight],
)
root = Agent(
name="travel_planner", # 协调者
sub_agents=[weather_agent, flight_agent],
# ADK 自动注入以每个子智能体命名的委派工具:weather_checker、flight_booker
)
要点:
- 委派工具自动注入:协调者看到的不是一堆 transfer_to_agent,而是每个子智能体各一个、以其命名的工具
- description= 是路由依据:协调者靠子智能体的 description 字段选择派给谁;不写 description 就等于让模型只看名字猜
- mode 只配给子智能体,根智能体不配
5.3 三种运行模式
| 维度 | chat(默认) | task | single_turn |
|---|---|---|---|
| 人在环中 | 完全交互 | 仅用于澄清提问 | 不允许 |
| 用户交互 | 用户自由与智能体聊天 | 智能体按需提问 | 无用户交互 |
| 控制流 | 智能体控制直到手动交接 | 智能体控制直到任务完成 | 任务完成后立即返回 |
| 并行执行 | 不支持 | 不支持 | 多个任务可并行 |
| 返回父智能体 | 手动(transfer_to_agent) | 自动(finish_task) | 自动(带结果) |
| 本质比喻 | "把对话交给专家" | "为这项任务协作" | "智能体即工具" |
chat 模式:对话移交(串行、专家持话权)
chat 是默认模式,本质是 1.x 时代的 handoff 式委派:父智能体通过 transfer_to_agent 把整段对话的控制权交给一个专家,专家从此直接面对用户;父智能体退场,除非专家再显式 transfer 回去。
要点:
- 协调者手里只有 transfer_to_agent 这一个工具(串行交接,一次给一个专家)
- 专家直接跟用户对话,运行结束于此,不会自动返回父智能体
- 无并行、无自动返回、无综合
例子:客服调度 SupportRoot,挂着 billing_specialist、tech_specialist、returns_specialist 三个 chat 子智能体。
- 用户:"我的退款还没到账。"
- SupportRoot 判断该转给退款专家,调用 transfer_to_agent → 整段对话交给了 returns_specialist
- 之后退款专家直接对用户说话:"查到你的订单...退款已于 10/12 发出,3--5 天到账...",对话到这里结束,SupportRoot 不再驱动
- 若用户接着问账单问题,退款专家得自己再 transfer_to_agent 给账单专家
- 用 Codelab 的原话:"六个专家、一次转移------这不是 bug,是 chat 模式在做它该做的事。对话属于持有它的人,直到有人显式转让。"

chat 模式是把"话筒"递给专家、协调者退场。而下面的task模式 是协调者"派活儿"给专家、自己始终坐在导演椅上。
task 模式(把任务委派下去)
- 协调者保持主导权:根会话上下文由协调者掌握,子智能体只是被"派出"执行一块工作。
- 委派即开独立分支:每个 task 子智能体拿到一个隔离的任务上下文(有自己的会话分支),因此多个 task 可以并行执行。
- 子智能体可主动澄清:执行中发现缺信息(比如"从哪个城市出发?"),可以向用户提问,用户补充后它继续干。
- finish_task 自动交回:子智能体完成工作后调用 finish_task,自动把"结果 + 控制权"还回协调者------你不需要写任何回传/return 代码。
- 协调者综合:拿到所有子任务结果后,协调者汇总成最终答复给用户。
官方把 task 称为 "best of both worlds" :既让 LLM 自主执行细节,又让协调者掌控全局、做综合决策------这是它和 chat 最本质的区别。

实例:智能旅行规划
假设有一个 travel_planner 协调者,下面挂三个 task 子智能体:flight_booker(查机票)、hotel_finder(找酒店)、itinerary_planner(排行程)。
用户说:"帮我规划 5 天东京家庭游,预算 2 万。"
- travel_planner 并行委派 3 个 task;
- flight_booker 发现缺"出发城市",向用户澄清 → 用户答"上海";
- 三个专家各自完成后 finish_task 把结果交回;
- travel_planner 综合三份结果,输出完整方案。
python
ini
from google.adk.agents import Agent
travel_planner = Agent(
name="travel_planner",
model="gemini-2.5-pro",
instruction=(
"你是旅行规划协调者。把任务委派给专业子智能体,"
"等它们用 finish_task 返回后,综合成完整方案交给用户。"
),
sub_agents=[flight_booker, hotel_finder, itinerary_planner],
)
flight_booker = Agent(
name="flight_booker",
model="gemini-2.5-flash",
instruction=(
"查机票。若缺出发城市,主动向用户澄清;"
"完成后调用 finish_task 返回结果。"
),
)
# hotel_finder、itinerary_planner 类似
下面这张双栏图把 chat 和 task 放在同一画面里对照,差异会非常直观。

single_turn 模式
-
无用户交互、自动返回、可并行
-
协调者一轮内发多个调用 → ADK 并行执行 → 各自自动返回 → 协调者综合
-
每个 single_turn 子智能体跑在自己隔离的会话分支 :看不到对话、看不到同辈。因此协调者必须把完整输入(问题+策略+数据)分别转发进每次并行调用
-
官方诚实的提醒:
- 子集由模型选,确定性弱于硬编码 router,每次运行派中的专家可能不同
- 偶尔会出现某个专家的输入校验错误------通常是协调者没把嵌套输入完整复现;ADK 把错误作为该工具的结果返回,协调者恢复后综合仍然成立(output_schema 由 Gemini 服务端强制,输出一般没问题)

5.4 同一子智能体,两种调用上下文(复用不改代码)
| 调用方式 | 任务完成后的控制流 |
|---|---|
| 作为工作流图节点(SequentialAgent / ParallelAgent / workflow.NewAgentNode) | 推进到图中的下一个节点 |
| 作为 LlmAgent 的转移接收方(委派工具) | finish_task → 回到原始智能体 |
运行时按智能体被调用的方式自动决定控制流。
5.5 与 1.x 的本质区别
1.x 里"LLM 选子集 + 并行"需要把每个专家包成 AgentTool 手工搭管道;
2.0 把它变成一句声明(sub_agents=... + mode="single_turn")。且 ParallelAgent 永远是"全部并行"、transfer_to_agent 永远是"串行"------协作工作流第一次让"选子集 + 并行 + 自动返回 + 综合"成为原生能力。
6. 第五层:生产级能力(HITL / 韧性 / 可观测)
6.1 人工在环(HITL)------ 内置
- 任意节点都可以暂停图并向人类提问,工作流持久等待应答:
php
event := workflow.NewRequestInputEvent(ctx, session.RequestInput{
InterruptID: "approve_refund",
Message: "Approve a $200 refund? (yes/no)",
ResponseSchema: schema,
})
-
人类在后续轮次应答后工作流恢复,两种恢复方式自选:
- Handoff:回答直接流给下一个节点
- Re-entry:被暂停的节点带着 ctx.ResumedInput(...) 重跑
-
持久化恢复:运行状态存在 session 中,ADK 甚至能扫描会话历史重建暂停的工作流------
- 进程重启后可恢复
- 跨运行时也可恢复(中断格式在 Python ADK 与 Go ADK 间共享)
- 恢复幂等;错误明确(ErrInvalidResumeResponse / ErrNothingToResume)
- 应答按 schema 校验
-
Console launcher 与 Web UI 原生理解 HITL:工具确认提示 + 工作流输入请求都能展示
6.2 韧性(Resilience)
-
每节点 retry policy:指数退避 + jitter,无外部依赖
- 默认:5 次尝试、初始 1s、上限 60s、2x backoff、full jitter
-
每节点 timeout
-
图级并发上限:WithMaxConcurrency(n)
-
并行分支隔离(WithIsolationScope):一个分支的嘈杂历史不会泄漏进另一个分支的 LLM 提示
-
调度器负责 goroutine、channel、背压、取消
-
细粒度选项:WithRunID(子节点身份)、WithUseSubBranch(历史隔离)、WithUseAsOutput(输出委托)

6.3 可观测性与运行时统一
-
节点/智能体执行出现在同一棵 telemetry span tree,图到底做了什么一目了然
-
Go 2.0 统一 agent.Context:ToolContext / CallbackContext 合并为一个类型------写工具、回调、图节点学同一个上下文
- 升级注意:节点/节点函数签名首参从 agent.InvocationContext 改为 agent.Context(它嵌入 InvocationContext,旧方法仍可用)
-
Agent modes(Chat / Task / SingleTurn) :runner now 用驱动工作流的同一套节点运行时来驱动普通 LlmAgent
- 收益:单智能体应用与完整图共享一个执行模型;普通 LLM 智能体也支持 HITL
- 按角色自动安装辅助工具(finish_task / single_turn / task)
-
升级 2.0 是高度增量的:整个工作流引擎是可选新包;少量破坏性改动都是机械修复
7. 第六层:数据与上下文管理
- 类型化 I/O:input_schema / output_schema(Pydantic / Zod / Go struct)定义契约;Gemini 可服务端强制 output_schema
- 自动数据流:图节点间经 event.Output 自动传递;动态工作流 RunNode 直接返回类型化值------都不用手工 session state 管线
- 会话分支隔离:并行子智能体各跑各的分支,构建 LLM 上下文时只见自己分支的事件
- 状态最小化:动态工作流把值存局部变量,只有指令模板需要读回时才写 Event(state=...)
- State-bound 节点:需要时按标签把 session state 拉进类型化结构,而不是全局乱翻
8. 第七层:选型决策指南

vbnet
需要多个步骤/多个角色?
│
├─ 控制流运行时才知道(循环次数、数据依赖、模型刚说了什么)→ 动态工作流
│
├─ 需要 LLM 动态决定"派给谁、派几个"?→ 协作工作流
│ ├─ 要专家直接面对用户自由对话 → chat
│ ├─ 专家可向用户澄清、完成自动返回 → task(注意:叶子智能体)
│ └─ 无交互、并行、完成即返回 → single_turn
│
├─ 分支/扇出/扇入/循环,且结构静态可见?→ 图工作流
│ └─ 超过两条分支就值得上图(官方原话:The graph model is worth the
│ learning curve as soon as you have more than two branching paths)
│
└─ 流程固定无分支 → 模板工作流(Sequential / Parallel / Loop)
经验法则:
- 能确定就确定------路由/调度/错误处理交给代码,LLM 只做认知推理
- 混合是常态:官方退款案例 = 工具节点(查库/退款/关单)+ LLM 节点(读懂投诉、写定制邮件)混编一张图
- 官方建议的上手顺序(I/O '26):先玩 Managed Agents / Antigravity 建立原型 → 路由决策需要显式化时移植到 ADK 2.0 图模型
附:一页速查
- ADK 2.0 = 图工作流 + 动态工作流 + 协作工作流 + HITL/韧性/可观测
- 图:节点(函数/智能体/工具/Join/动态/子工作流)+ 边(路由/扇出/扇入/回边循环),event.Output 自动传数据
- 动态:@node + ctx.run_node,用代码写编排,循环递归无限制
- 协作:sub_agents + mode(chat 手动交接 / task 澄清+finish_task 自动返回 / single_turn 无交互并行自动返回),委派工具按子智能体名自动注入,并行子智能体会话分支隔离
- 生产:任意节点可暂停问人(durable resume,跨重启跨运行时)、每节点 retry/timeout、图级并发上限、分支隔离、统一 telemetry span tree、统一 agent.Context
- 哲学:模型做决策,图保证可靠、可观测、可恢复;把确定性留给代码,把认知推理留给 LLM