Files

334 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 11. 子 Agent 使用边界和多 Agent 协作
本文用于推进 ZK Data Agent 后续的子 Agent 能力增强。目标不是“让模型更爱开子 Agent”,而是把子 Agent 收敛为一种可靠的编排手段:只在长耗时、可并行、边界清晰、上下文可隔离的任务里使用。
调研日期:2026-06-12。
## 1. 外部实践共识
### 1.1 Anthropic Research:适合宽度优先和并行探索
Anthropic 的 Research 多 Agent 系统采用 lead agent + parallel subagents。Lead agent 负责分析用户问题、制定研究策略,再派出多个 subagent 同时探索不同方向。
它强调几个判断点:
- 多 Agent 特别适合开放式研究,因为研究路径不可提前硬编码,需要根据中间发现动态调整。
- Subagent 可以拥有独立上下文窗口,并行探索不同方面,再把压缩后的结果交回主 Agent。
- 多 Agent 在 breadth-first query 上更有效,尤其是多个方向可以同时查的时候。
- 成本明显更高。Anthropic 提到 agent 通常比普通聊天消耗更多 token,多 Agent 系统消耗更高,因此只适合任务价值足够高的场景。
- 如果所有 Agent 都必须共享同一上下文,或者子任务之间依赖很多,就不适合多 Agent。
参考:https://www.anthropic.com/engineering/multi-agent-research-system
### 1.2 OpenAI Agents SDKhandoff 是专业化分工
OpenAI Agents SDK 的 handoff 用于把任务委托给另一个 Agent,特别适合不同 Agent 专注不同领域的场景。Handoff 本身以 tool 的形式暴露给 LLM,让模型决定是否转交。
这给我们的启发是:
- 子 Agent 不应该只是“再开一个一样的模型”,而应该有明确 profile。
- Profile 描述要告诉模型什么时候使用该 Agent。
- Handoff 可以带输入过滤和动态启用条件,避免把全量上下文无脑传给子 Agent。
参考:https://openai.github.io/openai-agents-python/handoffs/
### 1.3 LangChain / LangGraph:上下文工程比拆 Agent 更重要
LangChain 对多 Agent 的总结非常贴近我们的情况:多 Agent 成败的关键不是数量,而是 context engineering。每个 subagent 需要明确目标、输出格式、工具范围、数据来源和边界,否则容易重复工作、遗漏信息或互相冲突。
另一个重要观点是:以“读”为主的多 Agent 更容易成功,以“写”为主的多 Agent 更难。多个 Agent 同时写代码、写文档或写同一份数据,容易产生冲突;更好的方式是让多个子 Agent 读、查、分析,最后由主 Agent 统一合成和写入。
LangGraph Supervisor 也采用 supervisor-worker 模式:单一 supervisor 负责用户交互,worker agent 只和 supervisor 通信。
参考:
- https://www.langchain.com/blog/how-and-when-to-build-multi-agent-systems
- https://changelog.langchain.com/announcements/langgraph-supervisor-a-library-for-hierarchical-multi-agent-systems
### 1.4 AutoGen:多 Agent 是编排框架,不是默认答案
AutoGen 强调可对话、可定制、可集成工具和人工反馈的 Agent 协作。它适合构建复杂 LLM workflow,但也意味着需要显式设计对话模式、工具权限、人类检查点和终止条件。
对 ZK Data Agent 来说,这说明多 Agent 能力应该服务于“工作流编排”,不能变成模型遇到复杂任务就随意分身。
参考:https://microsoft.github.io/autogen/0.2/docs/Use-Cases/agent_chat/
## 2. ZK Data Agent 当前机制
当前子 Agent 的创建不是后端自动发生的,而是主模型调用 `Agent` 或旧名 `delegate_agent` 工具后触发。
关键链路:
```text
主 Agent 进入 turn loop
-> 模型返回 tool_calls
-> tool_call.name == Agent / delegate_agent
-> _execute_delegate_agent(arguments)
-> 解析 subagent_type / prompt / subtasks / max_turns / allow_write
-> 创建 LocalCodingAgent 子实例
-> 子 Agent 完成后把 child_results / delegate_batches 写回工具结果
-> 主 Agent 继续总结或执行下一步
```
当前实现里的重要约束:
- `subtasks` 最多取前 8 个。
- 子 Agent 默认不能递归调用 `Agent` / `delegate_agent`
- Explore、Plan、verification 等只读 Agent 禁止写文件。
- 写权限需要父 Agent 允许,并且工具参数显式 `allow_write=true`
- 子会话会标记 `session_metadata.visibility = child`,默认不进入左侧主会话列表。
- 右侧活动区通过 `child_results``delegate_batches``dependency_skips` 展示汇总。
相关代码:
```text
src/agent_tools.py Agent 工具 schema 和描述
src/agent_prompting.py 子 Agent 系统提示词注入
src/builtin_agents.py 内置 Agent profile 和 when_to_use
src/agent_runtime.py _execute_delegate_agent / _run_single_subtask
frontend/.../activity-panel 子 Agent 活动汇总展示
```
## 3. 我们的设计定位
ZK Data Agent 里应该有三层能力:
```text
主 Agent
负责用户意图、当前会话状态、Skill 选择、最终决策、最终写入和回复。
Skill
负责领域流程、业务知识、稳定脚本、review 门禁和产物规范。
子 Agent
负责边界清晰的独立子任务,尤其是读、查、分析、验证、候选召回。
```
子 Agent 不是 Skill 的替代品,也不是主 Agent 的替代品。
- Skill 回答“这类业务流程应该怎么做”。
- Tool 回答“这个确定性动作怎么执行”。
- 子 Agent 回答“这个可隔离子任务能不能交给另一个 Agent 独立完成”。
## 4. 什么时候应该优先使用子 Agent
### 4.1 明显适合
满足下面多个条件时,可以优先考虑子 Agent:
| 判断项 | 说明 | 示例 |
|---|---|---|
| 长耗时 | 主 Agent 直接串行做会占用很多轮 | 查多个索引、读大量文件、批量分析 badcase |
| 可并行 | 子任务之间没有强依赖 | 同时分析 5 个 rid、同时对比 3 个标签边界 |
| 可隔离 | 子任务只需要一小段输入,不依赖完整上下文 | 只给某个文件路径、某个 request_id、某个候选集合 |
| 读多写少 | 子任务主要是检索、阅读、总结、验证 | Explore / Plan / verification |
| 输出可压缩 | 子 Agent 结果能用结构化摘要交回主 Agent | 输出发现、证据、风险、建议 |
| 价值足够高 | 多消耗 token 和时间是值得的 | 线上事故排查、复杂数据策略、发布前验证 |
典型场景:
- 多个 request_id / session / badcase 可以独立排查。
- 多个文件目录需要分别探索,再合并成架构判断。
- 一个任务需要先从多个候选方向召回证据。
- 非平凡代码修改后,需要 verification agent 独立跑测试和检查。
- 上下文窗口快满,且有一个清晰阶段可以交给新上下文继续探索。
### 4.2 可以使用,但需要谨慎
这些场景可以用子 Agent,但必须限制边界:
- 需要生成多个候选方案,但最后只能采用一个方案。
- 需要多个 Agent 分别给 review 意见,但最终修改只能由主 Agent 做。
- 需要长时间跑工具或搜索,但要避免子 Agent 自己继续扩散任务。
- 需要子 Agent 写临时文件,必须限定在当前 session 的 scratchpad 或 output,并明确 `allow_write=true`
### 4.3 不应该使用
这些场景默认不要开子 Agent
| 场景 | 原因 |
|---|---|
| 一次普通问答或一次工具调用 | 额外开 Agent 只会增加延迟和 token |
| 强依赖连续上下文 | 子 Agent 容易拿不到主会话里的隐含状态 |
| 子任务之间依赖链很长 | 调度成本高,失败恢复复杂 |
| 多个 Agent 同时写同一份产物 | 容易冲突,合并困难 |
| 需要和用户持续互动 | 子 Agent 的交互会割裂主会话体验 |
| 主 Agent 自己还没想清任务边界 | 边界不清时拆出去只会放大混乱 |
| 业务流程已有明确 Skill | 应先用 Skill,而不是直接用通用子 Agent |
## 5. 子 Agent 调用前检查表
主 Agent 在调用 `Agent` 前,应在内部完成这个检查:
```text
1. 这个任务能否直接用一个工具完成?
能 -> 不开子 Agent。
2. 这个任务是否命中明确 Skill?
是 -> 先调用 Skill,除非 Skill 内明确建议拆子 Agent。
3. 是否存在独立子任务?
没有 -> 不开子 Agent。
4. 子任务是否可以用少量输入描述清楚?
不能 -> 不开子 Agent,先由主 Agent 整理上下文。
5. 子任务结果是否能用结构化摘要交回?
不能 -> 不开子 Agent。
6. 子任务是否主要是读、查、分析、验证?
是 -> 适合。
否 -> 需要明确写权限、路径和合并策略。
7. 是否有并行收益或上下文隔离收益?
没有 -> 不开子 Agent。
```
## 6. 子 Agent Prompt 契约
每次委托都应该给子 Agent 一个完整契约。不要只写“帮我看看这个”。
推荐格式:
```text
任务目标:
你要完成什么,不要做什么。
输入材料:
文件路径、request_id、query、候选数据、时间范围等。
上下文边界:
只依赖这些输入;不要假设完整主会话上下文。
允许动作:
只读 / 可运行命令 / 可写临时文件 / 可写 output。
禁止动作:
不修改平台代码;不提交 git;不改非本 session 文件。
输出格式:
用固定字段返回,例如 findings、evidence、risks、next_actions。
失败处理:
找不到数据时说明尝试过的路径和下一步建议。
```
示例:
```text
请作为只读 Explore 子 Agent,分析 request_id=xxx 的线上日志。
只允许读取 ELK 查询结果和当前 session 文件,不写文件。
目标是判断是否能还原 query、prev_session、模型 prompt、模型输出。
输出 JSON
{
"request_id": "...",
"found_fields": [],
"missing_fields": [],
"evidence": [],
"recommended_next_query": ""
}
```
## 7. 和 Skill 的组合方式
### 7.1 Skill 内可以建议子 Agent,但不应该滥用
Skill 可以在流程里写:
- 当候选样本超过一定数量,可以用 Explore 子 Agent 并行抽样。
- 当多个 rid 独立排查,可以每个 rid 一个子 Agent。
- 当生成数据前需要多标签边界 review,可以让多个只读子 Agent 分别分析边界。
但 Skill 不应该写:
- 每次执行都必须开子 Agent。
- 所有生成都交给子 Agent。
- 让多个子 Agent 同时写最终数据。
### 7.2 主 Agent 负责最终合成
推荐模式:
```text
子 Agent A:查证据
子 Agent B:查另一批证据
子 Agent C:做只读验证
-> 主 Agent 汇总
-> 主 Agent 决定下一步
-> 主 Agent 调脚本写最终产物
```
不推荐:
```text
子 Agent A 写一半数据
子 Agent B 写另一半数据
子 Agent C 修改格式
-> 主 Agent 被动猜测哪个文件是最终版
```
## 8. UI 和可观测性原则
子 Agent 不应该像普通会话一样挤进左侧列表。用户关心的是:
- 主任务有没有拆子任务。
- 拆了几个。
- 每个子任务是否完成、失败、跳过。
- 每个子任务的关键发现是什么。
- 必要时能 drill down 到子会话详情。
因此 UI 默认应该:
- 左侧会话列表只显示主会话。
- 右侧活动区展示子 Agent 汇总、批次、子任务摘要。
- 子 Agent 详情默认折叠。
- 子 Agent 输出应该有结构化摘要,不展示完整长日志。
## 9. 后续增强方向
### P0:收敛提示词和工具描述
- 在系统提示词里明确“子 Agent 不是默认策略”。
- 把“适合/不适合”的判断表加入子 Agent 指导。
- `Agent` 工具描述中补充:优先用于独立、可并行、长耗时、读多写少的子任务。
- 对 product-data、online-mining-v2、label-master 的 Skill 文档增加是否建议子 Agent 的边界。
### P1:结构化委托和活动展示
-`Agent` 参数增加更明确的 `output_contract``expected_fields`
- 活动区展示子任务输入、状态、摘要、失败原因。
- 支持从活动区打开 child session,但默认隐藏。
- 对运行中的子 Agent 做更稳定的 live event 汇总。
### P2:策略控制和评估
- 增加每轮最多子 Agent 数量、并发数、总 token 预算。
- 增加“只读子 Agent”默认模式。
- 记录每次子 Agent 的收益:是否减少主任务耗时、是否提升结果质量、是否造成失败。
- 建立小型 eval:同一任务单 Agent vs 子 Agent,对比准确率、耗时、token、用户体验。
### P3:业务化多 Agent
- online-mining-v2:多个 rid / 多个索引方向并行探索。
- label-master:多个候选标签边界并行查证,然后主 Agent 汇总裁决。
- product-data:批量数据质量 review 可并行,但最终 records 写入必须由主 Agent 或确定性脚本完成。
## 10. 当前建议
短期不要把多 Agent 做成自动默认能力。更稳的路线是:
```text
默认:主 Agent + Skill + Tool
遇到明确并行探索 / 独立验证 / 长耗时检索
-> 主 Agent 显式调用子 Agent
-> 子 Agent 只返回结构化摘要
-> 主 Agent 合成、写入、回复
```
一句话原则:
```text
子 Agent 负责把复杂任务拆成可独立完成的观察和验证;
主 Agent 负责保持用户上下文、做最终决策和产物写入。
```