很多人刚开始用 OpenClaw 那会儿,都是养一个 Agent 就完事了。我也是。一个 Agent 管着日程、回邮件、跑代码、盯数据,表面上很全能,实际上用起来越来越憋屈:对话一长,它把早期的重要上下文给忘了;让它处理代码仓库的事,它还顺手想翻你的日历;最要命的是它同一时间只能跟一条主线,两件事一起进来就得排队。我一度以为是自己选的模型不行,后来才反应过来,问题根本不在模型,在架构——你把所有角色塞进了一个人身上,它当然干不好。OpenClaw 这类框架真正的玩法,是把单一 Agent 拆成多个 Agent,各管一摊,需要的时候再互相通气。这篇文章就从拆分的必要性讲起,带你完整走一遍添加多个 Agent 的配置流程、协作机制和踩坑记录。不论你是刚把 OpenClaw 跑通的新手,还是已经在单 Agent 里撞到瓶颈的进阶用户,都能直接照着操作。
1. 先把“拆 Agent”想明白:单实例的痛点和多实例的适用边界
1.1 单 Agent 的三大痛点:上下文膨胀、权限混乱、任务串行
先说第一个痛点,上下文膨胀。今天的大模型 Agent 本质上是在一个有限的上下文窗口里做推理,窗口再大也有容量。单 Agent 跑久了,所有会话历史、工具返回结果、中间思考过程全堆在同一个上下文里。比如你早上让它整理出差行程,中午让它分析一份合同,下午又让它看代码缺陷,这些内容会互相挤占空间。到了晚上你再问它早上定过哪班航班,它可能已经“忘了”——不是模型变傻了,是早期信息被截断或者权重被稀释了。我自己实测的时候,大概连续跑上两三百轮对话,明显能感觉到它的行为开始漂移,该引用的文件路径都不记得了。
第二个痛点是权限混乱。OpenClaw 给 Agent 挂工具的时候,如果只做了一个全能 Agent,那你只能给它全量工具集:能搜网、能读写文件、能操作日历、能连数据库。它自己判断什么时候该用哪个工具,但你其实没法精细控制它的行为边界。有一次我让它只做代码审查,它却自作主张改了一个配置文件,虽然没闯大祸,但那种失控感非常糟糕。工具权限和职责范围应该绑定在一起,职责不清,权限就必然混乱。
第三个痛点是任务串行。单 Agent 是单线程模型的执行方式,一个任务没走完,另一个任务就得等待。现实中我们经常有“同时进行”的需求:让一个 Agent 盯着邮件,另一个 Agent 做数据统计,第三个 Agent 在代码仓库里跑 review。串行执行意味着人力浪费,更意味着响应延迟。尤其当你把它接到消息平台、钉钉、企微这类实时环境里,一个 Agent 被长篇任务占住,其他用户的消息就没人处理了。
1.2 多 Agent 的适用场景:角色分工、实例隔离和资源配额
既然单 Agent 有这些问题,那多 Agent 到底适合解决什么?按我现在的经验,主要分三类。
第一类叫角色分工。一个 Agent 是“对外客服”,负责接待消息平台上的提问;一个 Agent 是“内部运营”,负责读报表、发周报;还有一个 Agent 是“开发助手”,只碰代码仓库。它们职责边界清晰,工具集合互相独立,谁的上下文都不会被别人的任务污染。这是最常见的用法。
第二类叫实例隔离。同一个角色,跑多个实例。举个例子,你有一个“客服 Agent”,但要同时服务多个不同业务线,不同业务线的知识库、消息通道、数据权限都不一样,那就做多个实例,每个实例绑定各自的业务配置。实例之间像独立员工,只看自己那摊事。
第三类是资源配额。有些人会把多个 Agent 当作天然的资源隔离容器,给重要的 Agent 分配更多的模型调用额度、更长的超时时间,给次要 Agent 设置较低的运行优先级。单 Agent 做不了这种差异化调度。
那什么时候不需要拆?如果任务简单、量少,比如每天就固定做一次摘要,拆了反而增加配置文件数量和维护成本。我认为判断标准就一句话:当你在单 Agent 里开始频繁写“忽略之前的指令”“只处理这类任务”这类话时,就该拆了。
2. OpenClaw 多 Agent 的底层组织方式:一个主进程,多份配置
2.1 主进程如何承载多个 Agent 实例
OpenClaw 在这类框架里有一个和直觉不太一样的做法:多个 Agent 并不需要你手动启动多个进程,而是由一个主进程统一编排。你可以把它理解成一个大楼里有很多工位,每个工位坐着一个业务专员,但大楼的供电、安保、通信网络是共用的。这个主进程负责读配置、建连接、分发消息、管理生命周期。
我见过不少人在这一步绕弯子,以为加了第二个 Agent 就要跑第二个 openclaw 进程,然后在两个进程之间搞网络通信,维护两套日志。其实这是没必要的。OpenClaw 的架构里,主进程是唯一的入口,Agent 是配置级别的对象。你在配置文件里声明了哪些 Agent,主进程启动时就加载哪些,每个 Agent 都有独立的上下文和工具绑定,但底层共享同一个运行时。这样做的好处很明显:你只需要管理一个服务,监控也只要盯一个进程的指标。
具体到执行层面,每个 Agent 实例在内存里是一个独立的执行上下文,包含它自己的会话历史、状态缓存、工具调度状态。主进程靠一个调度器在事件循环里给它们分配注意力。某个 Agent 在等待模型响应时,其他 Agent 仍然可以继续处理自己的消息,这就是我前面说的“并行”在架构层面的支撑。
2.2 配置文件的组织方式:全局配置与 Agent 级配置
OpenClaw 的配置一般会拆成两层:全局配置和 Agent 级配置。全局配置放在最外层,内容通常是服务监听地址、公共的模型通道、默认的记忆服务、日志级别等。Agent 级配置则按目录或文件拆分,每个 Agent 一份独立的配置块,包含它自己的身份、角色指令、工具列表、专属的记忆空间。
如果你去看它的配置目录,大概会长这样:
config/ openclaw.yaml # 全局配置 agents/ main-assistant.yaml # 主助理 Agent code-reviewer.yaml # 代码审查 Agent ># agents/code-reviewer.yaml id: code-reviewer name: 代码审查助手 role: | 你是代码仓库审查助手。 你只负责处理代码评审请求、分析 Issue、检查 commit。 你不负责日程管理、邮件回复和其他非代码事务。 遇到与代码无关的请求,明确拒绝并引导用户找主助理。 model: provider: default temperature: 0.2 tools: - repo-read - issue-read - commit-search memory: scope: isolated provider: local namespace: code-reviewer这里有几个字段要细说一下。role不只是身份描述,它是这个 Agent 的行为“宪法”,决定了它遇到模棱两可的情况时怎么选择。我写的“明确拒绝并引导用户找主助理”就是边界意识,这个非常有用,不要让 Agent 遇到无关请求还硬着头皮回答。
temperature我设置得偏低,因为代码审查要稳定、要遵循规则,温度太高反而容易发挥不稳定。tools这一栏只给它代码相关的工具,不给日历、邮件、网页搜索等。这样万一它成年老司机也“越权”不了,因为工具层面就没有权限。memory.scope设成 isolated,表示这个 Agent 的记忆和主助理完全隔离,它只记得自己处理过的代码任务,不会混入其他业务信息。
3.3 启动、验证和日常确认:如何确认两个 Agent 都活着且互不干扰
配置写完后,回到全局配置,在agents注册列表里加上这条新记录。然后重新启动主进程。启动日志里会看到它按顺序加载 Agent 列表,每加载一个打印一个就绪信息。此时我想测的不是“它启动了”,而是“它们真的隔离”。
我的验证方法很朴素:分别向两个 Agent 发消息。向主助理发一条“帮我安排明天下午的会议室”,向代码审查 Agent 发一条“分析一下某个 commit 的变更风险”。看响应是否符合各自的角色设定。
然后我会做一次“越权测试”,这步很多人省略,但我认为必须做。给代码审查 Agent 发一条“帮我看看明天的日程安排”,理想结果应该是它拒绝,并且给出理由。如果它回答说“我没有日历工具的权限”,说明工具隔离生效了。如果它竟然开始编造日程,那说明角色指令里没有强调边界,或者工具集没配好,需要回头修。
另外要确认两个 Agent 之间的会话互相不串场。给代码审查 Agent 发消息时,主助理那边不应该有任何日志活动;反之亦然。如果发现一个 Agent 收到消息,另一个 Agent 也产生了响应日志,就要检查消息路由配置了,大概率是事件订阅范围设置过宽。
4. 让多个 Agent 既能各干各的又能协作:路由、记忆与权限
4.1 通过消息路由实现 Agent 间的对话
多个 Agent 全隔离、老死不相往来,那和开多个独立程序没什么区别。多 Agent 真正的价值在于协作,而协作的基础是消息路由。OpenClaw 里的消息路由机制,简单理解就是事件总线:每个 Agent 既是消息的生产者,也是消费者。一个 Agent 处理完某件事后,可以发布一个事件;其他 Agent 按自己的订阅规则接收事件。
举个例子。主助理收到用户的请求:“帮我生成一份日报,并让代码审查 Agent 看一下里面引用的 commit 描述是否准确。”主助理不需要自己懂每一个细节,它可以生成日报初稿,然后发布一个review.request事件,把日报内容挂上去。代码审查 Agent 订阅了这个事件,收到后就启动自己的审查流程,处理完再发布review.complete事件,主助理收到后把结果整合回复给用户。
这个机制的好处是面对复杂任务时,专职 Agent 各负责一段,不需要全部塞进一个上下文里。我在配置时会给事件类型取固定的命名规范,比如review.request、report.generate、meeting.check,避免出现“谁能处理什么消息”的歧义。主进程的路由表里维护这些事件与 Agent 订阅关系。
4.2 共享记忆与隔离记忆的取舍
记忆这块是我实战中最纠结的部分。全部隔离吧,Agent 之间配合时缺少共同上下文;全部共享吧,又回到单 Agent 上下文混乱的老路。目前实践经验是“默认隔离,按需共享”。
默认隔离,就是每个 Agent 有自己独立的记忆命名空间,它只累积自己业务范围内的历史。这样上下文干净,行为漂移慢。按需共享,是指把一些需要跨 Agent 同步的信息放到一个公共的记忆区。比如全局待办清单、项目进度状态、用户偏好摘要,这些属于公共信息,可以放到公共记忆服务里。OpenClaw 在记忆这块一般接向量数据库做语义检索,公共记忆区相当于一个“公共大脑”,各 Agent 需要时去里面查,而不是把整个公共大脑复制进来。
我在设计时通常把记忆分成三层:本地记忆(Agent 私有)、团队记忆(同一业务线多个 Agent 共享)、全局记忆(所有 Agent 可读)。配置上就清晰了,Agent 配置里列明它读哪些空间、写哪些空间。这比给所有 Agent 开同一个内存库要可控得多。
4.3 工具权限的精细化分配:最小权限原则
工具挂载一定要坚持最小权限原则。给 Agent 配工具,就像给员工发门禁卡,只发它工作需要用到的区域权限。别因为省事就给全量工具集。
我见过一个反面案例:某个 Agent 本应只读数据报表,配置时图省事挂载了文件管理工具,结果它在一次会话里把报表目录给清理了。那不只是尴尬,是事故。所以我在给每个 Agent 设计工具列表时,会先列一张“该 Agent 的职责”清单,再逐个工具问“这个工具与职责直接相关吗”。不直接相关,就不挂。
有些工具必须做成只读模式。比如文件工具,可以分成只读和可写两大类,给大多数 Agent 只挂只读版,只有极少数核心 Agent 才有写权限。这种细致划分看起来繁琐,但能避免大量潜在的坑。
5. 实测中撞过的坑:配置覆盖、端口冲突和日志分不清
5.1 配置字段互相覆盖:坑爹的继承规则
我第一次添加第二个 Agent 时,遇到的第一个坑就是字段继承。全局配置里定义了一个默认角色模板,叫做“通用助手”,里面写了一段比较通用的系统提示。主助理没写自己的 role 字段,就继承了全局模板。第二个 Agent 我也没写 role,以为它会继承全局模板,结果启动后发现两个 Agent 的行为几乎一样,都像“通用助手”,完全没有各自的特化。
还有更隐蔽的覆盖问题。在主助理配置里我改了一个temperature字段,结果重启后发现代码审查 Agent 的温度也跟着变了。排查到最后才发现,我在两个 Agent 配置文件里重复引用了同一个配置片段,后加载的覆盖了前加载的。这就是典型的心智模型错误——以为 YAML 文件之间互相独立,实际上框架加载的时候做了字段合并,后加载的拥有更高优先级。
要解决这个问题,我的建议是:第一,每个 Agent 配置里尽量写全关键字段,不要依赖全局继承,尤其是 role、model、memory 这类核心属性,显式声明比隐式继承安全得多;第二,启动前先看框架输出的“配置合并结果”,很多版本支持--dry-run或者--check,会打印最终生效的配置内容,一眼就能看穿合并逻辑;第三,给单个 Agent 文件做修改时,只改自己那份,不要动全局公共片段。
5.2 Agent 之间抢端口和资源:多个本地服务要提前规划
第二个坑是端口冲突。有些工具需要 Agent 在本地起一个小服务,比如本地搜索索引、回调服务器。两个 Agent 如果工具类似,都去尝试监听同一个默认端口,第二个启动时就会失败。日志里往往只显示“bind error”或者“port already in use”,如果你没意识到是多 Agent 资源竞争,会以为是主进程坏了。
我的排查路径是:先看启动日志里是哪个 Agent 报错,再看报错的服务名,最后用lsof -i :端口号或者netstat -tunlp查当前占用进程。确认是前一个 Agent 的实例还占着端口,就在配置里给每个 Agent 的工具分配独立的端口范围。这一步应该在规划多 Agent 时就做,不要等到冲突了再补救。我可以做一个端口分配表,每个 Agent 占一段,比如 main 用 18080-18089,code-reviewer 用 18180-18189,data-reporter 用 18280-18289,一目了然。
资源竞争还不止端口。模型 API 的调用额度也是公共资源,如果几个 Agent 同时高频调用,可能触发限流。这种限流往往表现为随机性的超时,很让人迷惑。我试过给不同 Agent 设置不同的请求优先级和并发上限,把不重要的 Agent 限制在每 10 秒 1 次请求以内,核心 Agent 不限制,系统稳定性明显好多了。
5.3 日志混成一团:用 ID 和结构化日志救命
第三个坑是日志问题。多个 Agent 跑在一个主进程里,如果日志没有按 Agent 区分,你看到的是一大锅混煮的流水账。某一行是哪个 Agent 打的?哪一段属于哪个请求?很难分清楚。排查问题时“无法定位来源”是最折磨人的。
解决办法有几个层级。最基础的是看日志行的前缀标记,OpenClaw 一般会在结构化日志里带上 Agent ID 字段,比如[code-reviewer]、[main-assistant]。如果你用的版本没带,就得自己在工具调用的日志里手动打标记。第二个办法是日志按 Agent 拆文件,配置一个日志目录结构,每个 Agent 一份独立日志文件,排查时直接去对应文件里看,效率高很多。第三个办法是给每个 Agent 发出去的请求加一个 trace_id,也就是链路追踪标识,这样从头到尾能追踪一次完整的处理过程,不管日志怎么混都能筛出来。
我自己现在维护的 OpenClaw 多 Agent 环境,日志配置基本是“全局入口 + 按 Agent 分文件 + trace_id 贯穿”。刚开始切换时会觉得多一层麻烦,但遇到两次线上问题需要快速定位时,你就知道这种投资太值了。
6. 多 Agent 不是越多越好:开销评估与收敛时机
6.1 资源占用评估与性能模型
说了这么多多 Agent 的好处,也泼点冷水:它是有代价的。每增加一个 Agent,不只是一个配置文件的事儿,它会带来真实的资源开销,包括内存里的上下文缓存、工具连接池的 keep-alive 占用、事件总线的消息处理循环调度、记忆服务的存储索引。
我大致估算过,在中等负载下,每增加一个 Agent,主进程的内存占用会增加几百兆左右,具体取决于工具数量和上下文长度。而模型 API 的费用则完全取决于调用频率。如果一个 Agent 几乎不被调用,那它的主要开销就是内存和常驻连接,费用可以忽略;如果一个 Agent 高频调用,那预算上要单独给它画一条线。
有几个优化手段值得一试。第一,给不常用的 Agent 开启按需唤醒,有消息才加载完整上下文,空闲时保持轻量状态。第二,模型通道做分级,重要 Agent 绑强模型,次要 Agent 绑弱模型,成本立刻降下来。第三,定期清理记忆空间,防止向量索引无限增长拖慢检索速度。
6.2 出现这些信号时,该收敛 Agent 数量了
拆 Agent 也要有个度。我见过有人一口气开了七八个 Agent,结果维护成本比收益还大。当出现以下信号时,说明数量过多或者划分不合理了。
信号一:Agent 职责重叠。两个 Agent 都能处理同一类请求,用户消息被随机路由到其中一个,回复质量忽高忽低。这说明边界设计有问题,要么合并,要么明确唯一入口。
信号二:协作链路过长。一个请求要经过四五个 Agent 的轮转才能完成,任意一环出错都会导致整个链路失败。链路越长,错误概率越高。我习惯的三级以内能解决问题就不拆成四级。
信号三:配置改一处要同步好多处。如果你发现加一个工具要在三个 Agent 的配置文件里各加一遍,说明你是在“复制粘贴式维护”,体验非常痛苦。这时应该考虑把公共逻辑抽成共享配置片段,或者减少同类 Agent 数量。
信号四:问题定位变慢。多 Agent 环境下,一次请求可能涉及事件订阅、消息路由、记忆共享、多工具调用,排查成本成倍增长。当排查时间占到你维护时间的大头时,就该回头审视是不是拆得太碎了。
我自己在实践里总结出一个起步建议:先跑两个 Agent,一个负责对外交互和任务编排,一个负责具体领域的专业处理,这样协作模式能跑通,开销又可控。等业务量真的上来了,再按上面说的信号逐步拆分。这比一上来就野心勃勃地铺七八个 Agent 要稳得多。
最后分享一个我踩过几次坑之后养成的习惯:在每个 Agent 的 role 指令里加一句显眼的自我介绍,让它每次会话开场先报自己的 ID 和职责范围。这一招看着简单,实际效果惊人,不管是用在日志定位还是对话调试上,都能让你一眼看出当前在处理请求的究竟是哪个 Agent。多 Agent 架构本身就是一套治理体系,运行机制是一部分,命名规范和边界意识是同样重要的另一部分,希望这篇经验能让你少走几段弯路。