看到“agency-agents”这个词,我第一反应不是某个具体开源仓库,而是一种正在被反复验证的多智能体协作模式:把几个擅长不同事情的 AI Agent,像一家小型公司那样组织起来,让它们各自认领角色、互相传递中间结果、最后拼出一份高质量交付物。我最近在一个客户项目里完整跑了一版“代理机构”式的工作流,用来做行业调研和内容生产,前后折腾了三个星期,踩了不少坑,也摸到了一些很实用的规律。这篇就围绕 agency-agents 这个思路,把架构设计、代码骨架、参数调优和问题排查一次说清楚。
如果你正在做 AI 应用开发,或者对 Agent 感兴趣但厌倦了“单智能体提示词越堆越长”的路子,这篇文章很适合你。即使你只是用过 ChatGPT,想理解“多个 AI 角色协作到底怎么玩”,里面的大部分思路也都能直接套用。
1. 项目概述与核心思路
1.1 什么是 agency-agents:把单点能力拼成专业团队
传统的单 Agent 用法是“一个大模型 + 一大段系统提示词 + 一个完整任务”,所有工作都由同一个模型完成。遇到简单任务还行,一旦任务变成“先调研、再分析、然后写报告、最后校对”,单 Agent 就开始露馅:提示词里塞太多角色要求,模型容易“精神分裂”;上下文太长,前面的结论到后面就忘了;更麻烦的是,你很难判断是哪一步出了问题。
agency-agents 的做法是把任务拆开。项目经理 Agent 负责拆解任务和管理进度,调研员 Agent 专门去搜索和整理资料,分析师 Agent 负责提炼规律,编辑 Agent 负责润色和排版。每个 Agent 只需要做好自己那一小块事,prompt 可以写得很聚焦,输出也更稳定。整个流程就像是把一个全能型员工替换成一个各司其职的小团队,每个人只对最终目标的一部分负责。
这种模式在开源社区里已经有 MetaGPT、AutoGen、ChatDev 等类似实践。agency-agents 更强调的是“代理机构感”:你需要让 Agent 之间有明确汇报关系、清晰交接物、统一的通信协议,而不是简单地把多个 Agent 丢进一个群里自由发言。否则很快就会出现“上下文大杂烩”和“没人对最终结果负责”的问题。
1.2 为什么我放弃单智能体转向多智能体协作
我做第一个 Agent 项目时,把所有需求全写进了一个 system prompt。为了让它能“全网搜索、分析数据、写周报”,我硬凑了一个超过 2000 字的提示词,结果模型经常顾此失彼:让它查数据的时候它开始总结,让它写结论的时候它又开始列数据表。最离谱的一次,它把上一轮调研的旧结论当成本轮结果,直接交了一份错误报告。
后来我尝试把任务手工拆开,分多次调用模型,每次干一件事,再手动拼装结果。过程很痛苦,但效果明显变好。这让我意识到:问题不是模型不够聪明,而是整个链路缺少结构和反馈。单 Agent 的上下文窗口再大,也装不下“一个完整的业务项目周期”;而 agency-agents 模式可以让每个 Agent 专注在自己的小上下文里,通过消息传递和共享记忆,让整体认知远远超过单 Agent 的窗口限制。
这种模式还有一个隐性优势:可解释性。一旦最终报告质量不行,我可以直接定位是投资分析师 Agent 的输出有问题,还是最后的编辑 Agent 改了风格。责任落到具体 Agent 上,调优就有方向。而不是像单 Agent 那样拿一段黑盒输出反复猜 prompt 哪里写得不到位。
2. 整体架构设计与智能体分工
2.1 核心组件拆分:编排器、角色智能体、消息总线
搭一个可用的 agency-agents 系统,至少要拆出四个核心组件。
第一个是编排器(Orchestrator)。它不负责具体内容产出,而是负责拆解任务、调度角色、判断何时该收尾。你可以把它理解成项目总监:不写代码,但盯着进度,看见某个 Agent 卡住或结果不对,就决定重试还是换人。编排器通常就是一个循环控制逻辑,用代码实现,不一定非要调模型。
第二个是角色智能体(Worker Agents)。每个 Worker 有独立的 system prompt、模型参数、工具权限甚至独立的模型供应商。不同角色可以配不同模型:简单的信息抽取用便宜快的小模型,复杂分析用贵一点的大模型,这样成本控制会好很多。
第三个是消息总线(Message Bus)。它是 Agent 之间的“共享聊天群”,所有中间输出都按统一的消息格式写入。其他 Agent 订阅到自己需要的消息类型后,就能取用上一环节的产出。消息总线不一定要用消息队列中间件,用 Python 里的 list 或者 Redis 都能实现,关键是消息要有标准结构。
第四个是外部工具层(Tool Layer)。Agent 需要搜索、查数据库、调 API 时,不能直接裸写浏览器操作,而是通过一组预定义的函数接口来调。工具层把“模型能发出的动作”限制在安全范围内,同时把结果转成结构化的返回内容。
这四个组件的关系很像一家真实公司:编排器是管理层,角色智能体是员工,消息总线是内部 OA 系统,工具层是办公用品和外部资源。少了任何一个,多 Agent 协作就会退化成“几个模型互相对话”的玩具。
2.2 角色分工设计的五个避坑原则
设计角色时,我总结出五个原则,每条都是从踩坑里摸出来的。
第一,职责单一。不要设计一个“全能型专家”Agent,什么都会,等于什么都不专业。项目经理只管计划和进度,不要让它去写市场分析。分析师只总结数据,不要兼任编辑。职责边界混乱,是系统跑偏的头号原因。
第二,输出标准化。每个 Agent 的输出都必须按约定好的格式返回,可以是 JSON、Markdown 或 YAML。你甚至可以在 system prompt 里强制要求“先输出 JSON 再输出正文”。没有标准格式,下游 Agent 解析时就会频繁出错,有时候不是模型不聪明,而是前一个 Agent 写了一堆“嗯、好的、明白了”这类废话,把有效的交接物淹没了。
第三,闭环校验。设计任务流要有计划、执行、评审、复盘这样的闭环。最简单的方式是加一个 reviewer Agent,专门检查上一个角色的输出质量。没有校验,错误会一路传导到最终结果,而且很难追溯。
第四,角色数量控制在 3 到 5 个。我试过 8 个角色的团队,结果是消息总线里充斥着大量无用信息,上下文迅速膨胀,编排器自己也分不清当前状态。小团队运转效率远高于大团队。想扩能力,不是加角色,而是给现有角色加工具。
第五,人工兜底。不管流程设计得多好,最终交付前要留一个“人工确认步骤”。尤其是用于客户报告或生产环境的内容,一定要有一个环节允许人介入修改。Agent 协作能提高效率,但还不能完全替代人的判断。
2.3 一个典型的信息流转流程
用一个“行业市场分析报告”举例。编排器先接收任务,拆成四个阶段:调研、分析、撰写、校对。第一阶段,编排器把“收集行业规模和头部玩家数据”发给调研员 Agent;调研员使用搜索工具拿到原始数据,整理成带来源的结构化笔记,写入消息总线。第二阶段,编排器把这份笔记交给分析师 Agent,分析师给出趋势判断和市场机会。第三阶段,编辑 Agent 把分析和原始笔记改写成可读的报告初稿。最后,校对 Agent 检查事实错误和格式问题,通过后输出最终版本。
整个流程中,编排器只在阶段切换时介入,平时不干预具体内容生成。这样既保持流程可控,又不会因为频繁调用模型导致成本暴涨。我实测下来,4 个角色的流程跑一个完整调研报告,大概需要 8 到 12 轮模型调用,时间在 2 到 5 分钟,费用取决于所选模型。
3. 实操过程:搭建一个可运行的 agency-agents 工作流
3.1 环境准备:用一套最小可跑的代码启动
下面这套代码我刻意写得非常简单,不使用重框架,方便理解底层机制。环境要求不高,只需要 Python 3.10 及以上、OpenAI 兼容的 API Key,以及两个基础库。
pip install openai python-dotenv然后在项目根目录建一个.env文件,写入你的 API Key:
OPENAI_API_KEY=sk-... MODEL_NAME=gpt-4o-mini关于模型选型,我可以提供一条参考经验:预算有限时,通用文本任务用 gpt-4o-mini 或同等定位的小模型,最终汇总和复杂分析用 gpt-4o 或同级别大模型。不要在每一步都上大模型,否则成本是线性上升的,而效果并不一定线性变好。
3.2 定义角色与任务流程:以市场分析报告为例
我建了一个roles.py文件,把每个角色定义成字典。之所以用字典而不是类,是为了直观,后续要接数据库或改配置也方便。
roles = { "pm": { "name": "项目经理", "system_prompt": ( "你是项目经理。你的责任是把用户任务拆解为若干清晰、有序的执行步骤," "并为每个步骤分配合适的角色。输出格式为 Markdown 列表,每行以 '- [ ] ' 开头。" ), "temperature": 0.3, "model": "gpt-4o-mini", }, "researcher": { "name": "调研员", "system_prompt": ( "你是调研员。根据项目经理给出的调研主题,使用提供的搜索工具收集资料。" "输出必须包含两个部分:'## 数据' 和 '## 来源'。数据部分用 Markdown 表格," "来源部分用带链接的列表。不要输出无关分析。" ), "temperature": 0.5, "model": "gpt-4o-mini", }, "analyst": { "name": "分析师", "system_prompt": ( "你是行业分析师。基于调研员提供的原始数据,找出趋势、风险和机会。" "输出格式:先给出三条核心洞察,每条 50 字以内;再给出两个需要进一步核实的问题。" ), "temperature": 0.4, "model": "gpt-4o", }, "editor": { "name": "内容编辑", "system_prompt": ( "你是内容编辑。将分析师和调研员的产出整合成一份逻辑通顺、段落清晰的中文报告。" "报告结构包括:摘要、市场现状、趋势分析、机会建议。不要添加新事实。" ), "temperature": 0.7, "model": "gpt-4o-mini", }, }注意几个细节:
- 每个角色的 prompt 都明确写了“不要做什么”,这比只写“要做什么”更能约束模型。
- 调研员 prompt 用了输出模板“## 数据”“## 来源”,这就是标准化的雏形。
- 分析师用了更贵的大模型,因为它要做深层推理;其他角色用便宜模型,整体成本就能压下来。
3.3 编排循环实现:关键参数怎么调稳
我写了一个不到 60 行的编排器,核心逻辑是“按阶段顺序调用角色 + 把上一阶段结果附加到上下文 + 阶段完成后自动终止”。
from openai import OpenAI from config import roles import os client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) MODEL = os.getenv("MODEL_NAME", "gpt-4o-mini") def call_agent(role_key, task, context, max_tokens=1500): role = roles[role_key] messages = [ {"role": "system", "content": role["system_prompt"]}, ] + context + [ {"role": "user", "content": task}, ] resp = client.chat.completions.create( model=role.get("model", MODEL), messages=messages, temperature=role["temperature"], max_tokens=max_tokens, ) return resp.choices[0].message.content def run_pipeline(topic): # 项目经理拆解任务 pm_task = f"请拆解以下任务,并标记需要哪些角色协作:{topic}" steps = call_agent("pm", pm_task, context=[], max_tokens=800) print("=== 项目经理拆解 ===") print(steps) # 让调研员执行第一步 research_task = f"围绕主题 '{topic}' 收集行业数据,重点包含市场规模与头部厂商。" research_out = call_agent("researcher", research_task, context=[{"role":"user","content": steps}]) print("=== 调研结果 ===") print(research_out) # 分析师基于调研结果分析 analyst_out = call_agent( "analyst", "请基于以下调研结果给出行业洞察。", context=[{"role":"assistant","content": research_out}], ) print("=== 分析结果 ===") print(analyst_out) # 编辑整合报告 final_report = call_agent( "editor", "请整合调研分析和原始数据,写出一份完整行业报告。", context=[ {"role":"assistant","content": research_out}, {"role":"assistant","content": analyst_out}, ], ) return final_report if __name__ == "__main__": report = run_pipeline("智能家居市场 2025") print("=== 最终报告 ===") print(report)这段代码最重要的参数有三个:
temperature:调研类角色要稳定,建议设0.4 以下;编辑类需要创造性,可以设0.7。千万别所有角色都用同一个温度,否则会出现“调研结果像散文、报告却像数据表”的错位感。max_tokens:每个阶段的输出长度要提前限制。调研阶段 1500 字足够,项目经理拆解任务 800 字足够。不限制的话,模型容易啰嗦,还会把上下文撑爆。context:编排器只把关键交接结果作为上下文传给下一个 Agent,而不是把整个历史对话全塞进去。这个设计非常重要,能缓解上下文超限问题。
4. 核心原理与关键细节解析
4.1 通信协议设计:让每个 Agent 都能接上话
多 Agent 协作里,最容易被低估的是通信协议。很多新手把所有历史消息一股脑塞给下一个 Agent,最后得到一堆混乱输出。正确做法是约定一个最小消息结构,每条消息包含四个字段:
{ "from": "researcher", "to": "analyst", "type": "research_note", "payload": { "data": "...", "sources": ["..."], "summary": "..." } }from和to是路由信息,type是消息类型,告诉接收方“这条消息是数据笔记还是最终报告”,payload是实际内容。用这个结构,编排器可以轻松实现已经处理的消息不再重复发送。更重要的是,模型看到的是清晰的结构化内容,而不是一堆聊天噪音。
我在实际项目里还加了一个“去重字段”:每条消息生成时都带一个哈希值,编排器比对后只保留最新的同类型消息。这个做法避免了调研员跑两次后,分析师同时看到旧数据和新鲜数据互相打架的情况。
4.2 上下文管理与记忆机制:别让 Agent“忘事”
多 Agent 系统最常遇到的问题是上下文爆掉。Agent 一多,每个人都要看到其他所有人的输出,对话历史指数级膨胀。解决思路是分级记忆:
- 工作记忆:当前阶段需要的最近几条消息,放在上下文里。
- 项目记忆:整个项目的关键结论,存在本地文件或向量数据库中,每轮结束后更新。
- 长期记忆:历史项目的总结,供未来任务参考。
在项目里我实现了一个简化版:每轮 Agent 运行结束时,用代码把它的输出里的“核心结论”提取出来,压成摘要,存到一个memory.md文件里。下一轮 Agent 需要做决策时,就把摘要和当前任务一起作为上下文。这样即使上下文窗口很小,也能保持对项目全貌的理解。
这种做法的代价是“可能丢掉细节”,所以我把原始输出完整保存在消息总线中,摘要只是给 Agent 的“短期捷报”。如果你需要精确引用某条数据,可以让调研员在输出里写清楚引用标识,后续 Agent 直接去找对应的完整内容。
4.3 工具调用与外部系统对接:给 Agent 装上手和眼
没有工具的 Agent 只能基于训练数据“想当然”。要真正完成调研,你至少需要一个搜索工具和一个抓取网页内容的工具。在 OpenAI 兼容接口里,工具调用可以通过tools参数声明。一个简化版搜索工具定义如下:
tools = [ { "type": "function", "function": { "name": "web_search", "description": "搜索给定关键词,返回前五条结果的标题和链接。", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "搜索关键词,尽量简短" } }, "required": ["query"] } } } ]这样模型就会在需要时调用web_search,而不是凭空编造数据。我把真实搜索函数写成一个 Python 函数,调用搜索 API 后把结果解析成上文约定的消息格式。注意,工具函数名称和描述写得越精确,模型调用的准确率越高。如果你写“这个方法可以获取信息”,模型很可能乱调;如果你写“传入中文关键词,返回带 URL 的结果列表”,它就会规范很多。
安全方面,工具层必须做权限控制。不能让 Agent 随便删文件、改数据库。我习惯给每个工具加一个“白名单角色”:只有调研员 Agent 能调搜索,只有编辑 Agent 能写文件。这样即使某个 Agent 被提示词注入攻击,损害范围也可控。
4.4 成本与延迟优化:多 Agent 不等于多花钱
很多人一听“多 Agent”,首先想到“那得多花多少 API 费用”。我实测下来,如果只追求稳定,其实并没有想象中那么贵。关键在于三件事:
第一,角色分模型。简单任务用便宜模型,复杂任务用贵模型。前面角色定义里我已经写好了,调研员和编辑用gpt-4o-mini,分析师用gpt-4o,整体费用比全流程大模型降低 40% 左右,质量几乎没下降。
第二,缓存中间结果。同一个话题的调研数据,如果只是换一种报告风格,就没有必要重新跑一遍调研员和分析师。我把每个阶段的结果按 topic + 阶段名缓存到本地 JSON 文件,第二次运行直接读缓存,秒级出结果。
第三,并行化。如果任务可以拆成多个独立子调研,就开多个线程同时跑不同调研员,而不是串行等待。比如一个市场报告要分析“国内市场”和“海外市场”,两个调研互相独立,并发执行能把总耗时从 6 分钟压到 3 分钟。
延迟优化要特别注意一个点:不要让编排器在工作流中频繁阻塞等待。如果某个阶段需要人工确认,就先把已完成内容持久化,然后退出循环,等待用户回调。不然一次真实验证可能让你白付好几轮等待费用。
5. 常见问题与排查技巧实录
5.1 问题排查速查表:Agent 循环失控怎么处理
在实际跑流程时,我遇到过最多的问题是 Agent 陷入死循环或重复执行同一操作。比如调研员反复搜索同一个关键词三次,或者项目经理在不该拆解任务的时候继续拆解。我把常见症状、原因和对应方案整理成了一张表:
| 症状 | 可能原因 | 解决方案 |
|---|---|---|
| Agent 重复执行同一工具调用 | 工具返回结果未更新上下文,模型看不到新信息 | 在工具返回后强制插入 assistant 消息;记录调用次数,超过上限直接终止 |
| 任务被拆解得越来越细 | 项目经理的 system prompt 缺少“拆解到二级步骤为止”的约束 | 在 prompt 里明确“只拆一次,不要继续细分”;设置拆解结果的 max_tokens |
| 两个 Agent 反复对话无法收敛 | 缺少终止条件,双方都以为对方在等自己 | 编排器统一判断:重复内容超过 2 次则强制合并或跳到评审角色 |
| 某个 Agent 输出空内容或只有感谢语 | 前一个 Agent 的输出不标准,导致它理解错任务 | 检查标准化输出要求;加一个 reviewer Agent 做格式校验 |
| 最终报告丢了一部分关键事实 | 中间有一个 Agent 把上下文里的关键内容截断了 | 启用完整消息存储,让编辑 Agent 从原数据而不是摘要中获取关键数据 |
这套排查表可以当成通用调试清单,先看症状,再按顺序检查对应模块。我自己的习惯是遇到问题先打印每一步的消息列表,看消息从哪里断的。多 Agent 系统的问题 90% 出在消息结构或上下文传递上,而不在模型本身。
5.2 质量不稳定:让结果更“靠谱”的三个技巧
多 Agent 系统还有一个痛点:同样的输入,每次输出飘忽不定。别人演示时效果好到起飞,你上手就翻车。这不是你的代码有问题,而是采样随机性在叠加。
第一个技巧是固定 seed。如果模型接口支持seed参数,就在配置里固定一个值。很多 SDK 支持seed但不保证绝对一致,可它至少能把波动压到最低。第二个技巧是多次采样 + 投票。让分析师角色跑三次,把三次结果都用编辑 Agent 汇总,取最一致的观点。这样能显著降低单次模型“跑偏”的概率。第三个技巧是增加评审 Agent。在最终交付前让一个独立的 reviewer Agent 对照任务要求检查报告,缺点和错误直接当成附加任务交给编辑修改。
我试过最夸张的一次,让一个审核 Agent 检查调研报告,它直接把“2024 年市场规模”写进报告的编辑版本标红并附了一句“该数据来源时间较早,建议更新到 2025 年”。这个检查效果不是靠提示词魔法,而是靠“职责分离”实现的。
5.3 成本超预期:怎么看账本并优化
跑完整套流程后,一定要有成本监控。最简单的方法是记录每次调用的 token 数量和模型名,写入本地日志。我把每次调用信息按“角色名”聚合,很快就能看出哪类角色花钱最多。
如果调研员烧钱太狠,就压缩它的输出长度,或者用更便宜的小模型。如果分析师烧钱太狠,就把它的输入上下文先做摘要,只传关键结论而不是全部原始数据。如果编辑 Agent 的temperature太高导致多版本长度失控,就把max_tokens压低。
还有一个容易被忽略的成本陷阱:调试时的重试。我在联调阶段开着频繁重试,发现账单跑得飞快。后来我写了一个“调试模式”:调试时所有 Agent 都使用最小模型,只保留一个复杂的最终汇总用大模型。逻辑通了再切回正式模型,成本能省一大半。
6. 一些实际体会与后续扩展方向
这套 agency-agents 流程我前后迭代了好几版,从最初直接调接口,到后来加入消息总线、工具层、缓存和评审,才真正稳定下来。回头总结,我最深的体会是:多 Agent 系统的复杂度不在模型,而在工程。
通信协议、上下文管理、任务边界、终止条件,这些看似枯燥的工程细节,才是决定一个多 Agent 应用能不能从 demo 走到生产的关键。模型反而成了最不重要的变量——换个更强的模型,如果不解决消息乱传的问题,照样输出烂结果。
后续如果在你的项目里继续扩展,我建议优先做两件事:一是给消息总线接入向量数据库,让 Agent 能根据语义检索历史结论,而不是每次都把所有内容硬塞进上下文;二是做任务路由,让每个任务自动匹配最合适的角色组合,而不是固定一个流水线。
我个人踩过最大的坑是“贪多”:一开始恨不得让 Agent 什么都能干,后来老老实实做减法,每个角色只管一件事,效果立刻上来了。做多智能体协作,少即是多,这不是一句鸡汤,是真的能帮你省下大量调试时间的实战经验。