跳到主要内容

第 4 章:Task API、agent 委派,与全局收尾

本章讲多 agent 怎么协作:一个 agent 怎么把活儿交给另一个。再给巧妙之处、边界、横向对比和代码地图(给 agent/人 的跳转表)。

4.1 三种委派模式(mode)

LlmAgent.mode(agents/llm_agent.py:319)决定一个 agent 被「指挥」的方式:

mode含义默认场景
chat标准对话 agent,可经 transfer_to_agent 接管对话作为根 / 子 agent 默认值
task任务 agent:会多轮和用户对话来完成一个任务显式指定
single_turn不和用户对话、一锤子完成一个子任务作为 workflow 节点时默认

注释明确(llm_agent.py:327):「作为子 agent 默认 chat,作为 workflow 节点默认 single_turn」。Runner 强制根 LlmAgent 必须是 chat(runners.py:1006)。

4.2 sub-agent 按 mode 自动变成工具

关键设计:把子 agent 加进 sub_agents,框架会按子 agent 的 mode 自动把它包成不同的「工具」挂到父 agent 上。看 LlmAgent 构造期(llm_agent.py:1064-1080):

# 真实源码节选 agents/llm_agent.py:1066-1080
if self.sub_agents:
for sub_agent in self.sub_agents:
if isinstance(sub_agent, LlmAgent):
mode = getattr(sub_agent, 'mode', None)
if mode is None:
sub_agent.mode = 'chat'; mode = 'chat'
if mode == 'single_turn':
self.tools.append(_SingleTurnAgentTool(sub_agent)) # 包成单轮工具
elif mode == 'task':
self.tools.append(_TaskAgentTool(sub_agent)) # 包成任务工具
  • chat 子 agent → 经 AutoFlowagent_transfer 处理器,模型可 transfer_to_agent(name) 把控制权整体转交(第 1 章)。
  • single_turn 子 agent → 包成 _SingleTurnAgentTool:父 agent 像调普通工具一样调它,拿到一次性结果。
  • task 子 agent → 包成 _TaskAgentTool:支持多轮任务委派。
  • task 模式 agent 自己构造时还会自动加一个 FinishTaskTool(llm_agent.py:1058),让它能显式宣告「任务完成、产出结果」。

4.3 委派的底层:ctx.run_node + isolation_scope

两种委派最终都落到第 2 章的动态节点机制上。看任务委派分发(workflow/_llm_agent_wrapper.py:135,_dispatch_task_fc):

# 真实源码节选 workflow/_llm_agent_wrapper.py:153-159
await ctx.run_node(
task_agent,
node_input=fc.args, # 模型给的任务参数
override_isolation_scope=fc.id, # 用 function-call id 作隔离作用域
)

isolation_scope 的直觉: 被委派的 task agent 要和用户多轮对话,但这段对话不该污染主协调者的会话视图。isolation_scope(Context 属性,agents/context.py:253)给每个委派一个独立作用域(这里用工具调用的 fc.id),让任务对话与父对话/同侪节点的事件隔离开。task/single_turn agent 共享父分支,靠 isolation_scope 而非 branch 来隔离(_llm_agent_wrapper.py:142-144 注释)。

委派结果被合成回一条 function-response 事件(_synthesize_task_fr_event,_llm_agent_wrapper.py:163),回灌给协调者的对话,模型据此继续。

节点输入转 Content。 _node_input_to_content(_llm_agent_wrapper.py:188)把任意 node_input(str/dict/BaseModel)转成模型能吃的 types.Content,这是「图节点的数据」和「LLM 的对话内容」之间的桥。

4.4 A2A:跨进程的 agent

a2a/ 模块(29 文件)实现 Agent-to-Agent 协议,把远程 agent 暴露/消费为标准接口;agents/remote_a2a_agent.py 是「本地看起来是个 agent,实际请求远端」的代理。依赖可选包 a2a-sdk(pyproject.tomloptional-dependencies.a2a)。本仓库里它建立在同一套 Event/Session 抽象上,细节超出本篇核心范围。

4.5 巧妙之处(可借鉴)

  • mode 驱动的「自动布线」。 你只声明子 agent 的 mode,父 agent 自动把它包成 transfer / 单轮工具 / 任务工具(llm_agent.py:1066)。多 agent 拓扑不用手写胶水。
  • 委派 = 动态节点。 transfer 之外的委派全部复用 ctx.run_node(动态节点),和工作流是同一套调度/恢复机制,而不是另起炉灶——所以任务委派也天然可恢复、可中断。
  • isolation_scope 而非分叉分支来隔离会话。 委派任务共享主分支但用作用域隔离视图(_llm_agent_wrapper.py:142),既隔离上下文又不切断与主对话的关联,便于把结果合成回去。
  • FinishTaskTool 让「任务完成」是显式信号。 task agent 用一次工具调用宣告产出(llm_agent.py:1058),而不是靠启发式猜「它说完了没」。

4.6 边界与局限

  • task 模式不能当静态图节点(_workflow.py:184,_validate_no_task_mode_graph_nodes):调度器重入时会覆盖 node_input,任务简报会丢。只能作 chat 协调者的子 agent,或经 ctx.run_node 动态调起。
  • 老的 SequentialAgent / LoopAgent / ParallelAgent@deprecated(agents/sequential_agent.py:48),功能被 Workflow 取代;新代码别再用。
  • AgentConfig YAML 加载器与 from_config 也已 @deprecated(base_agent.py:650)。
  • 强 Google 取向:默认模型是 Gemini(llm_agent.py:201,DEFAULT_MODEL,本提交实测值为 'gemini-3.5-flash'——注意 README 示例里的 gemini-2.5-flash 只是演示串,不是这个常量的值),很多可选集成是 GCP 服务(pyproject.tomloptional-dependencies.all)。

4.7 横向对比(同 shelf 兄弟)

维度ADK 2.0典型对照
编排模型一切皆节点的图:agent/函数/子图统一 BaseNode,Workflow._run_impl 即调度循环LangGraph 也是图,但 ADK 把单个 agent 也直接做成节点、并把委派复用同一调度
控制流顺序/扇出/扇入/路由/循环都是同一「触发器邮箱」机制的特例多数框架为不同控制流提供不同原语
恢复状态=事件重放结果 + invocation_id 续跑;HITL/长时工具共用暂停通路不少框架靠序列化检查点
agent 委派mode 驱动自动布线(transfer / task / single_turn 工具),底层是动态节点通常需手写「agent as tool」胶水

4.8 代码地图(导航索引)

按符号名 grep 比按行号更抗漂移。

主题文件路径符号名
一切皆节点的基类src/google/adk/workflow/_base_node.pyBaseNodeBaseNode.runBaseNode._run_implSTART
Agent 基类(继承 BaseNode)src/google/adk/agents/base_agent.pyBaseAgentrun_async_handle_before_agent_callbackclone
LLM Agentsrc/google/adk/agents/llm_agent.pyLlmAgentcanonical_modelcanonical_tools_run_async_impl_run_implmode
单 agent 的 agentic 循环src/google/adk/flows/llm_flows/base_llm_flow.pyBaseLlmFlowrun_async_run_one_step_async_preprocess_async_postprocess_async
请求处理器链src/google/adk/flows/llm_flows/single_flow.pySingleFlow_create_request_processors;auto_flow.pyAutoFlow
工具调用执行src/google/adk/flows/llm_flows/functions.pyhandle_function_calls_asyncget_long_running_function_callsREQUEST_EUC_FUNCTION_CALL_NAME
函数→工具自动包装src/google/adk/tools/function_tool.pyFunctionTool_get_declaration
图定义/编译src/google/adk/workflow/_graph.pyGraphEdgefrom_edge_itemsget_next_pending_nodesDEFAULT_ROUTERouteValue
图调度循环src/google/adk/workflow/_workflow.pyWorkflow_run_impl_run_loop_schedule_ready_nodes_buffer_downstream_triggers_make_schedule_dynamic_node_LoopState
动态节点调度器src/google/adk/workflow/_dynamic_node_scheduler.pyDynamicNodeSchedulerScheduleDynamicNode
跑单个节点src/google/adk/workflow/_node_runner.pyNodeRunner_create_child_context_enrich_event_flush_deltas
汇合节点src/google/adk/workflow/_join_node.pyJoinNode_requires_all_predecessors
函数节点/参数绑定src/google/adk/workflow/_function_node.pyFunctionNode_bind_parameters;workflow/_node.pynodeNode
节点状态机src/google/adk/workflow/_node_status.pyNodeStatus(PENDING/RUNNING/WAITING/COMPLETED/FAILED/CANCELLED)
节点运行期把手src/google/adk/agents/context.pyContextrun_nodeoutputrouteisolation_scopestate
入口src/google/adk/runners.pyRunnerrun_async_run_node_async_find_agent_to_runInMemoryRunner
事件模型src/google/adk/events/event.pyEventEventActionsis_final_response_accept_convenience_kwargsNodeInfo
请求人类输入src/google/adk/events/request_input.pyRequestInput
会话/状态存储src/google/adk/sessions/base_session_service.pyBaseSessionServiceappend_event_update_session_state;sessions/session.pySession
应用容器src/google/adk/apps/app.pyAppresumability_configevents_compaction_config
委派分发(task)src/google/adk/workflow/_llm_agent_wrapper.py_dispatch_task_fc_synthesize_task_fr_event_node_input_to_contentprepare_llm_agent_context
task agent 工具src/google/adk/tools/agent_tool.py_TaskAgentTool_SingleTurnAgentTool
完成任务工具src/google/adk/agents/llm/task/_finish_task_tool.pyFinishTaskTool;_task_models.pyTaskRequestTaskResult
跨进程 agentsrc/google/adk/a2a/src/google/adk/agents/remote_a2a_agent.pyA2A 协议接入(可选依赖 a2a-sdk)
工作流样例(最佳学习入口)contributing/samples/workflows/route/fan_out_fan_in/loop/state/request_input/dynamic_nodes/retry/