资讯动态

OpenClaw框架拆解:Agent工程化五大模块实战指南

发布时间:2026/10/21 12:14:02 来源:尧图企业网站定制
在 Agent 这个方向折腾了几年我最大的感受是跑通一个 Demo 很容易但让它稳定地服务真实用户很难。OpenClaw 是我最近完整拆过的一个工程化框架它把一个 Agent 系统拆成了 Gateway、Memory、Skills、多 Agent 协作和 Runtime 五个模块。这个拆法并不新鲜但真正把它跑起来之后你会发现在每个模块里都有大量“文档不会告诉你”的细节。这篇我准备把五个模块逐一拆开重点讲它们各自解决的问题、为什么这么设计以及我在实际操作中验证过的参数和步骤。适合正在做 Agent 中台、或者从单 Agent 往多 Agent 演进、再或者被“上下文爆炸、工具乱调、经常超时”折磨的人参考。1. 整体架构设计思路1.1 五个模块的边界先给一下整体画面。Gateway 是唯一的入口负责把外部请求收进来做鉴权、限流、路由也把内部响应送回给外部。Memory 是所有记忆能力的总称记的是跨会话的偏好、事实和知识。Skills 是 Agent 可以调用的外部能力小到查天气大到执行一段数据分析脚本都算。多 Agent 协作解决的是“一件事需要多个角色配合”的问题。Runtime 则是这些模块运行的基础设施负责调度、执行、容错和观测。这个分层最直接的好处是每个模块都能独立替换。今天用某家的模型服务明天换另一家只要 Gateway 后面加一个适配层就行今天记忆用向量库明天想换成关系型存储Memory 对外暴露的接口不变Agent 的代码一行都不用动。这种可替换性在生产环境中比什么都重要。1.2 一次请求的完整旅程把一次真实请求从头跟到尾你就能理解这几个模块是怎么配合的。用户的消息先到 GatewayGateway 做身份校验、检查限流然后根据路由规则找到合适的模型入口再把它转成统一格式发给 Runtime。Runtime 收到后从常驻的 Agent 实例池里挑一个或者现场拉起一个把消息交进去。Agent 开始工作循环先把当前输入发给模型模型可能决定要调某个 SkillAgent 就去技能注册中心拿技能描述执行技能把结果喂回给模型中间需要查历史就走 Memory 的检索接口需要别人配合就通过协作消息发给其他 Agent。最后模型给出最终答案再沿原路经过 Gateway 返回给用户。这整个过程始终有一个贯穿全局的 trace_id后面讲可观测性时还会再提。1.3 为什么这么拆说实话OpenClaw 的架构里没有太多原创设计所有的核心都是“不让故障和变化蔓延”。Agent 代码里如果直接持有模型 SDK模型服务商一旦改协议所有 Agent 都要跟着改如果记忆系统直接嵌在 Agent 里会话一多缓存就会爆炸。把共性能力下沉到模块层把业务差异留在 Agent 层是我见过最适合生产环境的组织方式。我自己踩过的最大一个坑就是把模型调用直接写在 Agent 逻辑里结果某家服务商调整了超时策略导致系统整体雪崩。所以看到 OpenClaw 这种把所有对外依赖都收敛到 Gateway 的做法我立刻明白这条路是对的。2. Gateway所有请求的第一道闸门2.1 Gateway 要解决的四个问题Gateway 在 OpenClaw 里不是一个“可选组件”而是整个系统最不能挂的一层。它主要干四件事鉴权、限流、路由、协议转换。鉴权解决的是“谁在调用”。内部系统我建议用短时 token 加双向 TLS 的组合外部系统用 API Key 就够。限流解决的是“调用多快”避免上游模型服务配额被打爆。路由解决的是“找谁处理”这一层决定了请求进到哪个模型、哪个 Agent 组。协议转换解决的是“格式不同怎么办”因为不同模型服务商的请求和返回格式差异很大统一转成一种内部格式下游都对接这一种将来模型随便换。2.2 路由表与动态切换路由这块我见过很多团队一开始没做后面才开始补。OpenClaw 里路由表最简单的形态是一份 JSON 配置按会话维度指定模型。比如普通闲聊走轻量模型复杂推理任务走重量模型工具调用强的任务走函数调用支持最好的模型。这个路由不一定要静态可以做成规则引擎比如根据输入长度、预估复杂度、用户等级来动态决定。实测下来路由表放在配置文件里已经够用不太建议一开始就上配置中心。真正需要动态切换的是模型服务商出故障时的降级路由。我自己的做法是维护一份健康状态表Gateway 定期对每个上游做一次轻量探测连续失败到一定次数就把流量切到备用的模型入口恢复后再切回来。整个过程对用户完全透明。2.3 限流、鉴权与重试参数限流推荐令牌桶。参数怎么给拿模型服务商的配额反推假设它的配额是每分钟 3000 次你的业务又有 30% 的峰值波动那 Gateway 层每秒请求数上限设 50 左右比较稳burst 建议为每秒请求数的 1.5 倍因为真实流量的到达是突发性的完全没有 burst 会误伤正常用户的短时高峰。重试要注意两个点第一只对幂等请求重试非幂等请求的重试可能会把重复操作这种事故放大第二重试必须带退避不然上游一抖动所有请求同时重试就形成重试风暴。推荐退避序列100 毫秒、500 毫秒、2000 毫秒最多重试 2 次超过就进入熔断状态连主路径都别等了直接降级返回。注意限流参数不是越大越好。设得太接近上游配额上限一旦业务出现瞬时高峰限流会直接变成上游熔断的前置放大器用户感受到的就不是变慢而是直接失败。2.4 流式响应的转发细节现在主流模型都支持流式输出SSE 转发是 Gateway 里最容易被低估的一环。实现转发其实不难难的是处理各种异常模型端长时间没有新 token 产出客户端已经断开网关反向代理的缓冲超时……这些都会让用户体验卡住。我的经验是Gateway 必须自己维护一条到模型端的连接而不是简单透传这样才有机会插入心跳、超时和重连逻辑。具体参数上模型端空闲超过 30 秒没有产出Gateway 就主动断开并重试一次客户端断开时要立刻向上游发送停止信号否则模型端还在继续生成白白浪费计费。这个小细节不实际调过真的想不到。3. Memory让 Agent 记住该记的事3.1 三级记忆架构Agent 没有记忆就是“每次对话都失忆”。OpenClaw 的记忆分三级工作记忆、短期记忆、长期记忆。工作记忆就是当前会话的上下文存在会话缓存里用高速缓存这类存储短期记忆是最近几轮交互的摘要保留窗口通常是 20 到 50 轮再老的就滚出窗口长期记忆是跨会话沉淀的用户偏好、事实性知识存在向量库里。分级的核心原因是成本全放向量库检索慢且贵全放上下文上下文一旦超限就什么都记不住。分级才能让“高频用的放近处低频用的放远处”。3.2 向量化与检索参数长期记忆的核心是向量检索。这里有两个参数直接决定体验top-k 和 score 阈值。top-k 建议取 5 到 10太小会漏掉信息太大就是给 Agent 塞垃圾。score 阈值建议 0.65 到 0.75具体情况看向量模型的分布有些模型的相似度普遍偏高就调高阈值有些普遍偏低就调低。切块大小推荐 256 到 512 token切块重叠 10% 到 15%。为什么要有重叠因为一句话的概念可能横跨两块如果硬切成互不相干的两块信息就丢了。重叠尺寸不要超过 20%否则检索结果里会大量出现重复内容浪费 Agent 的上下文窗口。3.3 写入、提炼与遗忘的数据流记忆的写入必须异步。交互完成后Agent 把消息丢进一个待处理队列就返回后台进程再做提炼和入库。为什么非要异步因为一次模型调用的返回时间已经够长了如果再让 Agent 等记忆写完再回复用户会明显感觉到更慢而且记忆提炼本身也是模型调用完全没必要阻塞主链路。提炼这一步建议用一个轻量模型抽取结构化事实比如“用户是谁、做了什么、表达了什么偏好、否定过什么结论”。抽取结果用 JSON 结构存和原始对话分开。遗忘策略我倾向使用 LRU 加时间衰减太久没被命中的记忆权重指数下降直到查询时被过滤掉。这样既能控制存储膨胀又不会永久保留过时信息。3.4 记忆污染治理记忆系统最怕的不是存不下来而是存了错误的东西。如果一条错误记忆被检索出来喂回给模型模型就会一本正经地胡说八道而且你说不清问题出在哪。我的经验是两件事必须做一是写入前校验提炼出来的事实必须带时间戳和置信度置信度低于阈值的就不入库二是冲突处理同一个实体出现矛盾事实时以时间戳新和置信度高的为准旧的一条降级标记。另外记忆检索的整个链路建议都打 trace。记忆被检索出来又被最终答案引用中间每一环都要可追溯。否则你会遇到那种“模型突然说用户是另一个公司的”的诡异情况查半天才发现是几个月前一次对话沉淀了一条错误记忆一直在污染后续检索。4. Skills把能力做成功能调用4.1 技能描述决定调用成功率Skills 的本质是把“能力”包装成一个模型能看懂并主动选择的函数。模型在推理过程中看技能清单判断当前任务该调用哪个。所以技能描述写得好不好直接决定调用成功率。我见过太多失败的技能描述要么太长要么太含糊。正确写法应该是name 用动宾短语比如 get_user_orderdescription 说三件事——什么时候用、做了什么、有什么副作用。比如“当用户询问订单状态或物流信息时使用会根据订单编号查询最新状态注意该操作会触发一次第三方接口调用费用较高非必要时不要使用”。parameters 用 JSON Schema 严格约束字段类型、必填、枚举都要写清楚。千万别省略枚举省略了模型就会自由发挥然后你的技能执行层报一堆类型错误。4.2 技能注册全流程OpenClaw 里技能注册流程大致是先按协议写好技能定义包括 name、description、parameters、执行入口、超时声明、幂等声明然后把定义注册到技能仓库技能仓库会统一生成一份“模型可以理解的函数清单”在每次推理时注入给模型最后执行入口注册到运行时标注好资源限制。有一个实操细节技能注册后最好有一个“上线前试运行”的环境。因为技能描述改动对模型选择行为的影响很大有时候只是改了一个词模型选择的准确率就掉了一大截。没有试运行生产环境上线后就只能靠用户投诉来发现问题。4.3 沙箱执行、超时与错误处理技能执行一定要在沙箱里跑原因很简单你永远不知道第三方技能会干什么也永远不知道模型会不会因为描述误导而调用一个本不该调用的技能。沙箱要限制资源和网络访问超出限制就强制终止。执行超时默认给 10 秒特殊情况可以声明更长的时限但必须有上限。技能返回的错误也必须是统一格式。我建议至少包含 code、message、recoverable 三个字段。recoverable 表示这个错误是否值得模型再试一次。比如“上游接口限流”是可恢复的模型换个策略再调一次“参数校验失败”通常不可恢复应该让模型重新理解输入。这个字段的设计能省掉非常多的无效重试。4.4 从单技能到技能编排单技能能解决单点问题真实场景往往需要多个技能配合。比如“帮用户查最近订单并退款”先要查订单再要发起退款两个技能有先后依赖。OpenClaw 的技能编排支持顺序、并行、条件分支。顺序编排最简单前一个技能的输出做后一个技能的输入。并行编排要小心共享状态两个技能同时写一个文件就会出问题。条件分支我建议让模型来做判断而不是在编排层写死因为模型的判断能力已经足够强写死逻辑反而降低了灵活性。编排层的重点是管好依赖和错误传播不要让一个子技能挂掉连累整个链路。5. 多 Agent 协作从单兵到团队作战5.1 多 Agent 不是银弹先说结论不是所有场景都需要多 Agent。我自己见过很多团队单 Agent 的方案还没跑稳就急着上多 Agent结果任务分解乱、消息满天飞、性能直线下降。多 Agent 的适用场景有一个共性任务可以被清晰地拆成多个职责不同、可以并行或分阶段执行的子任务。如果拆不出来强行拆只会制造混乱。5.2 四种协作模式怎么选Pipeline 管道模式适合数据加工链上游产出直接喂给下游逻辑简单Hierarchical 层级模式适合有一个主导者拆任务、收结果、做仲裁的场景Swarm 群组模式适合需要广泛收集信息、然后统一汇总的场景每个 Agent 都能说话但都不决策Blackboard 黑板模式适合复杂问题探索多个 Agent 在共享空间里写结论、引用别人的中间结果。实测下来绝大多数业务场景用 Pipeline 或 Hierarchical 就够了Swarm 和 Blackboard 很灵活但非常难控制。5.3 任务分解与结果汇聚在层级模式下主管 Agent 的任务是把大目标拆成子任务。拆得好不好直接决定整体的成败。子任务描述必须包含背景信息、约束条件、验收标准缺一样都会有麻烦。背景信息不够执行 Agent 就会猜约束条件不写清执行 Agent 就会用你不想用的方式干验收标准没有主管自己也不知道结果合不合格。结果汇聚这一步要求每个执行 Agent 返回结构化结果而不是一坨自然语言。我习惯的格式是任务编号、状态、输出、置信度、证据引用。置信度是模型对自己结论的把握证据是支撑结论的引用来源。有了这两个字段主管 Agent 仲裁时就能区分“这个结论是对的但不太确定”和“这个结论是编的”。5.4 防止幻觉在 Agent 之间传染多 Agent 系统最隐蔽的坑是“幻觉传染”Agent A 产生了一个错误的中间结论Agent B 把它当事实引用又基于它继续推理错误就像滚雪球一样被放大。要抑制这个现象核心手段就是上一条说的置信度和证据。下游 Agent 在引用上游结论时必须自带置信度标注。主管在汇总时对低置信度的结论要提高留意级别必要时再要求原 Agent 复核。注意协作消息里不要只传“结论”必须传“结论加依据”。只传结论的协作本质上是在鼓励幻觉传播。6. Runtime一切执行的底座6.1 调度与执行引擎Runtime 承担 Agent 实例的调度和执行。OpenClaw 的设计里Agent 实例不是用户请求一到就现场创建一个那样太慢。它会维护一个常驻实例池请求进来时从池子里取空闲实例用完再还回去。每个实例内部有一个事件循环收请求、调模型、执行技能、查记忆、发协作消息所有操作都在这一个循环里排队。最容易犯的错误是在事件循环里做阻塞操作比如同步等一个外部接口返回。这一阻塞整个实例就卡住了等它醒过来用户的请求已经超时。正确做法是阻塞操作异步化事件循环只负责调度真正等待结果的是异步回调。6.2 Agent 生命周期管理无状态 Agent 是最理想的情况用完即回收不占资源。但现实里很多场景有状态比如用户在做一个多步的审批流程中间状态必须存下来否则断一下上下文就全丢了。这种有状态 Agent 我建议把状态快照定期存到外部存储状态包含记忆缓存和局部数据Agent 崩溃后可以直接从快照恢复。序列化格式用 JSON 就够别整复杂方案性能和可维护性都要考虑。实例回收要防止内存泄漏。技能沙箱跑完不能想当然地认为它就自己清理了临时文件、网络连接、大对象引用都需要显式释放。我在线上见过持续跑了一周的实例内存一路飙到接近上限最后才发现是一个技能每次执行都会往全局容器里塞数据。6.3 容错策略Runtime 的容错分三层。模型调用层调用超时就重试一次再失败就降级到备用轻量模型保证主流程不断。技能层技能超时就中断执行把错误信息返回给模型让模型自己决定换一种方式而不是直接报错给用户。实例层实例崩溃就重启然后从最近一次状态快照恢复重放未完成的消息。这三层分别处理了“模型坏了、工具坏了、进程坏了”三种情况。有一个细节很多人忽略熔断要和降级联动。Gateway 限流触发了Runtime 这边不能还在用最高优先级去抢任务应该自动降低请求的优先级否则有限的资源会被高优先级请求打满低优先级的一直饿死整体表面看起来还没事实际已经半瘫了。6.4 可观测性建设没有可观测性的 Agent 系统就是一个黑盒出了事只能靠猜。我强烈建议从第一天就把 trace_id 整条链路打通用户在 Gateway 进来时生成一个 trace_id流经 Runtime、Agent、Skills、Memory 时全部在日志里带上它。这样任何一次异常的请求都能通过 trace_id 把整条调用链拉出来快速定位到具体环节。指标方面至少要看四个数P95 延迟、错误率、技能调用成功率、记忆检索命中率。其中记忆检索命中率极能反映记忆质量——如果这个数很低说明 Agent 虽然检索了一堆东西但真正被模型采用的不多很可能是 top-k 或者 score 阈值没调好。7. 常见问题排查与调优实录7.1 高频故障速查表症状排查方向常见解法所有请求超时Gateway 到模型服务商的连接池、限流是否触发调大连接池、增加重试退避、配置备用路由Agent 答非所问Memory 检出了大量无关内容调高 score 阈值、收紧 top-k总调用错技能技能描述模糊、参数 schema 不严谨重写 description、补全枚举多 Agent 任务停滞协作消息没被消费、状态机卡死查消息队列积压、补超时重投内存持续上涨技能沙箱未回收、有状态实例泄漏检查临时资源释放、加内存上限流式回复卡住SSE 心跳和空闲断开逻辑缺失补心跳、补客户端断开信号7.2 调优顺序如果系统已经跑起来了但体验不好我建议按这个顺序调优网关层先调限流和路由成本最低收益最直接然后是 Memory 的检索参数调完通常能明显感受到“Agent 变聪明了”再然后是技能描述此时的提升是让 Agent 更少犯错最后才是换更大的模型。顺序反了容易做无用功比如你换了个大模型但记忆里全是噪声再大的模型喂进去也是垃圾进垃圾出。7.3 一套可复现的压测方法压测时不要只盯着吞吐量要看 P95 延迟、错误率和上下文命中率一起。抓一小段线上脱敏流量按 1 倍、2 倍、5 倍三种压力跑。如果 2 倍流量下 P95 延迟已经恶化到 3 倍以上大概率是队列堆积去检查 Runtime 的消费者数量如果错误率飙升但延迟还正常大概率是模型服务商的配额被打爆去调 Gateway 限流值。我用过一个非常朴素但极其好用的压测脚本一个 Python 脚本并发发请求记录每个请求的耗时结束后算 P95。脚本本身不复杂难的是用脱敏的真实流量而不是自己编造的样例。因为真实流量里的上下文长度、工具调用频率和故障模式都是编不出来的。把这五个模块拆完我最大的体会是Agent 系统能不能稳定看的不是某个模块多强而是模块之间能不能把职责分清楚。Gateway 管出入口Memory 管记性Skills 管手脚协作管分工Runtime 管呼吸任何一层越权和失守整条链路都会出事。最后分享一个我自己的习惯调试任何 Agent 问题时先问一句“这个现象发生在哪一层”。发生在 Gateway 就去查限流和路由发生在 Memory 就去查检索质量和污染发生在 Skills 就去查描述和沙箱发生在协作就去查消息和状态机发生在 Runtime 就去查队列和容错。问题分层定位十次有八次能很快锁定方向剩下的两次基本都是跨层问题这时候 trace_id 就是你唯一的救命稻草。

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

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

免费获取报价 →
↑