ADK Go 2.0 发布:构建可靠的多智能体应用,新增基于图的工作流引擎、人工参与循环与动态编排
Build reliable multi-agent applications with ADK Go 2.0. Discover our new graph-based workflow engine, built-in human-in-the-loop, and dynamic orchestration
Agent Development Kit (ADK) for Go 2.0 发布,引入了一类基于图的工作流引擎,用于组合复杂多智能体应用。新版本内置人工参与循环(HITL)编排、使用纯 Go 代码的动态执行、以及指数退避重试等自动弹性特性。统一执行模型后,单智能体应用与复杂图均运行在同一运行时上,简化了遥测与状态持久化。
Google 给 Go 生态补上了多智能体编排的关键一环,图工作流引擎和人机协同直接内置,比之前拼积木的方式可靠很多,做 Agent 的 Go 开发者值得跟进。
ADK for Go 2.0:以图的方式构建智能体工作流
构建真实世界的智能体应用,很少像发送单个提示词那样简单。生产环境的智能体必须进行分类、分支、扇出、请求人工审批、失败重试,并循环直到完成。把这种复杂的编排表达为临时拼凑的控制流,很快就会变得脆弱不堪。
自 1.0 版本发布以来,Agent Development Kit(ADK)for Go 一直帮助 Go 开发者以简洁、地道的 API 构建生产级智能体——强类型、iter.Seq2 事件流,以及一个能自然融入现有 Go 服务的运行时。这一基础取得了真正的成功,也正是它让下一步成为可能。
今天,我们很高兴分享 ADK for Go 2.0。最核心的亮点是一种全新的、一等公民式的多智能体应用编排方式:基于图的工作流引擎。与之相伴的还有作为内置原语的 human-in-the-loop(HITL)、用纯 Go 编写的动态编排、LLM 智能体模式,以及一个将这一切整合在一起的 统一节点运行时——单个智能体和完整的图现在都运行在同一个执行模型之上。
如果你关注过 Python ADK 2.0,这会让你感到熟悉:它遵循同样的图优先方向,并且从底层开始就设计得具有 Go 的风格。
为什么要用图?
真正的智能体应用很少只是一个提示词。它们会分类、分支、向专家节点扇出、收集结果、请人类批准某项操作、失败时重试,并循环直到完成。把这一切用临时拼凑的控制流来表达,很快就会变得脆弱不堪。
ADK 2.0 让你把应用的形态描述为一张由边连接节点构成的图,并把执行交给一个调度器,它知道如何并发运行、持久化状态、为等待人类而暂停、之后再恢复——甚至能跨进程重启。下面就是把节点串联起来有多简单:
import "google.golang.org/adk/v2/workflow"
upper := workflow.NewFunctionNode("upper", upperFn, cfg)
suffix := workflow.NewFunctionNode("suffix", suffixFn, cfg)
edges := workflow.Chain(workflow.Start, upper, suffix)
wf, _ := workflowagent.New(workflowagent.Config{
Name: "simple_sequence_workflow",
Edges: edges,
})
那个wf只是一个agent.Agent。它运行在你已经在用的同一个 runner、launcher 和 console 中——无需特殊的 harness,也无需新的服务器。一张图就是一个智能体。
构建模块
万物皆节点
节点是任何实现了Node 接口的工作单元。你很少需要手写这个接口——ADK 为常见场景提供了带类型的节点构造函数:
- 函数节点包装一个普通的带类型 Go 函数。泛型会为你推断输入/输出 schema:
workflow.NewFunctionNode("classify",
func(ctx agent.Context, in string) (Category, error) { ... }, cfg)
- 发射函数节点是同时获得
emit回调的函数节点,因此单个函数可以流式发送事件或暂停等待人工介入,而无需降级为动态节点:
workflow.NewEmittingFunctionNode("progress",
func(ctx agent.Context, in Job, emit func(*session.Event) error) (Result, error) { ... }, cfg)
- 智能体节点将任意
agent.Agent(例如LlmAgent)放入图中。 - 工具节点将
tool.Tool转换为图中的一个步骤。 - 汇合节点是扇入屏障:它们等待所有前驱节点,并向你提供其输出的映射。
- 动态节点让你在代码中进行编排(详见下文)。
- 工作流节点将整个子工作流嵌入为单个节点——图可以组合。
- 并行工作器针对列表中的每一项并发运行一个节点,并聚合结果。
- 状态绑定节点(
NewFunctionNodeFromState)通过state:"<key>"标签将选定的会话状态值直接拉入带类型的 Params 结构体——无需手动传递状态。
边、路由以及你需要的各种形态
边连接节点,并且可以携带路由条件。节点发出一个路由值;匹配的边随即触发。仅凭这一个理念,你就能获得所需的所有控制流形态:
b := workflow.NewEdgeBuilder()
b.AddRoutes(router, map[string]workflow.Node{
"question": answerNode,
"statement": commentNode,
"exclamation": reactNode,
})
b.AddFanOut(planner, researchA, researchB, researchC) // parallel branches
b.AddFanIn(join, researchA, researchB, researchC) // gather results
顺序链、条件路由器、扇出/扇入、嵌套子图,甚至循环(已完成的节点可以被重新触发,因此循环是一等公民)——全都由边和路由实现。标准路由包括StringRoute、IntRoute、BoolRoute、MultiRoute,以及一个在其他条件都不匹配时触发的Default。如需更深入的配置,可利用Route 接口。
让 LLM 来操控图
最有用的模式之一,是让模型充当路由器的大脑。一个 LlmAgent 对用户的消息进行分类;一个简单的函数发出匹配的路由;图随即分派到正确的处理器:
User -> What time is it? Agent -> question answering question...
User -> Hello world! Agent -> exclamation reacting to exclamation...
User -> The sky is blue. Agent -> statement commenting on statement...
模型做出决策;图让它变得可靠、可观测、可恢复。(参见examples/workflow/routing/llm/。)
动态编排——用纯 Go 实现
有时执行顺序要到运行时才确定:它取决于数据、循环次数,或模型刚刚说了什么。为此,ADK 2.0 为你提供了动态节点,其中的编排主体是普通的 Go 代码,为每个子节点调用RunNode(...):
greeter := workflow.NewDynamicNode("greeter_workflow",
func(nc agent.Context, in string, emit func(*session.Event) error) (string, error) {
return workflow.RunNode[string](nc, greeterNode, in)
},
workflow.NodeConfig{},
)
循环、条件判断、累积、在动态列表上的扇出——全都用你早已熟悉的 Go 来表达。诸如 WithRunID、WithUseSubBranch、WithUseAsOutput 和 WithIsolationScope 这样的选项,让你能够精确控制子节点身份、历史隔离和输出委派。这是 Python ADK 动态图的 Go 对应实现。
内置的人类参与环节
生产环境中的智能体往往需要在运行中途由人类来批准、纠正或提供某些内容。在 ADK 2.0 中,任何节点都可以暂停图并向人类提问——而工作流会持久地等待答案:
event := workflow.NewRequestInputEvent(ctx, session.RequestInput{
InterruptID: "approve_refund",
Message: "Approve a $200 refund? (yes/no)",
ResponseSchema: schema,
})
// yield the event; the node moves to "waiting"
当人类在后续轮次中回复时,工作流会恢复运行。恢复方式由你选择:
- 交接——答案直接流向下一个节点。
- 重新进入——被暂停的节点会重新运行,人类的回复可通过
ctx.ResumedInput(...)获取。
而且恢复是持久的。运行状态保存在会话中,ADK 甚至可以通过扫描会话历史来重建被暂停的工作流——因此工作流可以在进程重启后恢复,甚至跨不同的运行时恢复,因为中断格式与 Python ADK 共享。响应会根据 schema 进行校验,恢复是幂等的,当出现不匹配时你会得到清晰的错误(ErrInvalidResumeResponse、ErrNothingToResume)。
控制台启动器和 Web UI 都开箱即用地理解 HITL,能够呈现工具确认提示和工作流输入请求。
无需样板代码的弹性能力
每个节点都可以携带带有指数退避和抖动的重试策略——无需任何外部依赖:
cfg := workflow.NodeConfig{ RetryConfig: workflow.DefaultRetryConfig() }
// 5 attempts, 1s initial delay, 60s cap, 2x backoff, full jitter
为每个节点添加 Timeout,用 WithMaxConcurrency(n) 限制整个图的并发量,并隔离并行分支,使一个分支的杂讯永远不会泄漏到另一个分支的 LLM 提示词历史中。调度器会为你处理 goroutine、channel、背压和取消。
智能体模式,以及一个统一运行时来运行所有模式
ADK 2.0 为 LLM 智能体引入了模式——Chat、Task 和 SingleTurn——因此协调者可以在与用户对话的同时,让子智能体静默完成任务或以单次执行方式运行。合适的辅助工具(finish_task、single_turn、task)会根据每个智能体的角色自动安装。
在底层,运行器现在驱动一个普通的LlmAgent通过同一个节点运行时来驱动工作流。带来的好处是:单智能体应用和完整的图共享同一套执行模型,并且human-in-the-loop 现在对普通的 LLM 智能体也能生效——而不仅仅是在工作流内部。
我们还简化了编程模型:ToolContext 和 CallbackContext 现在统一为单一的 agent.Context —— 无论你是在编写工具、回调还是图节点,都只需学习一种类型 —— 并且节点/智能体执行会呈现在一棵一致的遥测 span 树中,让你能准确看到你的图做了什么。
从 1.0 升级
ADK 2.0 具有高度的增量性 —— 整个工作流引擎都是你可选择启用的新包。统一运行时带来了一些新增的和破坏性的变更;每一项都有简单、机械化的修复方式:
- 节点和节点函数签名接收
agent.Context****。 如果你编写节点或节点函数,请将第一个参数从agent.InvocationContext改为agent.Context(它内嵌了InvocationContext,因此你之前使用的每个方法仍然有效):
// before: func(ctx agent.InvocationContext, in string) (string, error)
// after: func(ctx agent.Context, in string) (string, error)
- 统一的上下文。
ToolContext、CallbackContext已移除 —— 工具、回调和 workflow 节点都直接接收agent.Context。如果你在测试中 mock 了一个上下文,agent/context_mock.go仍然保留;使用该文件中的StrictContextMock作为你的测试替身。 - 自定义**
InvocationContext**实现需要两个方法:IsolationScope()和ResumedInput(id string)。大多数代码会内嵌所提供的实现,从而免费获得这些方法。 - 事件流更加丰富。 事件现在携带节点字段(
IsolationScope、Output、Routes、RequestedInput)以及一个 metadata 字段(NodeInfo)。如果你在测试中断言精确的session.Event相等性,请预期这些新字段;自定义会话存储应当持久化它们。 - **
llmagent.New**可能会安装特定模式的工具。 如果你设置了子智能体模式,实际生效的工具集将反映这些模式;task模式的智能体不能用作静态图节点。 - session.NewEvent 接受一个 context。其签名现在为
NewEvent(ctx context.Context, invocationID string)。迁移调用点时,将已在作用域中的context.Context作为第一个参数传入。
这就是完整列表。runner.Run/RunLive、agenttool 以及 llmagent 回调的公开签名均未改变。如需逐步的前后对比说明,请参阅 ADK Go 2.0 迁移指南。
试一试
感受 ADK 2.0 最快的方式就是 全新的工作流示例:
go run ./examples/workflow/basic/
go run ./examples/workflow/routing/llm/ # LLM-as-router
go run ./examples/workflow/dynamic/hitl/ # dynamic + human-in-the-loop
go run ./examples/workflow/hitl_rerun/ # HITL with re-entry resume
go run ./examples/workflow/complex/ # a larger, multi-shape graph
ADK 1.0 证明了用 Go 构建严肃的智能体可以既简洁又高效。ADK 2.0 迈出了下一步:将这些智能体组合成可靠、可观测、可恢复的 工作流——以图的形式,用地道的 Go 编写,并在关键时刻引入人类参与。
我们迫不及待想看到你构建的作品。
—— Go 版 ADK 团队
来源:Google Developers Blog(RSS) · developers.googleblog.com