Agency-Agents实践:拆分Agent构建稳定多智能体系统

发布时间:2026/10/26 16:10:32
Agency-Agents实践:拆分Agent构建稳定多智能体系统

1. 项目定位与整体思路拆解

1.1 "agency-agents"到底是什么:从单Agent到多智能体协作

"agency-agents"这个项目名,如果你拆开看,很有意思。"agency"既指"代理机构",也有"中介、主办方"的意思,"agents"则是智能体。"agency-agents"合在一起,本质上就是一个把多个AI智能体组织成"虚拟团队"的协作框架。与单纯接一个大模型API、让它在单次对话里完成任务不同,这个项目要解决的是:如何把一群"各有专长的AI员工"像管理真实团队一样编排起来,让它们各司其职、互相配合,最终交付一个复杂的成果。

我用这个框架的初衷很朴素:单Agent在稍复杂的任务上真的会"翻车"。举个例子,我曾经试图让一个Agent独立完成"收集市场数据 → 分析竞品 → 输出调研报告"这条完整链路。前十分钟它表现得像个专家,等它处理到第三四个环节时,开始出现生成质量明显下滑、遗忘前面关键结论、甚至把一个环节的结论错误复用到另一个环节的情况。这不是模型能力不够,而是"单线程上下文"的天然短板——一个Agent既要记着最初的目标,又要处理当下的子任务,还要兼顾中间所有步骤的中间结论,任何一个细小的注意力偏移,都会让整个链路崩掉。

Agency-agents的解法是把"一个大而全的Agent"拆成"多个小而专的Agent",中间通过一个调度层连接。每个Agent只负责链路里的一个环节,它的上下文只包含"自己这一步该看的输入"和"需要输出的结果",干净、清晰、无干扰。这样一来,每个环节的执行质量都被拉高了,整体交付的可靠性自然就上来了。这个概念不管你是做AI应用开发的工程师、正在规划企业级AI方案的技术负责人、还是对智能体自动化感兴趣的产品经理,都建议你认真了解一下——因为它代表了一种"把大模型能力落地成可用系统"的关键思路。

多智能体这个概念近两年借着"agents anywhere"这股热度被反复讨论,但真正能把"多Agent协作"做成稳定、可调试、可上线的系统,不是给一堆Agent发个群聊就完事。它背后涉及角色分配、消息传递、状态管理、上下文隔离、异常熔断这些工程问题——这也是我写这篇文章的原因,我把自己踩过的坑、验证过的实践路径,完整拆出来供你参考。

1.2 为什么不是"一条提示词解决所有问题"

做技术分享的时候,经常有人问我:"我为什么不干脆写一条巨长的提示词,把所有要求塞进去,一次性让模型输出全部结果?"说实话,这是一种典型的可行但不可持续的方案。单条超长提示词的本质,是让模型在"一次推理"里同时完成理解、拆分、执行、校验所有动作,这等于让一个员工同时扮演产品经理、数据分析师、文案写手和质检员。这个员工确实什么都会一点,但每一项都做得一般,而且一旦某个环节出问题,你几乎无法定位"到底是哪个步骤错了"。

我印象很深的一次实验:我用一条提示词让模型生成一份市场进入策略报告,结果模型在"市场规模预测"部分直接使用了竞争对手官网的推广数据,完全没有做交叉验证。如果这是一个独立的数据Agent,我一眼就能看出它接入的数据源有问题,但在一整段生成的文本里,要想追踪这个错误源,几乎等于大海捞针。多Agent架构把这一步"拆开",每个Agent只做一件事,输入和输出都是可检查的,问题环节一眼就能揪出来。

再从工程角度看,多Agent架构带来的三个优势是实实在在的:

第一,可定位性。系统里每个Agent的输入输出都是结构化的,任何一个环节出问题,直接看该环节的日志即可,不是在整段对话里捞线索。

第二,可替换性。想换某个环节的模型或者优化某个Agent的提示词,只改那一个环节就行,不影响其他部分。如果全塞在一条提示词里,每一个微调都可能引发蝴蝶效应。

第三,可审计性。企业级应用绕不开合规与审计的需求,多Agent的流程天然就有任务记录、执行轨迹,每一步做了什么、用了什么数据,都可追踪。

不过话也要说回来,多Agent不是银弹,Agent数量多不代表系统聪明。我见过有团队把六个Agent塞进一个流程里,光互相传递消息的耗时和Token开销就拖垮了整体性能,产出质量反而不如两个Agent的版本。核心问题不在于"有多少个Agent",而在于"每个Agent是不是真的独立承担了不可替代的职责"。拆分的粒度应该是"按职责、按上下文隔离需求来拆",而不是为了看起来厉害而拆。任何Agent的加入都需要回答一个问题:这个环节如果并入相邻Agent,是否会显著增加上下文复杂度或降低结果可靠性?如果不是,那就不该拆出来。

2. 核心机制与设计要点

2.1 Agent的角色定义与职责拆分

在"agency-agents"这类框架里,Agent的角色定义是整套系统质量的天花板。表面的操作是"写一段系统提示词",但真正写得好的角色定义,一定包含四个层次:身份、职责、边界、输出格式。

身份解决的是"你是谁",比如"你是一位有十年消费电子行业经验的市场分析师";职责解决的是"你负责干什么",比如"分析给定数据集中各品牌的价格带分布和增长趋势";边界解决的是"你不能干什么"——这一层最容易被忽略,但不写清楚的后果非常严重:Agent会越权。比如你让它做数据分析,它写着写着开始给你提营销建议了。输出格式解决的是"结果长什么样"——比如"返回一个JSON对象,包含价格带分段和趋势摘要两个字段"。

我常用的角色提示词模板长这样:

你是一位[身份]。 你的任务:[职责描述,越具体越好]。 在执行任务时,注意以下边界: - 不要[禁止事项1,如"不要给出主观建议"] - 不要[禁止事项2,如"不要引用未经来源标注的数据"] - 如果输入信息不充分,直接说明缺失信息,不要猜测补全。 输出要求:[明确的结构化格式,如"Markdown列表"或"JSON对象"。 你需要将完整结果返回给下一个处理环节。

这套模板里最关键的其实是"边界"和"输出格式"两层。我在一个内部分享里说过,给Agent戴上"边界"的枷锁,不是限制它的能力,而是保护它的专注度。边界写清楚之后,Agent就不会自作主张地扩大工作面,下游Agent也就不会被无关信息污染。

2.2 Agent间的通信协议与任务流转

多Agent系统的骨架不是Agent本身,而是Agent之间的消息通道和任务流转机制。最初我做这个项目时,天真地让Agent之间"自由对话"——A把结果发给B,B看完发表意见,A再回复……结果两个Agent在第七轮对话之后彻底偏离主线,开始纠结一个不重要的细节,最终流程因上下文溢出而崩掉。这次事故让我确定了一件事:Agent之间的通信绝对不能是自由聊天,必须是结构化消息。

我在实际项目中给每个Agent定义了一套统一的消息格式,核心字段包括:

  • message_type:消息类型,如task(派发任务)、result(返回结果)、error(报告错误)、review(审核意见)。
  • from:发送方Agent的名称。
  • to:接收方Agent的名称。
  • payload:实际的数据体,通常是一个JSON对象,包含该环节所需的全部输入或输出。

这套结构看起来简单,但它解决了三个核心问题:一是每条消息的来龙去脉都可追踪;二是每个Agent只订阅自己关心的消息类型,不会接收到无关信息;三是整个流程可以像查物流一样,随时定位"任务走到哪一步了"。

任务流转模式上,我通常只推荐两种。第一种是编排者模式(Orchestrator),一个中心Agent统一调度,A完成后通知调度者,调度者再把任务派给B。这种模式的优点是流程清晰、容易控制,适合环节固定、逻辑明确的场景。第二种是管道模式(Pipeline),每个Agent只处理上游的结果并传给下游,像工厂流水线一样。相比之下,那种让Agent"自己商量下一步谁该干什么"的自治协作模式,我在生产环境里试过几次,小规模demo确实显得很酷,但一旦Agent数量超过三个,调试难度就呈指数级上升,最终还是要靠一堆硬编码的规则去兜底。所以我的建议是:由中心节点控制流程,Agent专注于自己的节点任务,不要让Agent承担调度职责。

2.3 记忆与上下文的隔离策略——多Agent项目最容易被忽视的坑

如果你只记住这篇文章里一个"经验教训",我希望是这个:多Agent项目的上下文必须做隔离,绝对不要全部共享。

很多人在实现多Agent系统时,习惯性地把"整个会话的历史记录"一股脑塞给所有Agent共享。这种做法表面上是"让每个Agent都有全局视野",实际上是把多Agent系统退化回单Agent超长对话,而且是"token消耗翻倍版"的单Agent。每个Agent都要处理跟自己无关的上下文,注意力被稀释,Token开销暴涨,还经常出现"串味"——数据分析Agent给你输出了一段带有文案Agent口吻的文本,一眼就是被污染了。

我的上下文分层策略是这样的:第一层是项目级共享记忆,只有放那些所有环节都需要参考的全局事实,比如项目名称、最终目标、关键约束条件。共享记忆在每个Agent启动时注入。第二层是Agent级私有记忆,只放该Agent自己产出的信息和需要读取的输入。比如"调研Agent"整理出的事实清单只存在于它自己的状态里,作为消息payload发给下一个Agent后,表示"这个环节已完成",而非被所有Agent永久持有。第三层是消息级临时记忆,随消息传递,任务完成后即可丢弃,用来承载两个Agent之间的数据交接。

这套策略落地之后,我的一个五Agent调研系统在成本上的改善非常明显:Token消耗大约降到了原来的三分之一,生成结果的稳定性也有明显提升。因为每个Agent的上下文都够小、够聚焦,模型也就更不容易"想东想西"。

3. 实操过程与核心环节实现

3.1 环境准备与基础配置

理论说再多,不如亲手跑一遍。下面我以LangGraph为例,带你把一个最小的多Agent系统搭起来。选用LangGraph的理由很简单:它原生支持状态图建模、自带节点和边管理、能实现条件路由,非常适合做Agent流程编排。你不用非得用这个框架,但它的设计思路值得参考。

环境配置上,需要满足以下前提:

  1. Python 3.10+ 的环境。
  2. 安装LangGraph和模型调用库,命令如下:
pip install langgraph langchain-openai
  1. 准备大模型API访问。当前主流的模型服务商(OpenAI、Anthropic、DeepSeek、智谱、通义等)都支持函数调用和结构化输出,这对Agent场景是必需的。建议把API密钥放进环境变量或独立的配置文件,不要在代码里硬编码。
export LLM_API_KEY="你的密钥" export LLM_BASE_URL="你所用模型服务的接口地址"
  1. 模型参数方面,我非常建议把temperature设置到 0.2 以下。Agent场景不是在"写诗",而是在"执行任务",温度越低,输出确定性越高,后面审核环节的压力就越小。

3.2 从零搭建一个多Agent协作流程

为了演示,我们搭建一个"行业简报自动生成系统",它包含三个Agent:

  • 资料收集Agent:从原始文本中筛选和提炼关键数据。
  • 分析Agent:对数据做结构化分析,输出主要结论。
  • 写作Agent:依据分析结论撰写简报成稿。

这三个Agent之间采用"管道模式"串联,再用一个小型的编排层控制流程。以下是基于LangGraph的核心实现:

from typing import TypedDict, List from langgraph.graph import StateGraph, END class BriefState(TypedDict): raw_data: str # 输入:原始资料 key_facts: List[str] # 中间:收集Agent提炼的事实 analysis: str # 中间+输出:分析Agent的结论 final_brief: str # 输出:写作Agent生成的简报 def collect_agent(state: BriefState): """资料收集Agent:从原材料中提炼关键事实。""" prompt = f"""你是一名产业资料分析助手。 从以下原始资料中提取与主题相关的关键事实。 只输出事实清单,不要加工和评论。 原始资料: {state['raw_data']}""" response = llm.invoke([ {"role": "system", "content": prompt} ]) facts = [f.strip() for f in response.content.split('\n') if f.strip()] return {"key_facts": facts} def analysis_agent(state: BriefState): """分析Agent:基于关键事实给出结构化分析。""" facts_text = "\n".join(f"- {f}" for f in state["key_facts"]) prompt = f"""你是一名行业研究分析师。 基于以下事实,给出三个核心结论,并指出一个潜在风险。 要求:结论必须有事实支撑,不能无中生有。 事实清单: {facts_text}""" response = llm.invoke([ {"role": "system", "content": prompt} ]) return {"analysis": response.content} def writing_agent(state: BriefState): """写作Agent:把分析结论写成简报。""" prompt = f"""你是一名资深商业写作编辑。 根据以下分析结论,撰写一份简短的行业简报(约300字)。 风格要求:客观、简洁、有数据支撑。 分析结论: {state['analysis']}""" response = llm.invoke([ {"role": "system", "content": prompt} ]) return {"final_brief": response.content} # 构建状态图 workflow = StateGraph(BriefState) workflow.add_node("collect", collect_agent) workflow.add_node("analyze", analysis_agent) workflow.add_node("write", writing_agent) workflow.set_entry_point("collect") workflow.add_edge("collect", "analyze") workflow.add_edge("analyze", "write") workflow.add_edge("write", END) app = workflow.compile() # 执行 result = app.invoke({ "raw_data": "这里粘贴你要分析的原始资料……", "key_facts": [], "analysis": "", "final_brief": "" }) print(result["final_brief"])

这段代码的核心逻辑很简单:先收集事实,再做分析,最后成稿。每一步的输入都是上一步的输出,Agent之间没有多余的信息交叉。运行后,你可以直接在result["final_brief"]里看到成稿结果,中间过程的关键事实和分析也都在状态对象里,方便追溯。

我建议你在跑通这个例子后,往这个最小系统里加一个"审核Agent":专门用于检查简报的事实错误和逻辑矛盾,如果发现问题,把修改意见退回给写作Agent重写。加审核环节后,系统可靠性会有质的提升,但前提是要给"退回重写"设一个循环上限,不然就有可能进入死循环。

3.3 给流程加上审核与重试机制

只加"审核Agent"不改循环上限,是很多初学者踩过的坑。审核Agent发现一处问题退回给写作Agent重写,写作Agent改完再送审,如果审核Agent要求更高,又退回……运气不好的话,这个过程会反复循环,直到Token烧穿。

我的做法是:给审核节点定义一个条件路由,并在状态里加一个"重试计数器",超过三次就强制通过或自动降级处理。示例如下:

class BriefState(TypedDict): raw_data: str key_facts: List[str] analysis: str final_brief: str draft: str # 当前稿子 feedback: str # 审核意见 retry_count: int # 重试次数 def review_agent(state: BriefState): """审核Agent:检查简报质量。""" prompt = f"""你是一名资深内容审核员。 请审核以下简报,输出PASS或FAIL,如果FAIL,请给出具体修改建议。 简报内容: {state['draft']} 审核要求: 1. 是否有明显事实性错误? 2. 是否存在逻辑跳跃或前后矛盾? 3. 是否缺少必要的结论提炼?""" response = llm.invoke([ {"role": "system", "content": prompt} ]) result = response.content is_pass = result.startswith("PASS") feedback_text = "" if is_pass else result return {"feedback": feedback_text, "retry_count": state.get("retry_count", 0) + (0 if is_pass else 1)} def route_after_review(state: BriefState): if state["feedback"] and state["retry_count"] < 3: return "rewrite" # 有反馈且次数未到,退回修改 return "end" # 通过或超限,流程结束 def rewrite_agent(state: BriefState): """修改Agent:根据审核建议修改简报。""" prompt = f"""你是一名写作者。请根据审核建议修改以下简报。 审核建议:{state['feedback']} 当前简报:{state['draft']}""" response = llm.invoke([ {"role": "system", "content": prompt} ]) return {"draft": response.content}

这种"审核-修改-再审核"的闭环,是让多Agent系统走向可用的关键设计。生产环境里,我会进一步把"强制通过"和"人工介入"结合起来:连续修改三次仍然没有PASS,就自动转给人工审核,而不是无限消耗Token。

4. 常见问题与排查技巧实录

4.1 Agent"答非所问"、输出不稳定,问题出在哪

做过Agent项目的人,一定都遇过这种情况:同一个Agent、同一个输入,两次运行的结果却不一样,有时甚至出现严重的"答非所问"。碰到这问题,我按下面的顺序排查:

第一,查temperature。如果你的模型参数里temperature设置得比较高(比如0.7以上),那两次结果不一样是正常的。Agent执行任务,温度建议降下来,控制在0.2以下,大部分随机性漂移都能解决。

第二,查提示词边界。如果你的提示词没有写"不知道就说不知道,不要猜测",Agent就会在信息不足时强行编一个答案。我给所有Agent的角色定义里都会加一句"如果输入信息不足以得出结论,请明确说明缺失的信息",这个改动看着小,但对输出的稳定性影响巨大。

第三,查上下文污染。如果Agent的输入里混入了与当前任务无关的历史信息,它的输出就会"串味"。比如你让写作Agent去写简报,结果它的输入里还包含了上一次某个用户闲聊的对话记录,它可能会不自觉地改变写作风格。这时候需要做上下文隔离,不要一股脑传全部历史。

4.2 流程卡死、任务永远在等待,怎么破

多Agent系统最常见的"运行时"故障,不是某个Agent出错,而是整个流程卡死。我踩过的最深的一个坑是:一个Agent调用了外部API,结果API超时没有返回,下游Agent一直在等待一个永远不会到的消息。整个队列就这么挂着,用户前台显示"生成中"长达20分钟。

解决思路分两层。

第一层是单点超时控制。每个Agent调用外部模型或API时,都设置一个合理的超时时间。我一般设120秒,超过就自动返回重试信号或跳过。框架自带的超时机制也很好用,LangGraph里可以给节点设置timeout参数。

第二层是全局兜底。整个流程也要有一个总超时,比如"整个简报流程必须在10分钟内跑完"。如果超时,先把已完成的中间结果保存下来,再返回给用户"部分结果+提示稍后重试"。这个设计比让用户对着一个"加载中"的按钮干等强太多了。

4.3 Token消耗爆炸、成本失控的深层原因

做多Agent系统的人都很关心成本。我观察下来,Token消耗爆炸的原因就两个:一是上下文隔离没做好,二是循环没设上限。上下文隔离的问题前面讲了,这里说一下循环上限——你不显式地写死循环次数,几个Agent真的会因为一个意见分歧无限互改下去,Token消耗分分钟让你怀疑人生。

成本控制上还有一个思路:不同环节用不同级别的模型。比如写作Agent需要创意和语言组织能力,用顶级模型值得;资料收集Agent只是做文本抽取和筛选,用轻量模型完全够。强模型和轻量模型的价格差可能在十倍以上,合理分配能让整体成本下降一个量级。这一点在"agents anywhere"的落地实践里尤其重要——当Agent无处不在、流程无处不在,成本模型就必须精细化。

4.4 上下文污染的几种隐蔽表现

上下文污染在排查时是最隐蔽的,因为它的错误不报红、不报错,只是输出质量在"不知不觉地变烂"。我总结了几种典型表现:

  • 角色错乱:数据分析Agent的输出突然带上了写作Agent的措辞风格,甚至冒出口语化的表达。
  • 重复信息:简报里出现了与前一轮草稿相同的内容,说明旧版本没有从上下文里清干净。
  • 结论漂移:两个Agent对同一个数据的引用不一致,原因是其中一个Agent引用了旧版本的数据快照。

这些问题的根源都是"状态管理不严格"。我建议从最开始就给AgentState定义清晰的字段,并且严格约定"哪些字段允许跨节点传递"。不要让Agent直接读取全局的完整状态,而是像前面代码里展示的那样,只传它需要的字段。简单地说:状态图里流动的,应当是结构化的、最小必要的数据,而不是"历史上所有发生过的事情"。

5. 说几句实在话:从demo到可用系统,还差这几步

做Agent项目一年多,我最大的体会是:多Agent系统的难点,从来不是把单个Agent调聪明,而是把一群Agent组织成一个稳定、可控、可迭代的系统。这里没有那么多神秘的高深算法,真正的功夫都在工程细节上——消息结构、上下文隔离、异常熔断、超时控制、成本分配。

如果你想把这个demo往真实项目推进,我建议依次做三件事。第一,加人工确认节点:在关键决策环节,Agent给出建议后,必须有一个人工确认动作才能进入下一步。这在企业级场景里是刚需,也是让各方安心的必要设计。第二,打通工具调用:让Agent不只会"读文本和生成文本",还能真正查企业数据库、调内部API、发邮件、操作表格,这样Agent才有实际生产力,而不只是"内容生成器"。第三,建立流程监控:把每个环节的耗时、Token消耗、重试次数、成功率记录下来,长期积累下来,这些数据会直接指导你优化模型选择和流程设计。

我在跑"agency-agents"的过程中,最后悔的一件小事是:前三个月完全没做流程版本管理。每次调提示词都像开盲盒,改那么一两个字,可能整个下游输出的风格都变了。后面我把每次调整都记录下来,能回溯到具体版本,整个系统的迭代速度才真正快起来。如果你也要把这个方向往深了做,流程版本管理这一课,建议你一开始就补上。

做一个能跑的Agent demo很酷,做一个能持续迭代、稳定产出的Agent系统很难,但它值得你花时间去打磨。希望这篇文章能帮你少踩一些我已经踩过的坑。