恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Agent Zero 子代理委托机制全解析:call_subordinate 工具的设计、契约与运行原理
首页
资讯中心
/
Agent Zero 子代理委托机制全解析:call_subordinate 工具的设计、契约与运行原理
Agent Zero 子代理委托机制全解析:call_subordinate 工具的设计、契约与运行原理
发布时间:2026/9/14 22:29:35
Agent Zero 子代理委托机制全解析call_subordinate 工具的设计、契约与运行原理【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero本文聚焦 Agent Zero 框架中负责任务委派的核心工具call_subordinate。它允许主代理superior agent将研究、复杂子任务委托给一个独立的子代理subordinate agent并等待其返回最终结果。通过本文你将掌握该工具的完整参数契约message、profile、reset、子代理的创建与复用逻辑、RepairableException纠错机制以及它与历史压缩、日志系统、中断传播intervention flow之间的底层协作方式。一、call_subordinate在 Agent Zero 中的定位在 Agent Zero 的多代理架构中一个会话context内可以同时存在多个Agent实例它们通过data对象上的两个指针相互绑定Agent.DATA_NAME_SUPERIOR _superior子代理持有的指向上级代理的引用Agent.DATA_NAME_SUBORDINATE _subordinate上级代理持有的指向子代理的引用。这两个常量定义在 agent.py。call_subordinate工具正是这套上级/下级关系的最主要建立入口主代理在自主决策循环中调用它把一段任务文本注入子代理让子代理独立运行一轮monologue()再把结果回传给主代理。从 prompts/agent.system.tool.call_sub.md 中对模型暴露的工具描述可以看到它被设计为将研究或复杂子任务委托给专门的代理典型的应用场景是在继续主任务前需要聚焦的外部研究需要不同提示词画像profile的专业分工例如把研究意大利 AI 趋势这类任务交给researcher画像的代理处理。其实现文件为 tools/call_subordinate.py配套的维护说明文档为 tools/call_subordinate.py.dox.md后者明确了该模块的职责边界call_subordinate.py拥有运行时实现DOX 文档负责记录职责、契约、副作用与验证方式。二、工具参数契约message、profile、resetDelegation类继承自 helpers/tool.py 中的Tool基类其execute方法签名如下async def execute(self, message, reset, **kwargs):结合工具提示词三个核心参数的含义如下参数类型说明注意事项messagestring委托任务的具体描述应同时定义角色role、目标goal和具体任务concrete taskprofilestring可选子代理使用的提示词画像键必须精确匹配可用画像名留空则使用默认画像resetstringjson boolean 字符串是否重建子代理首次调用或更换画像时为true继续对话时为false其中profile同时兼容profile与agent_profile两个键名通过kwargs.get(profile, kwargs.get(agent_profile, ))读取提高了与其它代理画像 API 的兼容性。工具提示词给出的标准调用示例{ thoughts: [Need focused external research before I continue.], headline: Delegating research subtask, tool_name: call_subordinate, tool_args: { profile: researcher, message: Research Italy AI trends and return key findings., reset: true } }提示词还要求主代理在子代理返回结果后直接依据该结果作答只要它已经满足用户请求就不要重复做同样的求解工作或再调用额外工具。三、子代理画像的校验与纠错机制Delegation.execute首先调用模块顶层的两个辅助函数1._subordinate_profile_labels(agent: Agent) - dict[str, str]def _subordinate_profile_labels(agent: Agent) - dict[str, str]: project projects.get_context_project_name(agent.context) if agent.context else None return { name: subagent.title or name for name, subagent in subagents.get_available_agents_dict(project).items() }它返回画像键 - 显示标题的映射。数据来源是 helpers/subagents.py 中的get_available_agents_dict(project_name)该方法会按默认 → 插件 → 用户 → 项目的优先级合并各来源的代理清单agents/、插件内的agents目录、usr/agents/、项目的agents目录并依据项目设置过滤掉被禁用的画像。这也是工具提示词末尾{{agent_profiles}}占位符能动态列出available profiles的底层依据。2._validate_subordinate_profile(agent: Agent, profile: str) - strdef _validate_subordinate_profile(agent: Agent, profile: str) - str: agent_profile str(profile or ).strip() if not agent_profile: return labels _subordinate_profile_labels(agent) if agent_profile in labels: return agent_profile ... raise RepairableException( fAgent profile {agent_profile} not found. Use one of the available profiles: {available}. )校验规则可以总结为三点空画像被静默归一为表示使用默认画像合法画像名被原样返回并做了strip()归一化未知画像抛出 helpers/errors.py 中的RepairableException异常消息中会列出所有可用画像key (label)形式从而引导模型在下一次调用中改用真实存在的画像——这正是 DOX 文档所述agent 可以重试的纠错闭环。RepairableException是 Agent Zero 专为模型可自行修复的错误设计的异常类型区别于需要人工介入的硬错误这一点在 tests/test_subagent_profiles.py 的test_call_subordinate_rejects_unknown_profile中得到了验证传入profileghost时断言抛出Agent profile ghost not found且父代理的data保持为空未被污染。四、子代理的创建、复用与切换reset 的语义execute的核心流程分为三个步骤。1. 冲突检测防止静默切换画像existing_subordinate self.agent.get_data(Agent.DATA_NAME_SUBORDINATE) reset_requested str(reset).lower().strip() true if existing_subordinate and requested_profile and not reset_requested: current_profile str(getattr(getattr(existing_subordinate, config, None), profile, ) or ) if current_profile ! requested_profile: raise RepairableException( fSubordinate already uses profile {current_profile or default}. fSet resettrue to switch to {requested_profile}. )如果已存在一个子代理而本次调用指定了不同的画像且没有传resettrue工具会抛出RepairableException而不是静默替换旧子代理——这避免了会话上下文中的子代理状态被无意识地破坏。该行为由 tests/test_subagent_profiles.py 的test_call_subordinate_requires_reset_to_change_existing_profile覆盖验证。2. 创建或复用子代理if existing_subordinate is None or reset_requested: override_settings {agent_profile: requested_profile} if requested_profile else None config initialize_agent(override_settingsoverride_settings) sub Agent(self.agent.number 1, config, self.agent.context) sub.set_data(Agent.DATA_NAME_SUPERIOR, self.agent) self.agent.set_data(Agent.DATA_NAME_SUBORDINATE, sub)只有在没有现存子代理或显式resettrue两种情况下才重建通过 initialize.py 中的initialize_agent(override_settings...)生成新配置agent_profile覆盖项会透传到settings.merge_settings最终形成携带指定profile的AgentConfig见initialize.py中AgentConfig(profilecurrent_settings[agent_profile], ...)的构造逻辑新子代理的编号为self.agent.number 1并复用父代理的context从而共享同一会话上下文随后双向注册子代理记录上级self.agent上级记录子代理sub。3. 注入消息并运行 monologuesubordinate: Agent self.agent.get_data(Agent.DATA_NAME_SUBORDINATE) subordinate.hist_add_user_message(UserMessage(messagemessage, attachments[])) result await subordinate.monologue()message会被包装为UserMessage定义见 agent.py追加到子代理历史中随后子代理异步运行自己的完整决策循环monologue()返回其结果字符串。resettrue语义在测试test_call_subordinate_uses_valid_profiletests/test_subagent_profiles.py中被验证调用后父代理的_subordinate数据存在、其config.profile为developer且注入的消息文本正确进入子代理消息列表。五、主题封存与长结果提示子代理运行完毕后有两处容易被忽略但重要的收尾逻辑1. 封存当前主题subordinate.history.new_topic()这一行将子代理当前的主题topic封存使其消息进入topics集合以便后续压缩compression。也就是说每次call_subordinate完成一轮委托都会在子代理侧开启一个新主题边界防止历史无限膨胀——这与 Agent Zero 的历史压缩机制见helpers/history.py与tests/test_chat_compaction.py相关逻辑是配套的。2. 长结果 include 提示if len(result) save_tool_call_file.LEN_MIN: hint self.agent.read_prompt(fw.hint.call_sub.md) if hint: additional {hint: hint}当子代理返回的结果长度达到 extensions/python/hist_add_tool_result.py 中_90_save_tool_call_file的LEN_MIN阈值时工具会读取 prompts/fw.hint.call_sub.md 中的提示文案内容为do not rewrite long responses, use §§include( ) instead!作为additional附加信息交给Tool.after_execution最终通过hist_add_tool_result写入历史。这样长输出会被落盘为文件后续上下文引用时使用§§include(path)语法复用而不是把超长文本重复写进模型上下文。六、返回值契约Response 与 break_loopexecute的返回值为return Response(messageresult, break_loopFalse, additionaladditional)Response数据类定义在 helpers/tool.pydataclass class Response: message: str break_loop: bool additional: dict[str, Any] | None Nonemessage子代理的最终输出作为工具结果进入主代理历史break_loopFalse委托完成不主动打断主代理的决策循环——是否需要继续由主代理根据结果自行判断additional可选附加信息如长结果 include 提示由Tool.after_execution透传给hist_add_tool_result见 helpers/tool.py。七、日志对象可观测性设计Delegation覆写了get_log_object与Tool基类的默认实现以icon://construction标记工具调用不同def get_log_object(self): return self.agent.context.log.log( typesubagent, headingficon://communication {self.agent.agent_name}: Calling Subordinate Agent, content, kvpsself.args, )它使用typesubagent类型和icon://communication图标将调用子代理这一动作在会话日志中独立标记方便在前端 UI 中区分普通工具调用与代理间通信kvpsself.args记录了本次调用的全部参数供审计。该日志对象由Tool.before_execution创建见 helpers/tool.py并在after_execution中更新内容为工具结果。八、与中断传播Intervention Flow的协作call_subordinate建立的上下级关系并非只用于委托也参与了中断消息的传播。在 agent.py 的communicate方法中intervention_agent current_agent while intervention_agent and broadcast_level ! 0: intervention_agent.intervention msg broadcast_level - 1 intervention_agent intervention_agent.data.get(Agent.DATA_NAME_SUPERIOR, None)当用户发送干预消息时会沿着_superior指针链逐级向上广播。此外agent.py 中的_process_chain展示了上下级关系在会话从文件恢复场景下的关键作用如果聊天从磁盘加载、原始调用栈已丢失子代理完成后会通过superior agent.data.get(Agent.DATA_NAME_SUPERIOR, None)找到上级并把结果作为call_subordinate的工具结果递归回传保证恢复后的会话仍能继续原有的委托链。DOX 文档中Observed side-effect areas: filesystem writes, settings/state persistence所指的副作用也主要来自子代理自身运行过程中的工作目录写入与设置/状态持久化。九、验证与测试契约的守护DOX 文档列出了两个关联测试文件它们在仓库中的具体验证点如下测试文件验证内容tests/test_subagent_profiles.py未知画像抛RepairableException合法画像正确创建子代理并注入消息切换画像必须resettrue聊天序列化/反序列化往返后各代理profile保持test_persist_chat_roundtrip_preserves_each_agent_profile切换主代理画像不影响既有子代理画像test_agent_profile_set_preserves_subagent_profiletests/test_default_prompt_budget.py默认提示词预算相关契约确保提示词体积控制在上下文窗口预算内测试中大量使用monkeypatch替换Agent、initialize_agent、_subordinate_profile_labels等依赖说明该工具具备良好的可测试性——核心逻辑校验、创建、消息注入与底层框架解耦可在不启动完整运行时的情况下做单元级验证。十、实践建议正确使用 call_subordinate综合提示词契约与源码实现使用该工具时有几条值得遵循的规则首次委托必带resettrue只有显式重置才会创建全新子代理不带reset且无现存子代理时也会创建但带上true语义最清晰。切换画像必须resettrue否则会收到RepairableException并要求补充resettrue这是保护旧子代理状态的刻意设计。message要写清角色、目标与具体任务子代理拿到的是独立的完整任务而不是主代理的上下文摘录。长结果交给§§include(path)超过阈值的结果会自动落盘并附带 include 提示不要在后续回复中重写超长输出。在子代理结果已满足请求时直接作答避免重复求解或调用多余工具这也是工具提示词对模型行为的硬性要求。【免费下载链接】agent-zeroAgent Zero AI framework项目地址: https://gitcode.com/GitHub_Trending/ag/agent-zero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考