资讯动态

多Agent影分身实战:从上下文窗口困境到任务调度与角色隔离

发布时间:2026/9/28 16:40:15 来源:尧图企业网站定制
1. 单打独斗的Agent到底卡在哪1.1 上下文窗口和长任务的老大难我前阵子接了一个活儿让一个agent独立完成一份两万字的行业分析报告。最初我以为这就是加长prompt的事结果跑了三轮报告写到一半数据口径换了文风也飘了甚至出现了“第一部分说市场在萎缩第三部分又假设市场在爆发”这种自己打自己脸的结论。我盯着日志看了很久冒出一个很自然的念头恨不得把这个agent掰成两个。后来我捋了一下问题根源其实特别简单大模型对话窗口是有限的你给一个prompt塞进去越多的背景、角色要求、阶段性指令token就会越早逼近上限模型就越容易“捡了芝麻丢西瓜”。长任务跑到后面最开始的指令已经被后面生成的内容冲淡了于是它开始自由发挥。很多人以为这是模型“变笨了”其实不是而是上下文窗口里真正有效的“约束信息”占比越来越低。这个现象在单agent场景里几乎无解。你可以试着把任务切分成多个子任务然后再手动让同一个agent逐段生成最后自己来汇总。但问题随之而来同一个agent多次调用之间如果不做任何状态管理它根本不知道自己上一轮生成了什么数据口径也好、文风也好都没法保持一致。换句话说不是模型不行是“单线程、无记忆、无分工”的架构撑不住复杂任务。1.2 角色冲突一个提示词解决不了所有问题还有一类更隐蔽的问题当你希望一个agent既做分析又做创意既严谨又活泼的时候提示词里的要求就会互相打架。比如你写“你是一位资深产业分析师但同时要有新媒体风格的感染力”模型往往会在这两种风格之间来回摇摆结果就是四不像。这不是模型不理解你的要求而是角色之间的边界太模糊单一段system prompt很难同时让多个身份稳定共存。我试过把角色要求写得很细比如规定什么时候用分析师口吻、什么时候用媒体口吻但实测效果依然不稳定尤其是在长文本生成中模型跨段落切换角色时经常“刹不住车”。后来我发现真正有效的方式是把角色拆开让不同的分身各自独立维护自己的system prompt。分析师分身只负责输出数据、判断和逻辑编辑分身在拿到分析师结果后再单独做二次创作。这个“先产出后润色”的隔离模式比在同一个上下文里反复切换角色要稳定得多。所以多Agent的第一个价值不是“人多力量大”而是“边界清晰”。每个分身只需要专注一类职责它的prompt可以做得非常纯粹不要求模型同时扮演多个彼此冲突的角色。这就好比你不会指望同一个人既当会计又当销售还当法务但在单Agent场景里我们偏偏一直这么要求模型。1.3 多Agent的收益不是“人多力量大”而是“边界清晰”聊到这儿你可以理解成把一个大而全的agent拆成多个小agent本质上是把一套容易失控的复杂指令拆成几套稳定可控的简单指令。每一条简单指令都让模型在一个明确边界内干活犯错概率就会直线下降。并行提速是另一个附带收益。比如你要调研十个渠道的信息单agent只能按顺序一个一个查而拆成十个分身以后只要接口允许并发调用就可以同时查。实测下来类似“收集竞品资料”这种任务拆成四个调研分身并行跑耗时能从十几分钟压缩到三四分钟。当然不是所有任务都适合并行像“先分析再写报告”这种强依赖链路就必须等前一个分身干完才能交给下一个。但即便是这种串行依赖关系把不同环节隔离成独立分身也能让每个阶段自己拿着“上阶段的产出”重新组织上下文而不是让模型背着前面所有历史继续硬扛。所以多Agent这事听着玄乎说白了就是给每个角色分配独立上下文给不同角色建立明确的生产关系。只要这两点想清楚了真的能把一个agent掰成两个、三个甚至十几个来用。2. 多重影分身的几种实现姿势框架选型与手写调度2.1 主流的框架怎么干如果你打算正经搞多Agent绕不开当前主流的几个框架比如AutoGen、CrewAI、LangGraph。它们对“分身”这件事的抽象方式不太一样。AutoGen更偏“对话式协作”你可以创建多个Agent每个Agent有自己的名字、系统提示词和工具然后让它们通过互相发消息来协作。这种模式非常自然适合做“多个专家讨论一个复杂问题”的场景。但副作用是如果讨论没有明确主持人Agent之间容易聊起天来刹不住车上下文飞涨成本也飞涨。CrewAI则更像一个“流程式团队”你定义角色比如“研究员”“分析师”“文案”再定义一个任务列表让角色按顺序或按层级去完成。它的核心是Task和Agent绑定一个Agent干完一件事把结果传给下一个Agent。CrewAI对新手很友好因为它把“角色”和“流程”都做成了模板你几乎不用写调度代码。LangGraph是另一种路子它更底层强调图状态机。你可以把每个Agent当成图里的一个节点节点之间用边连接边的方向就是数据流动的方向。如果你需要非常精细地控制流程比如“如果A的结果不达标就回到B重新处理”LangGraph是更稳的选择。但它在代码上明显更重需要你理解状态管理、条件分支和递归这些概念。这三个框架我都跑过。AutoGen很灵活但会话成本控制需要自己调CrewAI上手快但稍微复杂一点的动态流程就要绕路LangGraph控制力最强学习曲线也最陡。我的建议是不要一上来就选框架先用最小的代价把多Agent这件事的原理走通再挑框架。2.2 手动调度器的核心抽象抛开具体框架多Agent系统拆到底就是三样东西分身注册表、任务队列、结果总线。分身注册表里存着每个分身的名字、角色提示词、它能用哪些工具、它依赖哪个分身的产出。这相当于一个“同事目录”调度器拿到任务以后先查这个目录看谁能干这件事。任务队列则负责把大任务分解成一个个可独立执行的小任务按依赖关系排序。结果总线是所有分身产出汇合的地方它负责把不同分身的输出按任务编号归拢供下一个阶段使用。我第一次手写调度器时发现最难的不是让多个Agent跑起来而是“任务分解的粒度”。同一个用户请求你可以拆成3个任务也可以拆成10个任务。拆得越细每个分身越专注但任务之间的交接成本也会变高错误会在交接过程中累积。后来我总结了一个经验先按“角色责任”拆不要按“文本段落”拆。这句话的意思是你不需要让分身A写第一节、分身B写第二节而是让分身A负责“市场调研”分身B负责“观点提炼”分身C负责“成稿润色”。这样每个分身的产出都有独立价值即使某个分身结果质量差一点下一个分身也能基于它做纠偏。如果你按段落拆那前一段写得好不好会直接影响下一段的连贯性那不是并行那是拼图。2.3 为什么建议你先手写一个裸调度器很多人喜欢直接上框架我刚开始也一样。后来发现框架会把很多细节藏起来比如任务是怎么分发的、上下文是怎么传的、结果是怎么合并的你都看不到。一旦出问题你只能对着框架文档猜。所以我建议哪怕你最后打算用CrewAI或LangGraph也先自己手写一个裸调度器哪怕只有两百行代码。目的不是为了做产品而是为了让你亲眼看清楚分身的生命周期、上下文何时被构建、结果如何被汇总。这些理解养成了之后再去看框架文档你会发现自己能预判很多设计取舍。另外现在热门的“ReAct”模式也值得提一嘴。ReAct就是让Agent循环执行“思考-行动-观察”的过程这其实就是一个最基础的单Agent分身。很多团队在做多Agent时底层每个分身都用ReAct来跑只是外面包了一层调度器。你有手写ReAct的经验再去理解多Agent调度会发现就是一环套一环的事情真没那么玄。3. 亲手拆一个Agent从任务分解到结果汇总的完整代码3.1 分身池子Agent定义与角色模板我们直接写一个最简版的多Agent调度器语言用PythonLLM调用留成接口。这个例子足够你本地跑通也方便扩展。先定义SubAgent类也就是“分身”from dataclasses import dataclass, field from typing import Callable dataclass class SubAgent: name: str system_prompt: str tools: list field(default_factorylist) model: str gpt-4o-mini llm_call: Callable None # 外部注入的LLM调用函数 def run(self, prompt: str) - str: messages [ {role: system, content: self.system_prompt}, {role: user, content: prompt} ] return self.llm_call(messages, self.model)这里的llm_call是外部注入的也就是说你可以自己接OpenAI、Claude、或者本地模型。tools暂时放空后面再说。这个类的关键点在于每一个SubAgent都有完全独立的system_prompt这样它们就是真正的“分身”而不是共享一份角色指令。接下来创建三个分身调研员、分析师、编辑。它们的system_prompt要写得足够具体互不干扰。researcher SubAgent( name调研员, system_prompt你是一个严谨的行业调研员。你只负责输出事实、数据和来源。禁止输出个人观点禁止跨过调研阶段直接下结论。所有数据必须标注未验证或已验证。, modelgpt-4o-mini ) analyst SubAgent( name分析师, system_prompt你是一个产业分析师。你会接收到调研员的原始材料你负责提炼关键趋势、识别风险和机会。你的输出必须逻辑清晰有论据支撑。, modelgpt-4o-mini ) editor SubAgent( name编辑, system_prompt你是一位资深主编。你负责把分析结果改写成适合管理层阅读的汇报稿。要求结构清晰、语言简练、不改变原意、不加新事实。, modelgpt-4o )注意我让编辑用了gpt-4o因为最后一步改写对语言质量要求高而前两步用mini模型就行。这就是多Agent的好处没必要所有分身上同一个大模型角色复杂度不同选不同模型成本和效果都能兼顾。3.2 调度器任务拆分、分发、收集、合并有了分身池还需要调度器。最简调度器不用搞复杂图计算一个函数就够了。def run_multi_agent(pipeline: list[tuple[SubAgent, str]], llm_call) - str: pipeline: [(agent, instruction), (agent, instruction), ...] 按顺序执行前一个agent的输出会拼成后一个agent的输入。 context for agent, instruction in pipeline: if context: prompt instruction \n\n上下文材料:\n context else: prompt instruction context agent.run(prompt) print(f[{agent.name}] 产出长度: {len(context)} 字) return context这实际上是串行依赖链适合“调研-分析-成稿”这种强依赖任务。如果你要并行可以把pipeline里的第一层拆成多个调然后一起等结果回来再汇总给下一层。并行版用Python的concurrent.futures就可以from concurrent.futures import ThreadPoolExecutor, as_completed def run_parallel_agents(tasks: list[tuple[SubAgent, str]]) - list[str]: results [None] * len(tasks) with ThreadPoolExecutor(max_workerslen(tasks)) as executor: future_map { executor.submit(agent.run, prompt): i for i, (agent, prompt) in enumerate(tasks) } for future in as_completed(future_map): idx future_map[future] results[idx] future.result() return results并行版适合“让三个调研员分别查不同维度的信息”这种任务。两个函数加在一起一个能处理串行依赖一个能处理并行收集已经覆盖了80%的多Agent需求。3.3 一个实际例子让五个分身合写一份市场分析我们用这个模式做一个实战五个分身合写一份智能硬件市场分析。任务流程是并行调研三个维度然后汇总分析最后成稿。第一步并行派三个调研分身出去收集信息tasks [ (SubAgent(name调研A, system_prompt你是智能硬件市场调研员重点收集市场规模和增长率。), 请收集2024-2025年全球智能手表市场规模。), (SubAgent(name调研B, system_prompt你是智能硬件市场调研员重点收集主要品牌和市场份额。), 请收集苹果、华为、三星在智能手表市场的份额变化。), (SubAgent(name调研C, system_prompt你是智能硬件市场调研员重点收集用户需求和痛点。), 请收集智能手表用户最关心的功能和弃用原因。), ] reports run_parallel_agents(tasks)第二步把三份报告拼成一份“调研汇总”交给分析师merged \n\n.join(reports) analyst_agent SubAgent(name分析师, system_prompt你是产业分析师基于调研信息提炼趋势和风险。) analysis analyst_agent.run(f以下是三份调研信息请提炼关键趋势、潜在风险、机会点:\n{merged})第三步交给编辑成稿editor_agent SubAgent(name编辑, system_prompt你是主编把分析改写成1500字汇报稿保留数据。) final_report editor_agent.run(f请基于以下分析写一篇面向管理层的工作汇报:\n{analysis})整个过程代码量不到五十行已经把一个单agent干不了的重活拆成了三个环节、五个分身。实测下来最明显的改善是每一个分身生成的内容都更“干净”了调研员不再突然冒出一句营销文案分析师也不会把调研数据和自己的猜测混在一起。这就是角色隔离带来的直接收益。4. 分身之间的记忆和通信短期工作区与长期记忆库4.1 共享工作区哪些信息必须所有分身可见多Agent跑起来以后最容易踩的坑是“分身之间信息不同步”。比如调研员查到了2025年Q2出货量但分析师看到的还是旧数据最后报告里出现两套数字。所以我们需要一个共享工作区让关键信息一旦产出所有相关分身都能读到。这个共享工作区在技术实现上可以很简单一个全局字典键是任务ID或主题名值是请求分发的数据。在每个SubAgent的run方法里把它做成一个只读参数传进去。千万不要让每个分身都自己去写同一个全局变量那样会出现竞争和覆盖。正确做法是上一层分身产出的结构化信息由调度器统一写进工作区下一层分身只能读取。我自己的习惯是定义一个ProjectState类class ProjectState: def __init__(self): self.data {} def update(self, key: str, value: str): self.data[key] value def snapshot(self) - str: return \n.join(f{k}: {v} for k, v in self.data.items())调度器每次调用分身时把state.snapshot()拼进prompt让分身看到当前已知信息。这样即使某个分身耗时很长其他分身已经产出的数据也不会丢。4.2 长期记忆与存档别让分身失忆短期工作区解决的是“当前任务内的信息同步”但多Agent跑长周期任务时还需要长期记忆。最近大家讨论agent记忆体系常提到短期记忆、长期记忆和永久记忆。说白了短期记忆就是对话上下文也就是分身的输入输出。长期记忆是你从多次任务里沉淀出的可复用知识通常存在向量库里。永久记忆是类似企业知识库、产品手册这类固定不变的背景材料。在多Agent系统里我建议为长期记忆设计“命名空间”。也就是说每个分身只查询和自己职责相关的记忆。比如调研员查询“市场数据”记忆库编辑查询“文风偏好”记忆库而不是都去问同一个全局向量库。否则一个分身学到的东西污染了另一个分身的判断反而比没记忆更糟。我做过一个简单的做法给向量集合的metadata里加一个namespace字段按分身名字过滤。这样查询时带上分身名就能保证记忆隔离。注意记忆隔离和共享工作区并不冲突——短期时效信息走共享工作区长期沉淀知识走独立记忆库两者各管一件事。4.3 通信协议与冲突仲裁子Agent吵架怎么办几个分身一起跑难免会给出互相矛盾的结论。比如调研员A说市场增长5%调研员B说市场下滑2%最后报告怎么写这就需要一个轻量级的仲裁机制而不是简单投票。我的经验是设置一个“冲突处理分身”或者让下一层分析师显式处理差异。具体来说你在给分析师的prompt里写清楚“如果三个来源数据冲突优先采信与权威出处一致的数据并在报告中标注分歧”。这相当于把仲裁规则前置到prompt里比等结果出来后再人肉裁决高效得多。另外一个更工程化的做法是给每个分身返回的数据加上置信度。简单任务返回“我确定”复杂任务返回“可能是”。调度器在汇总时可以按置信度加权。多Agent系统不怕结果不一致怕的是不一致了没人发现最后直接糊成一个前后矛盾的大杂烩。5. 影分身实战中的坑我替你踩过的几个5.1 任务拆得太碎上下文反而爆炸第一次上手多Agent的人普遍会犯一个错误任务拆得越多越好。我曾经把一个“写产品发布简报”拆成八个分身包括“标题创作”“摘要”“痛点分析”“竞品对比”……结果每个分身都要共享一份完整背景材料八个分身加起来消耗的token是单agent的好几倍而且因为信息传递次数变多出错率反而上升了。后来我琢磨出一套简单标准如果某个分身在被调用时需要把前一个分身的大部分输出原样搬运过来那么这两个分身就不该拆开。拆分的意义在于“产出形态不同”而不是“段落不同”。调研员产出原始事实分析师产出判断编辑产出定稿文字——这三个产出的形态差异足够大才值得拆。如果只是把一个自然段拆给两个分身去写那只是增加了上下文复制成本毫无收益。我在实践中一般遵循“2/8法则”先用最少的分身数量跑通一般三个左右然后再根据卡点逐步增加。比如发现调研阶段信息太杂才考虑把调研拆成数据、竞品、用户三个方向。不要一开始就搞十几个分身。5.2 子Agent目标漂移与提示词污染分身多了以后最气人的是有些分身会“越俎代庖”。我遇到过调研员自己给结论下判断把事实和观点混在一起让后面分析师很为难。还有个编辑分身为了追求文采擅自改了调研数据的表述导致数据和原文对不上。这些都属于目标漂移。根源往往是分身的system_prompt写得不够“窄”。解决方法是把每个分身的职责边界描述得非常具体最好明确写出“你只做什么”和“你禁止做什么”。比如调研员的prompt里就写“禁止输出任何非事实判断禁止提出建议”编辑的prompt里写“禁止增加新事实禁止修改数值”。另外不要在不同分身之间复用同一个System prompt模板再微调。模块里A的prompt里残留了B的角色描述就会污染。我在代码里会为每个分身单独写纯文本常量同时避免在prompt里写“你是一个”这种含糊表述而是写“你是唯一负责XXXX的角色”。这能让模型的角色意识更集中。5.3 成本与延迟分身越多钱烧得越快多Agent确实能提升效果但不是免费的。你拆成五个分身每个分身平均跑两轮LLM加在一起就是十次调用。如果每次调用都让所有分身用最强的模型一次综合任务的成本可能是原来的一倍甚至好几倍。我的建议是给分身按“认知难度”分级配置模型。收集事实和做简单归纳的用高性价比小模型需要推理、判断、创意改写的用大模型。我们在前面那个例子里就是这么做的调研用gpt-4o-mini分析用gpt-4o-mini编辑才用gpt-4o。实测下来效果几乎没差但成本能省30%左右。延迟也一样。如果多个任务之间没有依赖关系一定要用并发执行而不是写for循环串行跑。串行跑五个分身时间就是五倍改成线程池并发只要接口没限流延迟基本接近单个分身。这一点不做好多Agent很容易被用户吐槽“太慢了”。5.4 越权与安全每个分身都应该有“最小权限”最后聊一个容易被忽略的点多Agent的安全。很多人给所有分身都配同样的工具集比如所有分身都能搜索、读文件、发邮件。这其实很危险因为你不知道哪个分身会在什么上下文里触发副作用。我的建议是“最小权限原则”调研分身给它搜索和读网页的工具但不给它发邮件的权限编辑分身只给它读写指定文档的能力不开放网络搜索。这样即便某个分身的prompt被别人构造得乱七八糟它也没法越权乱来。在代码层面你可以把tools列表作为SubAgent的重要属性调度器只在调用对应分身时才把该分身的工具注入它的环境。还有一点所有分身产生的中间结果尽量写进独立的工作目录不要直接覆盖正式文件。多个分身并行写入同一个文件会出各种离奇问题而且很难排查。我在一次多Agent文档生成实验里因为两个分身同时写一个markdown文件结果互相把内容截断了最后靠日志才定位到。后来强制改成每个分身一个输出文件问题再也没有出现过。写这篇文章的时候我又把手头一个老项目的架构翻出来看了看发现当初那个让我头疼的“单agent精分”案例现在已经完全变成了一套标准流程先定角色边界再搭调度器最后配记忆与工具权限。整套思路下来最关键的并不是某个框架或某段代码而是“愿意把一个大而全的agent拆成几个小而专的分身”。如果你正被单agent的上下文溢出和目标漂移折磨不妨照着上面的思路试试第一次拆完跑通的那一刻你会觉得“恨不得把一个agent掰成几个”真不是玩笑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑