今年干了一件让自己挺意外的事:在继续维护原来 AI 助手的同时,我用团队内部代号为 OpenClaw 的框架,一口气把业务切成 11 个专业 Agent,从售后处理、内容审核到数据复盘,全部立了独立的“岗位”。这篇文章就是来复盘我是怎么设计这些 Agent 的,重点是我沉淀下来的设计模式,以及上线后一个个血坑。如果你正在规划多智能体系统,或者觉得“一个 AI 助手什么都能干,但什么都干不好”,那这篇应该能给你省下不少试错时间。
我不打算讲太多建模理论,OpenClaw 也不是什么公开框架,它是我在项目里对“可控 Agent 运行时”的一套内部抽象。但设计模式是通用的:工具路由、状态机、验收集、权限隔离、成本控制,换任何框架都能直接用。
1. 为什么是 11 个?先把需求盘点清楚
1.1 需求本质上是四类,不是四十类
我开始没有拍脑袋定数量,而是先把过去一年的用户请求和机器人对话日志捞出来分了个类。分类完发现,真实需求再五花八门,也逃不出四类:高频信息查询、内容生产、判断决策、跨系统操作。
高频信息查询,比如“我的订单到哪了”“额度还剩多少”,本质是查数据库然后翻译成人类语言。这类需求占了大头,适合做高并发、低延迟的轻量 Agent。
内容生产,比如周报初稿、活动文案、会议纪要,不是查一下就完,而是要理解上下文、生成结构化内容。这类需求对模型质量最敏感,必须单独拆,不然会被其他任务干扰。
判断决策,比如“这个用户投诉该不该升级处理”“这篇文章能不能过审”,本质是一个带评分标准的分类问题。这类 Agent 不能只输出结论,还要给出可追溯的判断链路。
跨系统操作,比如“帮我发起退款流程”“帮我建一个工单”,涉及写操作。这类 Agent 的安全要求最高,必须加人工确认和二次授权。
把四类需求铺到对应的业务线上,自然就形成了 11 个 Agent 的雏形。
1.2 矩阵规划:一个萝卜一个坑
我按“业务线 + 能力类型”双维度做了矩阵,11 个 Agent 的布局大概是这样:
| 序号 | 定位 | 核心能力 | 典型工具 | 记忆策略 |
|---|---|---|---|---|
| A1 | 订单查询助手 | 信息检索+口径解释 | 订单中心查询接口 | 短期+向量记忆 |
| A2 | 售后处理 Agent | 判断问题归属、生成处理方案 | 售后工单系统、退款预检 | 短中期记忆 |
| A3 | 物流补偿 Agent | 结合物流轨迹做赔付预估 | 物流轨迹接口、补偿规则库 | 中期记忆 |
| A4 | 内容审核 Agent | 多维度规则审核、风险标记 | 审核规则引擎、敏感词库 | 长期记忆 |
| A5 | 周报生成 Agent | 从项目数据生成结构化周报 | 项目管理接口、模板库 | 长周期记忆 |
| A6 | 会议纪要 Agent | 长文本摘要+待办抽取 | 转写文件存储、待办系统 | 短期记忆 |
| A7 | 数据复盘 Agent | 按维度和指标做归因分析 | 指标库、数据仓库查询 | 长期记忆 |
| A8 | 客服话术助手 | 提供合规话术并标注依据 | 知识库、用户标签接口 | 长期记忆 |
| A9 | 工单分类 Agent | 自动分类、定优先级 | 工单系统、服务目录 | 短期记忆 |
| A10 | 营销文案 Agent | 生成文案并做多版本对比 | 文案模板库、活动配置表 | 短期记忆 |
| A11 | 风险识别 Agent | 跨场景风险判断、事件上报 | 规则引擎、风控事件接口 | 长期记忆 |
这张表的重点是数量控制。很多人一上来就按部门做 Agent,一个部门一个,最后做出 50 个没人维护的面条。我的经验是先按“能否独立验收”来判断:一个 Agent 有没有自己的工具集、自己的状态边界、自己的验收标准。能独立验收,才给它立岗。
2. OpenClaw 的骨架:Agent 元模型与配置抽象
2.1 四层抽象,把每个 Agent 变成标准件
OpenClaw 的核心抽象,是把一个 Agent 拆成四层:模型接入层、工具层、状态层、策略层。
模型接入层不管业务,管的是路由:什么场景用什么模型,成本贵的模型只给核心判断用,普通查询走轻量模型。这一层必须做成网关,而不是让每个 Agent 自己配模型地址,否则后面 11 个 Agent 模型一变,改到崩溃。
工具层是 Agent 唯一的“手”,所有外部能力都封装成工具函数。工具必须有 Schema 声明,包括参数格式、调用权限、风险等级,不声明的一律不暴露给 Agent。
状态层管的是会话和记忆。每个 Agent 都有 session、短期缓冲、长期向量库,但不同 Agent 的状态 TTL 完全不同。比如天气查询类会话半小时就过期,售后工单类要保留整个处理闭环。
策略层放“规矩”,包括意图校验、工具调用次数上限、超时时间、脱敏规则、人工确认开关。这是 OpenClaw 最值钱的一层,因为大模型天然不可控,可控性全靠策略层兜底。
2.2 配置化:一个 Agent 一份 YAML
最开始写 Agent 的时候,我也习惯把逻辑全部写在 Python 代码里,结果一个 Agent 的代码调优,另一个 Agent 跟着出问题。后来改成配置驱动的思路:每个 Agent 一份 YAML,运行时统一加载。这是我在 OpenClaw 里做的第一个重构,收益非常直观。
一个典型的配置长这样:
agent_id: after_sale_agent display_name: 售后处理智能体 model: provider: internal-gateway model_name: llm-32k temperature: 0.2 memory: short_window: 20 summary_enabled: true long_term: vector_store tools: - name: query_order api: order.center.query risk: read - name: issue_refund api: finance.center.refund risk: write need_confirm: true policy: intent_gate: true max_tool_calls: 5 timeout: 30s refuse_template: "default_refuse"配置文件的意义不只是“不用改代码”,而是把 Agent 变成了可以被评审、被测试、被版本管理的对象。团队里任何人要做新 Agent,拿一个模板改两行就能跑通 Demo,效率完全不一样。
2.3 工具协议:所有接口统一按钮
工具层最容易踩的坑是接口风格不统一:有人写 Python 函数,有人写 HTTP 接口,还有人直接让模型读数据库。OpenClaw 的做法是把工具全部收编成统一协议,底层不管是什么,对外都是 ToolSpec。
@tool_spec( name="query_order", description="根据订单号查询订单状态", parameters={ "order_id": {"type": "string", "required": True, "rule": r"^\w{8,32}$"}, "user_id": {"type": "string", "required": False}, }, scopes=["after_sale", "logistics"], risk="read", ) def query_order(order_id: str, user_id: str = "") -> dict: ...统一协议带来的好处是 Agent 不用关心工具内部实现,只要能拿到标准参数。更重要的是,权限控制可以集中做:同样一个query_order工具,售后 Agent 能用,营销文案 Agent 就不能用。
3. 三个基础设计模式:工具路由、状态机、记忆分层
3.1 工具路由模式:别让模型自己拍板调函数
说到工具调用,很多人第一反应是把所有工具函数直接给模型,让模型自己选择。这个思路在大模型演示里看着很爽,到生产环境就是灾难。
原因很简单:模型对工具的理解是概率性的,不是确定性的,尤其是工具多到一定程度以后,模型选错工具、传错参数的概率会明显上升。OpenClaw 在这个问题上引入了意图网关:模型的工具调用请求必须先经过意图网关校验,校验通过才真的执行工具。
做法是这样:先把用户原始输入做意图识别和实体抽取,把“用户到底想干什么”和“用户提到了哪些关键参数”算出来,然后再看模型请求的工具是否和意图匹配。
def intent_gate(user_input, model_tool_call): intent = classify_intent(user_input) # 比如 refund_request entity = extract_entities(user_input) # 比如 order_id: 20240101... allowed_tool = tool_policy[intent].allowed # 退款意图能用哪些工具 if model_tool_call.tool not in allowed_tool: return reject("工具与当前意图不匹配") if not validate_param(model_tool_call.args, entity): return reject("参数与用户输入不匹配") return allow(model_tool_call)这个模式看起来多了一次模型调用,但换来的是工具误调用的概率从“随缘”变成“可控”。我后续 11 个 Agent 上线后,事故里没有一个是因为工具调错被外部投诉的,靠的就是这一层兜底。
3.2 有限状态机模式:把长对话拆成可回滚的流程
长对话 Agent 最容易出的事故是什么?跑飞。用户上来问退款,模型聊到一半突然开始给用户讲公司历史,或者把售后流程和工单流程混在一起。这本质上是因为模型把整个对话当成一个“无限自由流”,没有阶段概念。
我的方案是给 Agent 画有限状态机,每个会话只允许在业务流程定义好的状态之间流转。以售后 Agent 为例:
| 当前状态 | 触发事件 | 下一状态 | 动作 |
|---|---|---|---|
| initial | 识别到订单查询意图 | order_confirmed | 调用查单工具、展示订单信息 |
| order_confirmed | 识别到退款意图且订单符合条件 | refund_review | 校验权限、进入退款预检 |
| refund_review | 预检通过 | completed | 调用退款工具、发送回执 |
| refund_review | 预检不通过或需要人工 | escalate_to_human | 生成转人工任务、保留上下文 |
| 任意状态 | 用户连续否定或超时 | closed | 清空短期缓存、写摘要 |
OpenClaw 在每个会话初始化时读取状态机定义,每次用户消息进来后先判断允许的转移路径,不允许的直接拦下。你别觉得这限制了大模型的能力,它限制的只是模型的随意性,业务上每个状态内部的自由表达还是完全保留的。
这套机制还有个额外好处:能回滚。用户说“抱歉我不想退款了”,状态可以直接从 refund_review 回到 order_confirmed,而不是让模型自己脑补怎么处理。
3.3 记忆分层模式:短期、中期、长期各管一摊
Agent 的记忆不能只有一个“聊天记录”变量,越到后面越会炸。OpenClaw 的记忆模块做了三层:
短期记忆存最近会话里最具体的信息,比如订单号、用户 ID、刚才用户表达的情绪。用 Redis List 加 TTL,通常一个会话最多保留 20 到 40 条,超过就把最早的踢掉。
中期记忆是结构化的会话摘要。每过 5 轮对话或每次状态机状态跳转时,让模型把前一段对话压缩成 200 字以内的摘要。这样长对话永远不会从第一条扯到第一百九十九条,模型看到的永远是最新摘要加最新几轮。
长期记忆存在向量库里,存的是用户画像、历史偏好、历史处理结论。注意:长期记忆不能自动写,必须经过策略层审核,只有明确的事实(比如“该用户已有三次退款记录”)才能入库,模型的主观推断一律不存。
用 OpenClaw 写记忆策略时,我会在 Agent 配置里分别指定三层记忆的读写权限。有些 Agent 只有长期读写,没有短期查询权限,反而从设计上就避免了“跨 Agent 偷看隐私”的嫌疑。
4. 多智能体协作:主管、专家组与共享记忆
4.1 主管-工人编排:让调度变得可预测
11 个 Agent 之间不可能完全不交流。以客服场景为例,一个客诉进来,先由客服话术助手判断问题类型,如果是物流问题,就派给物流补偿 Agent;如果涉及退款,就要把售后处理 Agent 拉进同一个工单上下文。
OpenClaw 里的协作我用的是主管-工人模式,而不是自由多 Agent 对话。自由对话看起来酷,但两个模型你来我往很容易聊到失控,且 token 消耗是线性增长的。
主管 Agent 的职责很单一:拆解任务、派给负责的工人 Agent、回收结果、向用户汇报。它不负责深度理解问题,也不需要调用任何行业工具,就是一个纯调度器。工人 Agent 只处理自己领域的问题,拿到任务后直接在自己工具集里解决,然后把结果固定成结构化字段返回。
这种模式的最大的优点是每个 Agent 的验收边界是稳定的。主管好不好,看它有没有派错人;工人好不好,看它在自己领域的任务上表现稳不稳。问题一出现,能立刻定位到谁身上。
4.2 专家组仲裁:能打分的多 Agent 才是好多 Agent
还有一些场景,单一 Agent 判断不够稳,需要让多个 Agent 背对背出具结论,再合成最终答案。我在内容审核和风险识别场景里做了专家组模式:
三个相同定位但独立初始化的 Agent,分别对同一段内容做判断,各自输出风险等级和依据。汇总层拿到三个结果后,不搞“少数服从多数”,而是做加权打分的规则仲裁:每个 Agent 的风险等级映射为分数,再叠加预估置信度,超过阈值才出最终结论,否则转人工。
仲裁逻辑要考虑覆盖分歧。三个 Agent 不会一模一样,它们很可能一个判高、一个判低、一个踩中线。OpenClaw 的仲裁层会把分歧最大的样本自动回流到标注集里,作为后续调整提示词和阈值的数据基础。这个过程我称之为“把模型分歧当成免费标注员”。
4.3 共享记忆中心:Agent 之间传话的通道
多 Agent 协作里最容易被忽略的是共享上下文。主管把任务派给工人之后,工人不能只看一句话,还需要知道前面的对话脉络、用户已经提供的信息、其他 Agent 已经得出的中间结论。
OpenClaw 的做法是引入共享记忆中心,以工单 ID 或者会话 ID 为粒度,把跨 Agent 的上下文写到一个统一的存储里。写入的 key 按命名空间隔离:
agent/{agent_id}/sessions/{session_id}/state agent/{agent_id}/sessions/{session_id}/summary agent/{agent_id}/tasks/{task_id}/result不同 Agent 可以读共享 session 里的基础上下文,但只有负责该流程的 Agent 才能写。写操作也必须走工具层,不能浏览器直连数据库。
这里有个教训:共享记忆不要做成一个大杂烩。Agent 之间传上下文,只能传经过结构化的结果字段,比如“订单已确认”“物流已延误”“用户同意升级处理”,不能传原始全文。原始全文意味着每个 Agent 都要重新处理一遍信息,既浪费 token,又容易造成上下文污染。
5. 从 0 到 1 搭出 11 个 Agent 的落地路径
5.1 先把基座跑通,再谈数量
我不建议一上来就铺开 11 个 Agent,我自己是分三步走完的。
第一阶段只搭一个全场景基座:一个主 Chat Agent,挂上会话管理、工具网关、基础权限、日志链路。这一个 Agent 不强求业务能力,只求“能聊、能翻车、能追责”。这一阶段的核心产出不是功能,而是观测体系,得能看清楚模型每一步调用了什么工具、每轮消耗了多少 token、用户在哪个状态流失了。
第二阶段才把基座按业务拆成专用 Agent。每个 Agent 不是简单换个系统提示词,而是重新配置工具集和状态机。我把一个售后 Agent 拆给物流补偿 Agent 时,给后者新增了两个物流轨迹工具,同时从工具列表里删掉了退款相关操作权限。这个“权限随拆分下沉”的动作是最容易出涟漪效应的,一定要用配置中心统一管起来。
第三阶段是给每个 Agent 建验收集。OpenClaw 支持在 Agent 配置里绑定一个测试集,里面是 50 到 200 条历史真实问题样本,每条标注了正确答案和期望的工具调用链。推荐每一版发布前都跑一遍,没跑过测试集的 Agent 不允许上线。
5.2 工具授权表:Agent 的能力边界一念之间
我还是建议把所有 Agent 的工具授权提前整理成一张表,不然到后面根本管不住。以下是我当时上线前的部分授权表:
| Agent | 可读工具 | 可写工具 | 需人工确认的操作 |
|---|---|---|---|
| 订单查询助手 | 订单中心、物流查询 | 无 | 无 |
| 售后处理 Agent | 订单中心、工单系统 | 工单创建/更新 | 退款 |
| 物流补偿 Agent | 物流轨迹、补偿规则库 | 补偿单创建 | 超过阈值补偿 |
| 内容审核 Agent | 审核规则、敏感词库 | 审核结果写库 | 高风险判定 |
| 风险识别 Agent | 规则引擎、用户标签 | 风险事件上报 | 高风险上报 |
这张表看着简单,排查问题的时候极其好使。某个 Agent 被投诉“越权查了不该查的数据”,直接按表查它有没有对应的读工具权限即可,不用翻代码。
5.3 灰度上线:老系统始终是安全垫
11 个 Agent 不可能一次性全部上生产。我采用的策略是影子模式:新 Agent 先在线上接收真实请求,但只做“预测”,结果不直接生效,而是落到一个比对库里,跟人工处理结果做对比。
比如内容审核 Agent 在影子模式里跑了一周,每天把它的审核结果和人工审核结果做一致性比对。一致率稳定到 95% 以上,才打开真实审核按钮。哪怕打开真实按钮之后,高风险内容仍强制转人工,绝不交给模型一锤定音。
“安全垫”这个词不是套话。我见过太多 Agent 项目把系统提示词写得天花乱坠,一上线就被真实世界的脏数据打爆;影子模式能让这些脏数据在可控范围内先被消化。
6. 上线后最痛的五件事
6.1 工具幻觉:模型编了一个不存在的参数值
第一个大坑来得很快。售后 Agent 在处理一个订单退款时,模型自己脑补了一个订单号,看起来格式和真实单号一模一样,但根本不存在。结果工具层拿来查订单,自然查不到,Agent 就不停重试,反复报错,还把错误原因模棱两可地丢给用户说“系统繁忙”。
排查链路是这样的:先在日志里定位到模型请求工具时的入参,发现订单号跟前端传来的订单号完全对不上。根源是大模型在生成工具调用参数时,会把用户消息里没出现过的信息“补全”。修复措施有两层:外层是意图网关加参数回填校验,要求工具参数必须来自实体抽取结果,而不是模型生成内容;内层是给每个 Agent 加一句规则——参数不确定时必须反问用户,不允许猜测。这两层叠下去,工具幻觉从偶发事故变成了极小概率事件。
6.2 上下文污染:多轮对话被无关内容挤爆
第二个坑是在会议纪要 Agent 上暴露的。这个 Agent 要处理的文字很长,用户还会中途插入几句“刚刚那段不是重点”之类的口语废话。大模型分不清哪些是内容、哪些是态度表达,全塞到上下文里,结果纪要越来越偏。
根因是模型把所有消息当成同等权重的输入。修复方案是 OpenClaw 的上下文清理层:对话进入上下文之前先经过一个修剪模块,把意图以外的闲聊、无关重复、纯语气词单独剥离,只把有效业务内容提供给大模型。同时在状态机里加了一个“内容修正事件”,让用户可以在任意轮次补充“以上XX不记录”,触达后立刻将该内容从短期缓存里标记为失效,不让它参与后续摘要。
6.3 死循环:Agent 反复调用工具不收敛
第三个坑也够吓人的。某天凌晨,工单分类 Agent 因为一个非常规格式的工单描述触发了一个 bug,一直在“调用分类工具→结果置信度过低→重新分类→再调用工具”之间打转,一个工单烧掉了平时二十多倍的 token,整整循环了四十多分钟。
后来一查,就是没配 max_tool_calls 的锅。很多框架默认允许模型无限调用工具,模型在“不确定”状态下会反复尝试。OpenClaw 的策略层后来强制加了三个默认值:单轮工具调用上限默认 5 次;工具结果置信度低于 0.4 不再重试,直接转人工;连续两次调用相同工具且参数相同,直接终止并提问。这套组合拳下来,死循环基本绝迹。
还有一个经验:不要相信模型“会主动承认自己卡住了”。模型永远会把当前动作描述成理性决策,哪怕它已经在循环。所以停止条件不要靠模型自觉,要靠策略层硬性拦截。
6.4 权限越界:上层模型“借用”了不该用的工具
第四个坑比较隐蔽,问题出在共享工具仓库。我们有个 Agent 能导出最近一周的用户访问日志,本来只有风险识别 Agent 能用。结果某次主管 Agent 在处理用户投诉时,为了“全面了解情况”,居然调用了这个日志导出工具,把一堆敏感字段拉了出来,还展示给了终端用户画面。
这就是工具层权限没做隔离导致的。OpenClaw 工具协议里的 scopes 字段解决不了动态权限问题,因为主管 Agent 在运行时确实能接触到风险识别 Agent 的工具列表。后来我把所有 Agent 的工具列表做了运行时过滤,每个 Agent 只能看到自己 scopes 内的工具,物理隔离掉“借用工具”的可能。这一个改动涉及的代码量不大,但安全性提升是质变的。
6.5 token 成本失控:11 个 Agent 同时跑起来,账单先崩
最后一个坑不报错,但比报错更让人肉疼,是成本。11 个 Agent 都在生产环境跑之后,每天 token 消耗一度是预估值的 3.2 倍。
复盘发现三个地方烧钱:第一,所有 Agent 都用的旗舰模型,哪怕“查订单状态”这种一眼出结果的活儿也走大模型;第二,多智能体协作场景里,主管 Agent 把完整工单全文发给工人 Agent,一个工人 120 元 token 的调用,七个工人就是 840 元,信息还大量重复;第三,上下文窗口设得过大,每轮对话都把全部历史塞进去重新计算。
这三个问题的解法分别是:小任务路由到轻量模型,只有关键判断才走旗舰模型;工人 Agent 之间只传结构化抽取字段,不传原始全文;上下文窗口按状态机阶段动态收缩,退出某个状态后,该状态细节立刻被摘要替代不再参与 next token 计算。调整之后,日成本基本回到预估线附近。
7. 现在回头看:哪些模式留下,哪些其实是过度设计
7.1 真正留下来的是“业务边界 + 策略兜底”
现在回看这 11 个 Agent 的设计,真正让我有信心的是两件事:业务边界和策略兜底。
业务边界指的是每个 Agent 必须有清晰的角色定位,可以使用“这个 Agent 服务谁、解决什么、不解决什么”一句话讲清楚。边界模糊的 Agent,后续无论你怎么优化提示词,稳定性都很难起来。策略兜底则承担了所有不确定性兜底:意图网关、工具调用上限、权限过滤、人工确认,这些机制压住了模型失控带来的大部分风险。
专业 Agent 设计的核心,不在于你用了多强的模型,也不在于你接了多少个工具,而在于你是否愿意从代码逻辑层面去约束一个大模型。约束力越强,Agent 才越能稳定创造价值。
7.2 被我亲手删掉的设计:全面自由对话
我最早构想的协作方案是两个 Agent 之间自由对话,任意 Agent 都能向任意 Agent 发起请求,整个系统看起来像一个有机体。但这个设计在测试阶段就被我自己毙了。自由对话意味着协同路径不可枚举,一旦路径不可枚举,你就没法做评测,出故障也没法固定证据链。
后来换成了固定工作流 + 有限跳数:主管负责派发,工人负责执行,需要跨域协作时只能通过主管中转,且总链路跳数不超过 3。这个设计的直接观感是没那么“酷”了,但换来的是可观测、可测试、可回滚,这些才是商用的底线。
7.3 最后分享一个最实用的微设计:统一拒绝模板
如果你从这篇里只带走一个小技巧,我建议是给每个 Agent 配一个“拒绝模板”。模板不是简单的“我不能帮你”,而是包含三层:拒绝原因、替代路径、升级入口。用 OpenClaw 的话说,每个 Agent 的配置里留一个 refuse_template 字段。
比如售后 Agent 无法处理金额超过阈值的退款时,输出逻辑是:“这笔退款金额超过我的处理权限,已经为你生成人工工单 W12345,客服会在一个工作日内联系你,目前进度可以随时查询。”同样的模型,有这条模板和没有这条模板,用户体验是两个完全不同的档位。读者你自己接 Agent 的时候,千万别忘了这个最小的兜底。