11预置 Agent 的设计范式
supervisor、plan-execute、DeepAgent 各代表一种组合范式。
adk/prebuilt/supervisor/supervisor.go:101adk/prebuilt/planexecute/plan_execute.go:862adk/prebuilt/deep/deep.go:171三个预置 Agent,三种组合范式
第 7 章你已经跑通了 supervisor、DeepAgent、plan-execute。这一章换个高度:不问”怎么用”,而问”它们各自代表哪一种把 Agent 拼起来的范式”。因为 ADK 的这三个预置件不是三个孤立的工具,而是三种组合哲学的参考实现——读懂它们,你就掌握了搭建任意多智能体系统的三块基本模板。
三种范式可以先用一句话概括:
| 预置件 | 组合范式 | 一句话 | 上下文 |
|---|---|---|---|
| Supervisor | 控制转移(transfer) | 中心调度,接力交棒 | 共享 |
| Plan-Execute | 工作流编排(workflow) | 固定时序,规划→执行→重规划 | 结构化传递 |
| DeepAgent | 智能体即工具(agent-as-tool) | 嵌套调用,隔离执行 | 隔离 |
flowchart TB
subgraph S["Supervisor · 控制转移"]
SUP["主管"] -->|transfer| EA["专家 A"]
EA -->|交回| SUP
SUP -->|transfer| EB["专家 B"]
EB -->|交回| SUP
end
subgraph P["Plan-Execute · 工作流编排"]
PL["Planner"] --> LP["Loop"]
LP --> EX["Executor"] --> RP["Replanner"] --> LP
end
subgraph D["DeepAgent · 智能体即工具"]
MAIN["主 Agent"] -->|"task 工具调用"| SUB["子 Agent(隔离上下文)"]
SUB -->|"返回结果"| MAIN
end
三种组合范式的控制流对比
范式一:Supervisor —— 用”控制转移”组合
supervisor.New(adk/prebuilt/supervisor/supervisor.go:101)代表最直觉、也最”拟人”的组合:一个主管居中,把活派给专家,专家干完交回主管。它的实现只做了一件核心事——给每个子 Agent 包一层强制”转移回主管”的逻辑:
// supervisor.New 内部(简化)for _, subAgent := range conf.SubAgents { subAgents = append(subAgents, adk.AgentWithDeterministicTransferTo(ctx, &adk.DeterministicTransferConfig{ Agent: subAgent, ToAgentNames: []string{supervisorName}, // 干完必须回主管 }))}它建立在控制转移 + 完整上下文共享之上:所有 Agent 泡在同一份 session 里,彼此的中间过程互相可见。这带来”拟人协作”的直觉,但也带来第 9 章讲过的代价——控制流难以隔离、中断难以干净恢复。
⚠️ 它被官方标注 NOT RECOMMENDED,但依然值得读
supervisor.New的文档(adk/prebuilt/supervisor/supervisor.go:98)明确写着 NOT RECOMMENDED:transfer + 共享上下文经验上并未更有效。但它作为”控制转移范式”的最小参考实现,教学价值极高——它让你亲眼看到”共享上下文”这条路走到底是什么样,从而真正理解为什么另外两条路更好。范式本身不因不推荐而失去学习意义。// New creates a supervisor-based multi-agent system with the given configuration.//// In the supervisor pattern, a designated supervisor agent coordinates multiple sub-agents.// The supervisor can delegate tasks to sub-agents and receive their responses, while// sub-agents can only communicate with the supervisor (not with each other directly).// This hierarchical structure enables complex problem-solving through coordinated agent interactions.//// The returned agent is wrapped in an internal container that provides unified tracing.// When used with Runner and callbacks, all agents within the supervisor structure will// share the same trace root, making it easy to observe the entire multi-agent execution// as a single logical unit.//// NOT RECOMMENDED: Supervisor is built on agent transfer with full context sharing,// which has not proven to be more effective empirically. Consider using// ChatModelAgent with AgentTool or DeepAgent instead for most multi-agent scenarios.func New(ctx context.Context, conf *Config) (adk.ResumableAgent, error) {subAgents := make([]adk.Agent, 0, len(conf.SubAgents))supervisorName := conf.Supervisor.Name(ctx)for _, subAgent := range conf.SubAgents {subAgents = append(subAgents, adk.AgentWithDeterministicTransferTo(ctx, &adk.DeterministicTransferConfig{Agent: subAgent,ToAgentNames: []string{supervisorName},}))}inner, err := adk.SetSubAgents(ctx, conf.Supervisor, subAgents)if err != nil {return nil, err}return &supervisorContainer{name: supervisorName,inner: inner,// … 这是 L86–118 的片段(该行不在任何顶层声明内);点击上方「浏览完整文件」
范式二:Plan-Execute —— 用”工作流编排”组合
planexecute.New(adk/prebuilt/planexecute/plan_execute.go:862)代表另一种完全不同的组合思路:不靠模型临场决定”下一个交给谁”,而是用固定的时序结构把几个 Agent 编排起来。它的实现极其诚实地暴露了这一点——它本身几乎没有新逻辑,只是把编排原语拼起来:
// plan_execute.go 的 New(简化)loop, _ := adk.NewLoopAgent(ctx, &adk.LoopAgentConfig{ SubAgents: []adk.Agent{cfg.Executor, cfg.Replanner}, MaxIterations: maxIterations, // 默认 10})return adk.NewSequentialAgent(ctx, &adk.SequentialAgentConfig{ SubAgents: []adk.Agent{cfg.Planner, loop}, // 先规划,再进循环})拆开看就是:Sequential(Planner, Loop(Executor, Replanner))。先跑一次 Planner 出计划,再进入”执行一步 → 重规划”的 Loop。Replanner(adk/prebuilt/planexecute/plan_execute.go:807)判断任务完成时,通过 respond 工具触发 BreakLoopAction 跳出循环。
// NewReplanner creates a plan-execute-replan agent wired with plan and respond tools.// It configures the provided ToolCallingChatModel with the tools and returns an Agent.func NewReplanner(_ context.Context, cfg *ReplannerConfig) (adk.Agent, error) { planTool := cfg.PlanTool if planTool == nil { planTool = &PlanToolInfo }
respondTool := cfg.RespondTool if respondTool == nil { respondTool = &RespondToolInfo }
chatModel, err := cfg.ChatModel.WithTools([]*schema.ToolInfo{planTool, respondTool}) if err != nil { return nil, err }
planParser := cfg.NewPlan if planParser == nil { planParser = defaultNewPlan }
return &replanner{ chatModel: chatModel, planTool: planTool, respondTool: respondTool, genInputFn: cfg.GenInputFn, newPlan: planParser, }, nil}🔑 本章的设计钥匙
Plan-Execute 揭示了一件深刻的事:多智能体的”编排”和 compose 引擎的”编排”是同一套东西。
NewSequentialAgent(adk/workflow.go:686)、NewLoopAgent(adk/workflow.go:704)、NewParallelAgent(adk/workflow.go:695)这几个 workflow 原语,让”Agent 之间怎么走”变成了一张可声明的图——而不是散落在提示词里让模型自己猜。这就是 Eino 的一以贯之:能用确定性结构表达的,就不交给模型即兴发挥。控制转移把时序交给模型,工作流编排把时序交给代码——后者可测、可复现、可推理。// NewSequentialAgent creates an agent that runs sub-agents sequentially.//// NOT RECOMMENDED: Workflow agents are built on agent transfer with full context sharing,// which has not proven to be more effective empirically. Consider using// ChatModelAgent with AgentTool or DeepAgent instead for most multi-agent scenarios.func NewSequentialAgent(ctx context.Context, config *SequentialAgentConfig) (ResumableAgent, error) {return newWorkflowAgent(ctx, config.Name, config.Description, config.SubAgents, workflowAgentModeSequential, 0)}// NewLoopAgent creates an agent that loops over sub-agents with a max iteration limit.//// NOT RECOMMENDED: Workflow agents are built on agent transfer with full context sharing,// which has not proven to be more effective empirically. Consider using// ChatModelAgent with AgentTool or DeepAgent instead for most multi-agent scenarios.func NewLoopAgent(ctx context.Context, config *LoopAgentConfig) (ResumableAgent, error) {return newWorkflowAgent(ctx, config.Name, config.Description, config.SubAgents, workflowAgentModeLoop, config.MaxIterations)}// NewParallelAgent creates an agent that runs sub-agents in parallel.//// NOT RECOMMENDED: Workflow agents are built on agent transfer with full context sharing,// which has not proven to be more effective empirically. Consider using// ChatModelAgent with AgentTool or DeepAgent instead for most multi-agent scenarios.func NewParallelAgent(ctx context.Context, config *ParallelAgentConfig) (ResumableAgent, error) {return newWorkflowAgent(ctx, config.Name, config.Description, config.SubAgents, workflowAgentModeParallel, 0)}
这也解释了为什么 plan-execute 适合”步骤多、需要中途纠偏”的任务:计划是显式的数据,执行是确定的循环,纠偏是循环里的一个固定环节。整条链路你都能静态看懂。
范式三:DeepAgent —— 用”智能体即工具”组合
deep.New(adk/prebuilt/deep/deep.go:171)代表第 9 章推崇的组合方式,也是三者里工程上最推荐的。它的精髓在实现里看得最清楚:所有子 Agent 不是被平铺,而是被一个 task tool 中间件收敛成单个 task 工具(adk/prebuilt/deep/deep.go:131)。
// New creates a new Deep agent instance with the provided configuration.// This function initializes built-in tools, creates a task tool for subagent orchestration,// and returns a fully configured ChatModelAgent ready for execution.func New(ctx context.Context, cfg *Config) (adk.ResumableAgent, error) { return NewTyped(ctx, cfg)}// NewTyped creates a new typed Deep agent instance with the provided configuration.// This function initializes built-in tools, creates a task tool for subagent orchestration,// and returns a fully configured TypedChatModelAgent ready for execution.func NewTyped[M adk.MessageType](ctx context.Context, cfg *TypedConfig[M]) (adk.TypedResumableAgent[M], error) { handlers, err := buildTypedBuiltinAgentMiddlewares(ctx, cfg) if err != nil { return nil, err }
instruction := cfg.Instruction if len(instruction) == 0 { instruction = internal.SelectPrompt(internal.I18nPrompts{ English: baseAgentInstruction, Chinese: baseAgentInstructionChinese, }) }
if !cfg.WithoutGeneralSubAgent || len(cfg.SubAgents) > 0 { tt, err := typedTaskToolMiddleware( ctx, cfg.TaskToolDescriptionGenerator, cfg.SubAgents,
cfg.WithoutGeneralSubAgent, cfg.ChatModel, instruction, cfg.ToolsConfig, cfg.MaxIteration, cfg.Middlewares, append(handlers, cfg.Handlers...), cfg.ModelFailoverConfig, ) if err != nil { return nil, fmt.Errorf("failed to new task tool: %w", err) } handlers = append(handlers, tt) }
return adk.NewTypedChatModelAgent(ctx, &adk.TypedChatModelAgentConfig[M]{ Name: cfg.Name, Description: cfg.Description, Instruction: instruction, Model: cfg.ChatModel, ToolsConfig: cfg.ToolsConfig, MaxIterations: cfg.MaxIteration, Middlewares: cfg.Middlewares, Handlers: append(handlers, cfg.Handlers...),
// … 省略 6 行;完整声明 L113–166,点击上方「浏览完整文件」// NewTyped 内部(简化):把子 Agent 装进一个 task 工具中间件if !cfg.WithoutGeneralSubAgent || len(cfg.SubAgents) > 0 { tt, _ := typedTaskToolMiddleware(ctx, ..., cfg.SubAgents, ...) handlers = append(handlers, tt) // 子 Agent → 一个中间件 → 一个 task 工具}return adk.NewTypedChatModelAgent(ctx, &adk.TypedChatModelAgentConfig[M]{ ... Handlers: append(handlers, cfg.Handlers...),})注意这里的巧妙:DeepAgent 本身就是一个普通 ChatModelAgent,只是通过第 10 章讲的中间件机制,把”调度子 Agent”的能力当作一个工具叠了上去。子 Agent 在隔离上下文里执行,主 Agent 只拿到 task 的返回值。三种能力——可组合、可控、中断可传播——由此而来(实现细节留到第 16 章)。
这个设计的优雅之处在于范式的自洽:它没有引入”多智能体”这个新概念,而是把多智能体还原成了”Agent + 工具 + 中间件”这套已有的原语。少一个概念,就少一处特例。
三种范式如何选
把三者放在一起,选择标准就清晰了:
- 时序由谁定? 模型临场决定 → transfer(supervisor);代码固定 → workflow(plan-execute);主 Agent 按需调用 → agent-as-tool(DeepAgent)。
- 上下文要不要隔离? 要隔离、要可组合、要中断可传播 → DeepAgent(默认首选)。
- 任务是否有清晰的多步骤结构? 有,且需要中途纠偏 → plan-execute。
- 什么时候用 supervisor? 几乎不建议在生产用;但当你想教学式地理解”共享上下文范式”时,它是最好的活标本。
三个预置件,本质是 Eino 递给你的三张模板。真实系统里你常常会混用:一个 DeepAgent 的某个子 Agent,内部可以是一个 plan-execute;一个 workflow 的某个节点,可以挂一个 agent-as-tool。范式是可以嵌套组合的——这正是”组合优于跳转”哲学的红利。
本章小结
- 三个预置 Agent 是三种组合范式的参考实现:supervisor=控制转移、plan-execute=工作流编排、DeepAgent=智能体即工具。
- Supervisor(
adk/prebuilt/supervisor/supervisor.go:101)靠强制”转移回主管”实现中心辐射,共享上下文——NOT RECOMMENDED,但是理解 transfer 范式的活标本。 - Plan-Execute(
adk/prebuilt/planexecute/plan_execute.go:862)=Sequential(Planner, Loop(Executor, Replanner)),揭示”多智能体编排 = compose 工作流编排”。 - DeepAgent(
adk/prebuilt/deep/deep.go:171)把子 Agent 收敛成单个task工具,把多智能体还原为”Agent+工具+中间件”,范式自洽。 - 选择标准:时序由谁定、要不要隔离、有无多步结构;三者可嵌套混用。
设计部分只剩最后一块拼图:v0.9 为什么要把整套 ADK 泛型化?下一章讲 AgenticMessage 与 [M MessageType] 如何让 chat 与 agentic 复用同一体系。