资讯详情

AI Agent与Subagent协作实战:任务分发、上下文管理与结果校验的稳定范式

📅 2026/10/21 2:56:52 | 华诺云谱 👁 阅读
AI Agent与Subagent协作实战:任务分发、上下文管理与结果校验的稳定范式
说实话提到 AI Agent 和 Subagent 的协作我最早是持怀疑态度的。大概两三个月前我接手了一个任务把几十份格式混乱的行业资料整理成结构化问答库。一开始我用单个 AI Agent 跑前面几轮效果还行但随着材料累积问题立刻暴露——上下文窗口被塞满它开始把 A 文档的结论安到 B 文档身上甚至重复输出已经给过的答案。当时同事建议不如拆成多个 Subagent各自处理一块 我想着这不过就是主 Agent 派活、子 Agent 干活结果一上手就连续踩坑前后重构了两版才稳定下来。这篇文章就是我从多次翻车到基本跑稳的完整复盘聊聊 Agent 和 Subagent 到底是怎么协作的哪些环节最容易出问题以及我最后沉淀下来的那套协作约定。标题讲的是协作但本质是在解决三件事怎么把大任务拆出去、怎么把必要的信息交出去、怎么把结果可靠地收回来。文章适合所有正在用 Agent 做自动化任务的人尤其是那些已经发现嵌套子代理跑得很欢结果却一塌糊涂的朋友。如果你还没开始用 Subagent这篇文章也能帮你少走很多弯路。1. 单 Agent 卡壳的本质不是能力不够而是上下文在打架1.1 一个典型的多任务场景那批资料包含几十份文档有扫描件转出的文本、有表格、有会议纪要。如果全部塞给一个 Agent 去读完并整理会出现一个很尴尬的矛盾你希望它保持全局视角但它同时只能处理有限的上下文。实测中当输入材料累积到接近窗口上限时模型的注意力会明显下降具体表现就是前后矛盾、遗漏关键数字、把不同来源的信息混在一起。这其实不算模型的能力问题而是信息太多导致的注意力稀释。类比一下让一个人同时盯几十块监控屏幕他一定会漏看和串台。所以从方向上来说把任务拆给多个 Subagent 是对的。但问题出在后面三步——怎么拆、怎么传、怎么收。这三步没设计好拆了反而比不拆更糟。1.2 委派机制真正解决的是什么很多文章把 Subagent 说得特别玄什么自主规划、自主决策。以我实际项目里的体会它的价值其实可以归纳成三条上下文隔离每个子代理只处理自己负责的那块材料避免无关信息互相干扰。职责聚焦子代理的提示词可以只围绕单一任务不需要在它头上压一堆全局约束。并行潜力互不依赖的子任务可以同时跑整体耗时能明显压下来。但这三条优势没有一个会自动生效。如果主 Agent 委派时把整段对话历史原封不动传给子代理那上下文隔离从根上就失效了如果任务描述写得模棱两可子代理就会按自己的理解脑补这时候职责聚焦也成了一句空话。我发现很多团队在引入 Subagent 时看中的是并行潜力却忽略了前两条才是稳定性的关键最后并行没吃到红利反而多了不少协调成本。1.3 最典型的错误认知我见过不少方案包括我自己最初那版设计思路都是这样的主 Agent 拿到一个复杂需求先写一段自然语言帮我把这个任务拆一下然后把拆出来的子任务再塞给下一层 Agent下一层如果觉得任务还不够小就继续往下拆。听上去很自动化在实际跑起来之后问题会一个个浮现拆出来的子任务不一定比原来的任务更清楚只是变得更碎。每一层转述都会丢信息、添油加醋任务目标传到第三层时已经偏离原意。没有任何机制保证最终的结果能拼回主任务的目标。这就是看起来很智能用起来很崩溃的来源。走到这一步我才真正意识到Agent 和 Subagent 之间需要的不是更自由的对话而是一套具备约束力的协作协议。自由对话适合人跟人之间因为人有常识、有默契但模型每次调用都是全新的人它不会自动继承你的全局意图。把意图显式写清楚是整个协作设计的第一原则。2. 协作的三段式链路任务分发、上下文交割、结果回收要把协作做得稳定我的做法是把主 Agent 与子 Agent 之间的交互切成三段任务分发、上下文交割、结果回收。每一段都有明确的产出物和检查点缺一段都会出问题。2.1 任务分发别用一句话派活先看看最常见的做法你负责整理 PDF 里的财务数据整理好给我。 这句话在传统职场里都很难保证不出错更别说是让模型去执行。模型会默认补充很多你没想到的细节然后给你一份看似完整、实则跑偏的输出。我现在验证过最稳定的任务分发是一份结构化任务单。下面是一个简化版示例字段不一定全但思路可以参考{ subtask_id: subtask_001, objective: 从 input_doc_03 中提取 2023 年度的所有成交额数据按月份输出, input_ref: [storage://docs/input_doc_03.txt], constraints: [ 只使用 input_ref 指向的材料不得引入外部推测, 如果原文没有明确月份标注 null 而不是猜测 ], output_schema: { type: array, items: { month: string, amount: number } }, acceptance_criteria: [ 覆盖 1 到 12 月缺失的月份必须显式列出并标记为 missing, 金额保留两位小数, 金额单位为万元 ], max_retries: 2 }这里最关键的是最后两项。output_schema告诉子代理交什么作业acceptance_criteria定义了什么才算合格作业。没有这两个字段子代理大概率自由发挥你事后还得花大量精力清洗和兜底。从实战角度说任务单里的每一项最好都能被自动校验。覆盖 1 到 12 月就比把数据整理完整实用得多因为它是可检查的金额保留两位小数也比输出规范可执行。凡是不能校验的要求本质上都是在给模型留模糊空间。2.2 上下文交割只传必要的不传全部的第二个容易踩的坑是为了让子代理理解全局主代理把整段对话历史、其他子代理的输出也一并塞给它。这样做的结果通常是三连token 消耗暴涨子代理的注意力被无关信息干扰反而忽略了真正要处理的内容多个子代理各拿一份大上下文时成本线性叠加甚至更高。我的做法是在任务单之外单独维护一份上下文卡片。它包含三个部分任务背景摘要用三到五句话讲明白这份材料在整个大任务里的位置本子任务需要的局部事实比如相关文档的编号、需要重点关注的关键段落明确排除的信息比如不需要处理 2022 年及以前的数据。这份上下文卡片不是让主 Agent 随口生成的而是按固定格式生成。理想情况下上下文卡片的长度控制在 500 token 以内。如果某个子任务确实需要读全文那就传文件引用路径让子代理按需读取而不是把全文复制进上下文。这个习惯帮我省下的成本相当可观后面第 5 章会详细算。2.3 结果回收把子代理的输出当代码提交看待子代理返回结果时它自己通常自信满满但千万别直接采信。我在内部推行的原则是把子代理输出当成一次代码提交来审核而不是当成最终答案。审核分三步第一步是格式校验按output_schema检查结构不对直接打回第二步是自洽性校验比如数字之间是否互相矛盾、是否有明显越界值第三步是交叉核对如果任务单要求对照原文档就把关键字段和源材料再做一次比对这一步可以由主 Agent 完成也可以用代码里的规则完成。任何一步没过都应该把具体失败原因写回任务单重新委派给子代理修正。这里有个关键细节反馈要具体。不要说结果不对请重试要说3 月和 4 月的成交额缺失且 5 月的金额没有保留两位小数。模型对具体修正指令的响应比对笼统的再来一遍要敏感得多。原因也不难理解模型需要知道差异在哪里而不是单纯被要求重复劳动。3. 实测踩坑复盘一次三层嵌套设计引发的连环翻车3.1 背景与最初的设计为了防止纸上谈兵分享一段真实的踩坑经历。当时我在做一个模拟项目目标是把几十份项目文档整理成统一格式的知识库问答条目。第一版我设计成了三层结构主 Agent负责理解整体需求、做任务规划中层 Agent负责把主 Agent 发来的子任务再拆成更细的步骤当时我觉得这样更专业底层 Agent真正执行读取文档、生成条目的工作。理论上这像是一个正经公司的三层汇报体系。但实际跑起来三层结构几乎没有带来任何好处反而触发了一连串事故。现在回头看这根本就是把组织管理的直觉错误地搬到了 Agent 协作里——公司里加管理层可以减少沟通成本但模型之间加中层只会增加信息损耗。3.2 第一轮翻车任务目标在传递中漂移第一轮事故相当典型。主 Agent 给中层 Agent 派的任务是基于 2023 年度文档生成知识条目。中层 Agent 为了把任务拆得更细自作主张地在委派单里加了一句重点关注团队与协作相关内容。这句补充是它自己根据文档标题推测出来的并不是主 Agent 的本意。于是底层 Agent 交回来的条目大量聚焦在团队协作流程而整体需求里占比最大的数据指标说明反而被漏掉了。最后我核对成果时发现产出的知识条目和项目需求对不上只能返工。排查时看日志中层 Agent 的输出里有一行它的自我理解与主任务的原意已经有了明显偏差。这类偏差不是模型坏而是每一层转述都在做有损压缩层数越多损失越大。语言模型在转述时总会加入自己的推测性补充这是它的工作方式你不能怪它只能从结构上减少转述次数。3.3 第二轮翻车上下文拼接爆炸三层结构还有另一个隐藏问题。为了让底层 Agent 能准确处理每一份文档我当时采用的策略是主 Agent 把所有文档的核心段落传给中层中层再原样传给底层。结果就是每一层都在重复携带同一份巨大的上下文。跑了几次任务之后我统计了一下单轮整理的 token 消耗大约是单 Agent 方案的 4 到 5 倍。更尴尬的是上下文变大并没有带来更准的输出因为大量无关段落在底层 Agent 那里只是徒增噪音。一段时间里接口费用涨得很快项目差点被叫停。这个问题的根子就是没有做上下文按需裁剪把隔离做成了扩散。很多初学者会复制同样的错误以为上下文传得越全模型就越聪明。但在实际体验里给模型塞一堆无关内容效果等同于让一个人带着一堆不相干的文件开会他反而找不到真正需要的那张纸。3.4 第三轮翻车子代理擅自创建子代理出现循环委派第三轮最离谱。某次一个底层 Agent 在读取文档时发现有一小段表格无法解析它没有按约束直接标记无法识别而是自己又创建了一个新的子代理让新子代理帮忙解析表格。新子代理拿到任务后又把问题抛回给了原来的底层 Agent。日志里能看到连续几十次创建新子代理的记录任务迟迟不结束。虽然我设置了单次请求的超时但整个流程的编排层没有做最大深度限制导致它在超时前消耗了大量 token还拖慢了整个任务队列。这轮事故给我的教训非常直接不要让子代理拥有无限的创建权。无论是工程约束还是调度策略都必须限制递归深度最好直接禁止子代理再建子代理。不要指望模型在运行中去自我克制它没有这种长期自控能力约束必须写死在外层代码里。3.5 三轮翻车的小结把这轮复盘整理成一张表方便自查问题表现根因关键修复任务漂移产出与主需求不符多层转述损失信息中层擅自补充目标减少层级用结构化任务单固定目标上下文爆炸token 成本 4-5 倍输出质量下降未经裁剪的上下文全量传递上下文卡片按需供给控制长度循环委派子代理不断创建新子代理缺少深度限制与禁止递归规则限制最大深度禁止子代理创建子代理这张表现在还贴在我工作台旁边每次设计新的 Agent 协作方案时我都会照着这三行检查一遍踩过的坑就不再踩第二次。4. 目前验证过最稳的协作范式扁平化委派 结构化任务单 校验环踩完坑之后我重构方案时就盯着三条原则层级要扁、任务单要结构、结果要验证。三件事缺一不可。4.1 扁平化最多两层禁止往下再建目前我所有在跑的任务都遵守这条硬规矩主 Agent 可以直接管理多个子代理但子代理不允许自行创建子代理。如果某个子任务仍然太大由主 Agent 负责把它二次拆分成更小的委派单而不是让子代理自行去外包。这样做的好处有三个信息损耗可控主 Agent 到子代理只有一跳任务目标不会经过多轮转述排查简单出了问题只需要检查主 Agent 和对应子代理之间的单次通讯不用追一整条委派链成本可控不会出现无法预测的递归扩张。如果业务场景真的需要多级分解比如主任务极其复杂那也应该由编排层代码去分步调度而不是靠 Agent 自主递归。代码层做分解和 Agent 自主递归是两回事前者每一步都可控后者随时可能失控。这句话是我用真金白银买来的经验。4.2 任务单与上下文卡片的完整示例下面是一个我在用的任务单模板去掉了具体业务信息保留通用结构{ subtask_id: subtask_004, objective: 根据 docs/contract_2023.md生成 5 条面向用户的问答条目, context_card: { background: 这批问答条目用于某企业内部知识库用户为非技术岗位, local_facts: [ contract_2023.md 第 3 节是付款条款, 第 5 节是违约责任, 不要引入合同之外的价格信息 ], excluded: [ 不需要解读 2022 年旧合同 ] }, constraints: [ 每条回答不超过 120 字, 必须引用原文中的具体条款编号 ], output_schema: { type: array, items: { question: string, answer: string, clause_ref: string } }, acceptance_criteria: [ 条目数量不得少于 5 条, 每条 answer 必须包含 clause_ref ], max_retries: 2, forbidden_actions: [ 禁止创建任何新的子代理来处理本任务 ] }注意最后那个字段forbidden_actions。它专门用来阻断子代理创建子代理的路径。别小看这一行它能在运行日志里给你一条明确的判断依据——一旦出现违反 forbidden_actions 的操作直接判定任务失败不给模型狡辩的机会。4.3 校验环反馈要带着证据校验环节的代码思路很简单但比代码本身更重要的是错误信息要具体def validate_result(subtask, result): errors [] # 1. 结构校验 if not isinstance(result, list): errors.append(输出不是数组和 output_schema 不一致) # 2. 数量校验 if len(result) subtask[acceptance_criteria][0]: errors.append(条目数量不足) # 3. 关键字段校验 for item in result: if not item.get(clause_ref): errors.append(存在缺少 clause_ref 的条目) return errors def dispatch_with_retry(subtask): for attempt in range(subtask[max_retries]): result call_subagent(subtask) errors validate_result(subtask, result) if not errors: return result # 把具体的错误反馈写回任务单 subtask[feedback] ; .join(errors) raise TaskFailed(subtask[subtask_id])这里的核心模式是errors必须带着具体原因重新委派时把这些原因写进新的任务单。模型在收到3 月和 4 月成交额缺失5 月金额未保留两位小数这类反馈后修正成功率会明显高于收到结果不合格请重试。因为前者指出了明确的修正方向后者只是告诉它你又错了。4.4 为什么这套范式有效用大白话讲这套范式本质上是把 Agent 协作从人和人聊天降维成接口调用。人聊天的时候可以靠默契补全信息但模型没有跨会话的默契每一次调用都是全新的人。所以协作协议必须把目标、上下文、边界、验收标准都显式写清楚。这也是我一直跟身边人强调的不要追求Agent 之间像同事一样自然对话要追求每次委派都像一张填写完整的工单。自然对话的容错率很低你预期对方听懂了你没说出口的意思但它根本没这个能力工单式协作则几乎每一步都可检查、可回滚、可重试。稳定比看起来智能重要得多。5. 工程化收尾成本、并发、可观测性一个都不能少协作协议定了最后是工程层面的几个细节。它们不直接决定能不能跑通但决定了能不能长期稳定运行。很多项目前期 Demo 跑得很漂亮一上量就崩基本都是栽在这几个细节上。5.1 成本控制的三道闸门第一道是上下文闸门每个子代理收到的上下文卡片必须控制在 500 token 以内更长的材料走文件引用不直接复制全文。这能从源头压住大部分 token 浪费。最初我这道闸门形同虚设每次看到 token 账单都很心虚。第二道是输出闸门任务单中的output_schema只允许子代理输出必要字段。比如整理问答条目时只返回 question、answer、clause_ref不需要它把整段源文档再抄一遍。这能避免子代理把原文重复返工这种隐蔽开销这类开销不加日志统计时根本发现不了。第三道是重试闸门重试次数必须写死在任务单里一般 1 到 2 次就够。超过上限就记录失败并交给人工审查不要无限重试。无限重试不仅烧钱还会把错误结果一遍遍加强最后可能给出一个看起来很完整、实则全是幻觉的答案。5.2 并发与超时把失控概率压到最低并行跑多个子代理确实能提速但要注意三点限制最大并发数。我常用的上限是 5具体取决于接口速率限制和上下文总预算。并发太高时单个任务出问题会导致群体性失败排查起来极其麻烦。每个子代理必须有自己的超时时间。整体超时和子代理超时要分开设置这样失败时才知道是哪一环超时。如果只设一个全局超时你只能看到一个笼统的超时定位不到具体是哪个子代理卡住了。递归限制落实到代码层。至少要加一个max_depth参数默认值为 1 或者 2而不是默认无限。很多框架默认不限制递归深度这是生产事故的高发区。5.3 可观测性日志里要有委派单和校验结果跑了几十次任务之后我最大的感触是Agent 协作出问题最怕的不是报错而是不报错但结果不对。所以日志里至少要有三样东西每次委派的任务单完整内容方便事后复盘它到底接到了什么指令子代理返回的原始输出以及校验结果校验失败时能看到具体的 error 列表每次调用的 token 消耗和耗时方便做成本归因。我在实际项目中会给每次委派生成一个运行 ID把任务单、输出、校验结果、token 消耗绑定存起来。后续排查某条知识条目质量差时直接按 ID 查记录——当时给子代理传了什么、它答了什么、哪一步验证没过一目了然。没有这套日志体系时排查一次异常往往要翻半天聊天记录效率极低。5.4 一个值得保留的小习惯最后分享一个小习惯在任务单末尾增加一个字段内容大概是如果本任务确实无法完成请直接说明阻碍你的具体原因不要尝试自行扩大任务范围。这个字段看起来增加了自由度实际反而减少了模型的盲目发挥。模型在承认我做不了这件事上通常比我必须做出来点什么更诚实。而诚实的失败永远比虚假的成功好修——至少你知道问题出在哪而不是面对一份看似完成、实则全错的垃圾输出还得逐条去核对。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑