
1. 项目全貌先弄清“agency-agents”到底在解决什么做Agent开发这一年多我踩过最大的坑不是模型选型而是单Agent扛不住复杂任务。你给它一个“做个市场调研并输出报告”的需求它要么在前两步就钻进细节出不来要么生成一份结构完整但内容全靠编的漂亮文档。后来我和团队搭了一套叫“agency-agents”的多智能体协作系统核心思路不复杂——把一组大模型驱动的Agent组织得像一家微型代理事务所那样运转有人接单拆解有人分头干活有人专门挑毛病返工。这篇文章就把这套项目的设计思路、踩坑实录和可直接抄的配置方式完整写出来。先解释下名字。“agency”在英文里有双重含义一是“代理”对应Agent本身二是“代理机构”“事务所”对应这套系统的组织形态。所以agency-agents翻译过来就是“让Agent们像事务所一样协作”的编排框架而不是单个智能体的增强。它解决的核心问题是当任务的复杂度超出单一模型上下文窗口和推理能力时如何通过多个Agent的分工、流转、互检把整体输出质量拉回可用水平。什么人适合参考这套方案已经在用LangChain、CrewAI或自研框架做Agent应用但发现单个Agent处理端到端任务时质量不稳定的开发者想给团队搭建“AI员工小组”的产品和技术负责人需要一套角色分工、任务流转、质量验收的工程化思路被“多Agent协作”这个概念打动但不知道从哪下手、担心做成玩具项目的初学者。这套体系跑通以后最直观的变化是**同样一份行业分析报告任务之前单个Agent产出的东西只能当草稿现在这个“虚拟事务所”交出来的东西基本能直接进评审流程。**下面从设计思路开始拆。1.1 单Agent的瓶颈为什么单独一个大模型智能体不够用先说个扎心的事实大模型Agent的失败模式是高度可预测的。我做过一个对比实验用同一个模型分别以“单个Agent”和“多Agent协作”两种方式完成一个竞品分析任务。单Agent模式暴露的问题非常稳定任务分解靠“感觉”模型拿到“分析竞品”这种开放性指令自己拆出来的子任务经常是“研究市场”“分析功能”“写报告”这种维度混杂的列表而不是真正可执行的工作流。上下文单向膨胀单Agent要把所有中间结果都塞在自己的上下文里跑完三步以后前面两步的有用信息往往被后面的内容挤掉或者被模型自己遗忘。没有质检回路模型生成完直接交付错别字、数据编造、逻辑断层没人拦。你让模型自己“检查一下”它大概率回你一句“整体良好无需修改”。单点故障一旦某一步工具调用失败或者返回格式异常整个任务链直接崩掉前面的工作全白费。这四点单拎出来都能绕过去但叠在一起就很致命。尤其当你把Agent从“玩一玩”推向“真正干活”的时候出错的代价不再是一次对话的尴尬而是业务方的信任流失。1.2 “agency”模式的核心把智能体组织成一个微型机构我参考了现实中小型咨询公司的运作方式把Agent分成了三类角色主管AgentDispatcher负责接需求、拆任务、派活、汇总。它不直接产出内容只做决策和调度。执行AgentWorker按主管分配的子任务干活比如文献检索、数据分析、初稿撰写。一个任务可以对应多个Worker并发执行。质检AgentInspector对Worker的产出做验收从事实准确性、格式规范性、逻辑完整性三个维度打分。不达标就打回重做并附上具体修改意见。这套结构对应到代码层面就是三条核心原则角色隔离每个Agent有自己的系统提示词、工具白名单和输出格式约束不允许越权。任务作为一等公民任务不再是一段自然语言指令而是结构化的JSON对象包含任务ID、目标、约束、依赖关系和验收标准。强制质检节点任何任务在进入下一环节之前必须经过质检Agent的验收验收不通过不允许流转。你可能会问多一次质检不就多一次模型调用、多花一份token钱吗确实是但质检Agent发现的问题远比它多花的钱值钱。后面实测部分我会给出具体成本数据。1.3 项目边界与目标什么样的任务适合这种架构做了这版以后我总结了三类“天生适合agency-agents模式”的任务研究分析类行业调研、竞品拆解、政策解读。这类任务天然可以拆成“资料收集→信息整理→观点提炼→报告输出”四段而且每段之间都有明确的验收点。内容生产类长文写作、SEO文案矩阵、课程大纲设计。单个Agent写八千字的长文写到后面经常忘了前面的论点拆成“提纲→分章节撰写→统稿润色”以后每一章的质量都能被单独评审。代码任务类功能模块开发、Bug修复分析。主管拆需求Worker写代码质检Agent先静态审查再决定要不要进入测试环节。不适合的也有三类实时聊天对话多一跳调度就有延迟、简单确定性操作查个天气还要走一遍拆单派单纯属浪费、强依赖隐性上下文的场景比如客服对话里客户只说了半句话剩下全靠脑补。2. 方案选型与核心设计思路2.1 编排框架的取舍自研还是用现成框架项目启动的时候团队内部先吵了一轮是直接用CrewAI、AutoGen这些现成框架还是自己写编排层我的结论是**框架可以拿来当参考但核心调度必须自己掌控。**原因有三现成框架的角色模型比如CrewAI的AgentRoles确实好用但它们的抽象层次偏高遇到“需要给不同Agent配置不同模型”“需要精确控制任务依赖关系”这类需求时反而要绕开框架做一堆hack。多Agent系统的瓶颈从来不在“能不能对话”而在“状态怎么管”。现成框架大多把状态存在内存会话里一旦进程重启任务跑到一半就丢了。我们需要的是可持久化的任务状态机。质检回路的控制逻辑非常个性化。你希望质检Agent看到什么东西、按照什么标准打分、打回时携带什么反馈信息这些细节框架很难覆盖周全。最终我们选择了自研一个轻量调度层 复用成熟组件的组合调度层用Python写任务状态存SQLiteAgent调用层直接封装各家大模型API数据插桩用现成的向量库。这套组合的好处是灵活性和可控性都在自己手里坏处是前期开发量会多出两三天——但这两三天省下来的是后面调试协作逻辑时无数的弯路。2.2 角色设计主管、执行者、质检者的分工逻辑三大角色的提示词设计是整个项目里性价比最高的一步。我见过太多项目把Agent提示词写得像使用说明书结果模型根本不按套路出牌。我们的做法是把每个角色的系统提示词压缩成“身份职责边界输出格式禁区”四个模块。以主管Agent为例它的系统提示词核心长这样简化版你是一个项目经理型Agent负责接收任务、拆解子任务、分配给执行Agent并在最终环节汇总产出。 职责边界 - 你可以调用“任务拆解工具”和“任务分配工具”。 - 你无权直接调用任何数据检索、内容生成相关的工具。 - 你必须为每个子任务指定验收标准字段为acceptance_criteria。 输出格式 - 所有决策必须以JSON格式输出包含task_id, subtasks, assignments三个字段。 禁区 - 禁止输出自然语言格式的任务描述所有任务描述必须是结构化字段。 - 如果用户需求不明确输出status: need_clarification禁止擅自猜测需求。这里最关键的三个设计是不让主管Agent干活——它一旦能调用数据分析或内容生成工具马上就会忍不住自己动手整个协作结构就会退化成单Agent。强制结构化输出——任务描述必须带验收标准这一步把“模型含糊其辞”的空间压缩到最小。明确“不清楚就说不知道”的选项——很多Agent系统翻车是因为模型在需求不明确时强行开工这一条从Prompt层面做了硬约束。执行Agent的提示词设计则更侧重“查询参数规范化”和“中间结果结构化”。比如它被要求所有查询请求必须拆分出source、time_range、keywords三个字段缺一不可所有检索结果必须按summary raw_data_links的格式返回。质检Agent的提示词则是一张打分卡后面会专门展开。2.3 通信与状态任务看板与消息协议多Agent系统最容易被忽视的就是通信协议。如果让两个Agent直接用自然语言对话你很快就会遇到三个鬼故事模型开始寒暄、模型开始重复对方的话、模型开始自作主张替对方做决定。我们为系统定义了一套“任务看板协议”所有Agent之间的通信都通过结构化消息完成消息格式长这样{ message_id: msg_20250112_001, from: dispatcher, to: worker_web_research, type: task_assignment, payload: { task_id: task_20250112_001, objective: 收集过去一年内行业TOP10公司的融资信息, constraints: { source_type: [news, official_announcement], time_range: 2024-01-01_2024-12-31, output_format: json_array }, acceptance_criteria: [ 每家公司须包含公司名称、融资金额、融资轮次、投资方列表, 融资信息必须附带原始链接 ], depends_on: [] } }这套协议的核心价值不在于格式有多漂亮而在于消息类型只有四种task_assignment分配任务、task_result提交结果、task_review质检反馈、task_update状态变更。Agent之间不允许传其他类型的消息从机制上杜绝了“聊着聊着跑题”的问题。所有消息进入持久化存储也就是所谓“任务看板”每个消息带时间戳和状态字段方便回溯。依赖关系显式声明如果任务B依赖任务A的结果B的消息里会带上depends_on: [task_A]调度器据此决定执行顺序。我在项目文档里给这套模式起了个外号叫**“哑巴通信”**——Agent之间不做任何闲聊式对话只交换结构化工件。实践下来这个设计对最终系统稳定性的贡献比任何一个精心调过的Prompt都大。3. 核心实现拆解配置、提示词与调度逻辑3.1 角色配置与质检打分卡前面提到质检Agent是整个项目质量保障的枢纽我把它的输出设计成“打分卡”形式。质检Agent每次验收一个任务结果必须输出如下JSON{ review_id: review_20250112_001, task_id: task_20250112_001, decision: pass|rework, scores: { factual_accuracy: 85, format_compliance: 90, logical_coherence: 70 }, issues: [ { type: missing_citation, severity: major, description: 融资信息中提及某公司完成2亿美元融资但未附原始新闻链接, suggestion: 补充官方新闻源或工商变更记录链接 } ], feedback_summary: 有两条融资信息无法溯源且结论段存在前后矛盾建议返工。 }这个打分卡有几个细节值得讲decision字段只有两个值pass或rework没有“勉强通过”这个中间态。实际运行中一旦允许“勉强通过”质检Agent很快会变成和稀泥的角色所有结果都会以低质量糊弄过去。issues必须结构化每条问题要有类型、严重程度和修改建议。质检Agent只输出“此处不完整”这种模糊反馈没有任何价值我们的经验是如果质检反馈里没有给修改建议这个任务90%会进入“返工-提交-再返工”的死循环。严重程度分级major级别的问题强制返工minor级别的可以带问题流转但进入最终汇总阶段时由主管Agent统一决定是否修复。这个分级避免了质检环节陷入无休止的细节打磨。3.2 任务拆分与分配策略主管Agent的任务拆解能力直接决定了整个系统的上限。最初版本里我让主管Agent自由发挥拆分逻辑结果它经常拆出“维度重叠”的子任务——比如同时拆出“分析市场规模”和“评估用户群体规模”两个Worker找到的数据一半重叠。后来我引入了一个“任务分解检查器”本质上是一个辅助Agent专门审查主管Agent拆分出来的任务列表是否符合三个约束互斥性任意两个子任务的目标不能有超过20%的重叠。穷尽性所有子任务的并集必须覆盖原始任务的目标。可验证性每个子任务必须能被独立的验收标准量化衡量。有了这个检查器任务拆解质量明显提升。另外还有一个实用小技巧分配任务时不要只给Worker一个目标要同时给它“已经有谁做过什么”的共享背景。这能大幅减少两份子任务重复检索同一批数据的情况。3.3 上下文管理与记忆截断多Agent系统的上下文管理比单Agent要复杂一个量级因为每个Agent都有自己的上下文窗口而且它们还会共享同一个“记忆库”。我们踩过最大的坑是共享记忆库无限制增长——跑了一天以后每个Agent的上下文窗口里都塞满了和当前任务无关的历史记录推理速度肉眼可见地变慢。最终采用的方案是“三层记忆截断”工作记忆只保留当前任务相关的消息任务完成后清空但消息会归档到持久化存储。共享记忆存任务级产物、关键结论和引用来源每条记录打上时间戳和任务编号满100条自动按时间淘汰最老的20条。长期记忆只有系统最终交付的产出会写入这里比如最终报告全文、关键数据摘要。这个设计的好处是主管Agent从长期记忆里拿“大图”Worker从工作记忆里拿“细节”质检Agent在必要时可以回溯共享记忆做溯源核对。各取所需互不干扰。3.4 工具注册与权限控制最后讲一个容易被新人忽略的点——工具权限。在多Agent架构里给所有Agent都暴露全部工具是大忌。我们遇到过的一次事故是一个负责写文案的Worker顺手调用了“发送邮件”工具差点把不成熟的初稿发给客户。现在的工具注册机制是一个白名单字典每个角色对应一组可用工具角色可用工具列表不可用操作主管Agent任务拆解、任务分配、最终汇总、状态查询数据检索、内容生成、外部通信执行Agent检索类网页检索、向量库查询、数据抓取内容生成、任务拆分、外部通信执行Agent写作类大纲生成、章节撰写、格式转换数据抓取、任务拆分质检Agent文本审阅、格式检查、引用核对内容生成、数据检索、外部通信代码层面就是一个简单的装饰器路由TOOL_WHITELIST { dispatcher: [split_task, assign_worker, merge_result], worker_researcher: [search_web, query_db, scrape_page], worker_writer: [generate_outline, write_section, convert_format], inspector: [review_text, check_format, verify_citation] } def check_tool_access(agent_role, tool_name): if tool_name not in TOOL_WHITELIST.get(agent_role, []): raise PermissionError( fAgent {agent_role} 无权调用 {tool_name} f当前角色仅允许调用 {TOOL_WHITELIST[agent_role]} )别小看这个简单的白名单它阻止的问题比任何Prompt调优都多——当系统里有五个Agent、每个Agent能调用十个工具的时候组合出来的权限空间已经非常巨大不掐死这个口子安全性和稳定性都是纸上谈兵。4. 实操过程从零搭一个最小可用体系4.1 项目骨架与依赖以下是我们跑通完整流程时的最小依赖清单。所有关键逻辑都在core目录下约600行Python代码外加几个JSON配置文件。agency_agents/ ├── core/ │ ├── message_bus.py # 消息总线所有Agent通信走这里 │ ├── task_store.py # 任务看板SQLite持久化 │ ├── dispatcher.py # 主管Agent入口 │ ├── worker.py # 执行Agent基类 │ ├── inspector.py # 质检Agent入口 │ └── llm_client.py # 大模型API统一封装 ├── config/ │ ├── agents_config.json # 角色与工具白名单配置 │ └── prompts/ │ ├── dispatcher_prompt.txt │ ├── worker_prompt.txt │ └── inspector_prompt.txt └── main.py # 系统入口依赖库就三个openai大模型调用、sqlite3标准库任务状态存储、requests网页检索调用。不用消息队列、不用Redis、不用Docker——第一版跑通之前任何多余的组件都是负担。4.2 关键代码片段消息总线的实现消息总线是整个系统的“血管”。我实现它的策略是先写一个send_message函数处理格式校验和持久化再让所有Agent通过这个函数通信。import json import sqlite3 from datetime import datetime DB_PATH task_store.db class MessageBus: def __init__(self, db_pathDB_PATH): self.conn sqlite3.connect(db_path, check_same_threadFalse) self._init_table() def _init_table(self): self.conn.execute( CREATE TABLE IF NOT EXISTS messages ( message_id TEXT PRIMARY KEY, from_role TEXT NOT NULL, to_role TEXT NOT NULL, type TEXT NOT NULL, payload TEXT NOT NULL, status TEXT DEFAULT pending, created_at TEXT NOT NULL ) ) self.conn.commit() def send_message(self, from_role, to_role, msg_type, payload): # 核心校验只允许四种消息类型 assert msg_type in (task_assignment, task_result, task_review, task_update) message_id fmsg_{int(datetime.now().timestamp() * 1000)} record { message_id: message_id, from_role: from_role, to_role: to_role, type: msg_type, payload: json.dumps(payload, ensure_asciiFalse), status: pending, created_at: datetime.now().isoformat(), } self.conn.execute( INSERT INTO messages VALUES (?, ?, ?, ?, ?, ?, ?), tuple(record.values()) ) self.conn.commit() return message_id def get_pending_tasks(self, to_role): cur self.conn.execute( SELECT * FROM messages WHERE to_role? AND statuspending, (to_role,) ) return [(row[0], row[2], row[3], json.loads(row[4])) for row in cur.fetchall()]这段代码里的assert不是摆设它是防止Agent通信“跑味”的最后一道防线。如果哪天某个Agent试图传出casual_chat类型的消息系统会直接抛异常这种问题暴露得越早越好。4.3 主管Agent的调度逻辑主管Agent不直接调用大模型生成内容它的核心是一个“决策循环”读取待处理任务调用大模型拆解校验拆分结果然后分发。我这里用一个简化版的调度循环展示核心思路def dispatcher_loop(msg_bus: MessageBus, llm_client): pending msg_bus.get_pending_tasks(dispatcher) for msg_id, from_role, msg_type, payload in pending: if msg_type task_update and payload.get(status) all_completed: # 所有子任务完成进入最终汇总 final_report llm_client.generate_report( system_promptDISPTACHER_REPORT_PROMPT, sub_resultspayload.get(sub_results, []) ) # 汇总报告也要过质检 msg_bus.send_message( dispatcher, inspector, task_review, {report: final_report, task_id: payload[task_id]} ) continue if msg_type task_assignment and from_role user: # 拆解任务 split_result llm_client.split_task( system_promptDISPTACHER_SPLIT_PROMPT, user_requestpayload[objective] ) # 校验拆分结果是否满足互斥性/穷尽性/可验证性 check_result llm_client.check_split( system_promptSPLIT_CHECKER_PROMPT, split_resultsplit_result, original_requestpayload[objective] ) if not check_result[is_valid]: # 拆分不合格重新拆最多重试两次 continue # 分发子任务给合适的Worker for sub in split_result[subtasks]: worker_role route_to_worker(sub[type]) msg_bus.send_message( dispatcher, worker_role, task_assignment, sub )主线逻辑不复杂复杂的是边界条件任务拆解校验失败怎么处理、某个Worker迟迟不返回怎么超时、子任务间存在依赖时需要等哪个先完成。这些细节我在后面“常见问题”章节里展开。4.4 一次完整任务流转的现场记录拿一个测试任务举例“调研2024年国内AI写作工具市场的竞争格局输出一份3000字分析报告”。系统实际跑完一次任务消息流转是这样用户提交需求→ 消息类型task_update状态new发送给主管Agent。主管拆解→ 输出4个子任务子任务A检索市场规模与增长数据子任务B梳理头部产品的功能对比子任务C整理用户评价与口碑数据子任务D分析行业趋势与潜在机会。分发→ 主管将A和C发给“检索Worker”B发给“对比分析Worker”D发给“趋势研判Worker”。三个Worker并行执行→ 各自返回结构化中间结果。主管汇总初稿→ 生成一份约3500字的报告初稿发送给质检Agent。质检→ 打分卡给出事实准确性78分有两个数据缺引用、格式合规90分、逻辑连贯85分。decision为rework附带3条修改建议。打回重做→ 主管根据质检建议定位到对应段落让检索Worker重新补数据和链接再进行二次汇总。二次质检→ 打分提升到事实准确性92、格式合规95、逻辑连贯90decision为pass。交付→ 主管将最终报告和质检记录一起提交。整个流程耗时约4分半钟模型API调用为主token消耗约12万。换成单Agent直接写同样任务耗时约2分钟、token消耗约6万但产出质量基本被质检Agent按在及格线上下摩擦。5. 实测数据与效果评估5.1 质量和效率的权衡不是所有任务都值得“走流程”项目上线后我专门对20个不同类型的任务做了对比实验用同一组模型分别走“单Agent直出”和“agency-agents协作流”请了团队里三位同事按1-10分盲评打分任务类型单Agent平均分多Agent协作平均分耗时增幅成本增幅行业分析报告5.28.1125%108%长文写作3000字5.87.986%95%代码Bug分析6.58.370%82%短视频文案脚本7.17.432%40%简单问答8.26.955%65%数据说明一个重要事实复杂度越低的任务协作流的“质检-返工”环节带来的损耗越明显。短视频文案这种本身比较模式化的内容单Agent已经能良好完成硬走协作流反而会因为过度审校让它失去灵气。所以我们的决策是只有预估复杂度在“需要处理外部信息且需要多角度交叉验证”级别的任务才推荐走agency-agents模式。用一张路由表来判断任务目标中有“分析、研究、对比、综述、调研”等动词且预期产出在800字以上 → 上协作流。任务目标是明确的模板化产出如周报、会议纪要、文案改写→ 单Agent直出必要时加一个轻量质检。5.2 成本控制质检Agent是花小钱省大钱的典型很多人一看“多Agent”就觉得token成本高不可攀但实测下来情况没那么吓人。以行业分析报告为例单Agent直出的6万token里大概有20%是模型“自己推翻自己”产生的无效推理。协作流的12万token里质检Agent只占约1.5万token但它拦截下来的问题数据编造、逻辑断层、格式错乱如果直接交付团队的返工成本可能是一个工作日。事实上我在另一个项目里尝试过“加大质检Agent的权重”来进一步提升质量比如给它更高昂的“返工指令”质检Agent会变得异常挑剔一份报告返工四五次质量和第一次相比只提升了0.3分。质检不是越严越好严到边际收益趋近于零时纯属烧钱。我们最终的策略是质检Agent打回一级修改后二稿直接进入盲审盲审不过再考虑人工介入。5.3 在哪些场景收益最大结合半年多的生产环境使用我给这套系统打出的“最佳适配场景画像”是跨领域信息综合单Agent的知识范围有限但多Agent可以通过“检索Worker”补足外部信息再让“研判Worker”做分析比单模型靠内部知识硬答靠谱得多。长流程任务任务链条越长单Agent“忘记前文”的概率越大。协作流把整个链条拆成了独立的上下文窗口每个环节只载入自己需要的信息。需要可审计性的交付物质检记录天然形成了交付物的审计日志。老板问“为什么你觉得这个数据可靠”你可以直接调出质检Agent当年的核验记录。6. 常见问题与排查技巧实录6.1 Agent之间陷入死循环返工卡死现象质检Agent打回任务后Worker改了一轮再交上来质检Agent又因为别的问题打回改了再交又被打回。循环往复任务永远无法通过。根因质检Agent的“验收标准”和Worker的“修改能力”不匹配。常见原因是验收标准写得太抽象比如“请确保内容深度足够”Worker根本无法判断“深度够”是什么样只能瞎改。排查思路第一步看质检记录里的issues字段如果连续两次打回的issues存在重叠说明质检标准没被执行者理解。第二步检查验收标准是否可量化。我们后来把所有验收标准改成“包含/不包含”句式错误示范“报告应该有足够的数据支撑。”正确示范“报告必须包含至少5组来源可溯的统计数据每组数据须在文末参考文献中给出对应编号。”解决方法在调度循环里加一个“返工次数上限”默认3次。超过上限后任务不再打回而是带着质检意见直接进入“人工复核队列”由人工决定是放行还是终止。6.2 上下文爆炸每个Agent都塞了一肚子历史现象系统跑久了Agent的响应速度明显变慢而且后期任务的产出质量忽高忽低。根因虽然设计了记忆截断但实践中发现当Worker处理完第一个任务后它的上下文窗口里还残留着上一个任务的中间结果。它再处理新任务时会把旧任务的信息混进新任务。排查思路给每个消息加上trace_id链路追踪号在日志里检索同一个trace_id下Agent调用大模型的输入是否包含无关历史内容。解决方法Worker处理完一个任务后强制执行“上下文重置”——清掉工作记忆只保留共享记忆里与其强相关的关键结论。类似于一个员工换新项目工位时把上一项目的草稿纸全部扔掉只留下脑中的经验。6.3 Agent“假协作”看似在接力其实在各自编故事现象质检打回的情况很少但最终交付物里多处数据对不上。比如甲Worker说市场规模50亿乙Worker引用了针锋相对的40亿数据两份数据竟然都被质检放行了。根因质检Agent的职责边界没设好它默认“每份子任务结果独立检查”而不对比不同子任务之间的数据一致性。这是质检环节最容易漏掉的一环。排查思路在质检Agent的打分卡里加一个cross_consistency维度让它对同一任务不同子结果之间的关键数据进行交叉比对出现矛盾直接判rework。解决方法改为“两阶段质检”第一阶段是单任务质检第二阶段是汇总前的一致性核验由主管Agent在汇总阶段触发。这个改动上线后跨模块数据冲突的事故率降低了约70%。6.4 工具调用失败后Agent“装成功”现象Worker调外部数据接口失败了接口返回超时或空值但Worker在提交结果时一切照常完全没提失败的事。根因大模型在“完成任务”和“汇报失败”的取舍里天然倾向于前者。它宁可编一个看似合理的数据结构也不愿意输出一个“status: failed”的空结果。排查思路所有工具调用必须走统一封装封装层捕获异常后直接返回结构化错误对象而不是把异常吞掉让模型自由发挥。def call_with_error_tracking(tool_func, *args, **kwargs): try: result tool_func(*args, **kwargs) # 结果必须带状态字段空结果也不能例外 return {status: ok, data: result} except Exception as e: # 禁止把原始异常发给模型自由发挥 return { status: failed, error_code: type(e).__name__, error_message: str(e)[:500] }解决方法在Worker的系统提示词里明确写一条硬规则“如果你收到statusfailed的返回必须立即中止任务并汇报失败禁止尝试自行伪造补齐数据。”这条规则加进去以后模型伪装成功的行为几乎绝迹。6.5 排查技巧速查表症状优先排查方向常用手段返工死循环验收标准是否可量化查看issues是否重复、检查acceptance_criteria字段响应越来越慢上下文膨胀检查记忆截断策略、清理工作记忆数据前后矛盾跨模块一致性缺失启用两阶段质检、增加cross_consistency评分工具失败但继续输出异常处理被吞统一工具封装、强制状态字段任务拆解重叠拆分检查器未生效检查互斥性校验逻辑Agent擅自动用无关工具权限白名单缺失检查TOOL_WHITELIST配置最后再分享一个个人体会做完agency-agents这个项目我最大的感受是多Agent系统真正的难点不在Agent本身而在Agent之间那套“看不见的秩序”。你的模型能力再强如果角色边界不清、通信协议混乱、质检标准模糊系统跑起来就是一群聪明人在互相添乱。如果你也准备搭类似的东西我的建议是先别急着上复杂架构。把主管、一个Worker、一个质检这三个角色先跑通——哪怕用最简单的JSON消息在本地进程间传递——然后把“返工循环”“上下文膨胀”“假协作”这几个坑全部踩一遍你自然就知道下一步该往哪个方向投入。这套体系在更长远的维度还有一个可以扩展的方向把质检Agent沉淀下来的问题库做成一个反馈回路定期用真实案例反向微调各角色的提示词。简单说就是让系统自己“吃一堑长一智”那个方向做下去项目会越来越像一个真正成熟的事务所而不是三个固定工位的临时团队。