乐于分享
好东西不私藏

OpenClaw 专题第五期 Prompt、Agent 与工具调用

OpenClaw 专题第五期 Prompt、Agent 与工具调用

在做大模型应用时,很多人最先接触的两个词,往往是:
  • Prompt
  • Tool Calling
于是很容易形成一种印象:
只要 prompt 写得足够好,再给模型接几个工具,一个 Agent 系统就差不多成了。
这个理解不能说完全错,但确实太乐观了。
因为在真实系统里,这里面至少有三层问题:
第一,Prompt 不是一段“万能咒语”,而是一套分层约束。  
第二,Agent 不是“一个会回复的模型实例”,而是一个带职责边界的运行单元。  
第三,工具调用不是“让模型随便调函数”,而是一套受控执行系统。
也就是说,真正成熟的 Agent Runtime,不是“模型会不会调用工具”,而是:
模型怎么被约束、Agent 怎么被组织、工具怎么被定义和治理。
这篇文章,我们就集中讲清楚这三个问题。
一、先从一个误区开始:为什么 Prompt 不是“越长越强”的系统提示词
很多人第一次做 Agent,最自然的动作就是写一大段 system prompt。
里面可能会包含:
  • 角色定义
  • 语气风格
  • 安全规则
  • 业务背景
  • 输出格式
  • 工具使用规范
  • 各种注意事项
  • 失败处理方式
  • 一堆案例
写着写着,system prompt 就会越来越长,最后变成一段巨大的说明书。
这时候通常会出现两个问题。
1. Prompt 变成了“信息垃圾桶”
什么都往里面放:
  • 长期有效的系统规则
  • 当前任务的临时约束
  • 某个 Agent 的特殊职责
  • 某次调试时加的补丁说明
  • 某个渠道的回复风格要求
结果是:
  • 不同层次的信息混在一起
  • 很难维护
  • 很难复用
  • 很难灰度升级
  • 很难知道哪句规则在起作用
2. Prompt 会承担它不该承担的职责
很多本该由平台结构化提供的信息,也被硬塞进 prompt 里,比如:
  • 当前任务状态
  • 当前用户权限
  • 工具定义
  • 最近执行结果
  • 当前业务实体 ID
这会导致一个问题:
系统把“结构化状态管理”的责任,推给了自然语言描述。
短期也许能跑,长期一定会乱。
所以,一个成熟系统首先要建立一个认知:
Prompt 不是所有信息的总入口,它只是模型约束体系中的一层。
二、Prompt 应该怎么理解:它不是一段话,而是分层策略
更稳的理解方式是:
Prompt 不是单一文本,而是一组按层次拼装的行为策略。
在 OpenClaw 这类系统里,至少可以分成四层。
1. 平台级 Prompt
这一层定义平台通用规则。
比如:
  • 你是一个执行型 Agent,不要编造执行结果
  • 高风险动作不能擅自执行
  • 输出应尽量清晰、可验证
  • 不泄露内部敏感信息
  • 工具调用失败时要如实说明
这一层是“平台宪法”,不依赖某个具体业务。
2. 渠道级 Prompt
这一层定义某个渠道下的交互特性。
比如:
  • 企业 IM 里回复简洁一点
  • 邮件里可以更正式、更完整
  • 群聊场景下避免暴露不该公开的信息
  • 卡片回复时优先结构化输出
这一层是“交互环境约束”。
3. Agent 级 Prompt
这一层定义某个 Agent 的职责和边界。
比如:
  • 你是审批协同 Agent,只负责发起审批、跟进和同步结果
  • 你不是最终审批决策者
  • 你可以给建议,但不能替用户批准
或者:
  • 你是周报审计 Agent,负责检查提交情况并输出结果
  • 你不负责生成周报内容本身
这一层是“角色定义”。
4. 任务级 Prompt
这一层才是本轮运行的临时任务背景。
比如:
  • 当前目标是检查本周周报提交情况
  • 本轮允许使用周报审计工具和通知工具
  • 如果发现未提交人员,输出名单并提醒
这一层是“当前任务说明书”。
这样分层的好处是非常明显的:
  • 可维护
  • 可复用
  • 可灰度
  • 可审计
  • 不同 Agent 可共享平台规则,但保留个性边界
所以,Prompt 设计真正成熟的标志,不是“写得长”,而是“分层清晰”。
三、Prompt 里到底应该放什么,不应该放什么
理解分层之后,下一个问题就是:每层里到底该放什么?
1. 适合放进 Prompt 的内容
比较适合放进 Prompt 的,通常是:
  • 角色职责
  • 行为边界
  • 风格要求
  • 推理原则
  • 工具使用原则
  • 错误处理原则
  • 输出格式要求
  • 风险控制规则
这些内容的特点是:
  • 倾向于策略性
  • 偏自然语言约束
  • 适合模型理解
  • 不是高精度结构化事实
2. 不适合主要依赖 Prompt 承载的内容
这些内容更适合结构化注入,而不是写进一大段自然语言:
  • 当前任务状态
  • 当前用户权限
  • 当前会话标识
  • 工具参数 schema
  • 当前审批单号
  • 当前目录 ID
  • 最近工具执行返回值
  • 精确配置项
因为这些本质上是“运行时状态”,不是“行为原则”。
3. 一个常见错误
很多系统会写成这样:
“当前你正在处理审批单 A123,它由张三发起,目前处于待 HRBP 审批状态,上一次催办时间是昨天 18:00……”
这类信息当然可以写,但如果整个平台长期都靠自然语言来表达这些状态,那说明状态系统其实没有建好。
更合理的方式是:
  • Prompt 负责“怎么做”
  • 上下文状态负责“现在是什么”
这两者分开,系统会清爽很多。
四、Agent 到底是什么:不是“一个模型”,而是一个职责单元
接下来讲第二个关键词:Agent。
很多人习惯把 Agent 理解成“一个带 prompt 的大模型实例”。  
这个理解太窄了。
在系统设计里,更好的理解是:
Agent 是一个带有明确职责、边界、工具权限和行为约束的运行单元。
这意味着,一个 Agent 至少要回答这些问题:
  • 它负责什么
  • 它不负责什么
  • 它能访问哪些上下文
  • 它能调用哪些工具
  • 它在什么场景下被触发
  • 它和其他 Agent 如何协作
也就是说,Agent 的本质是“职责划分”,而不是“模型包装”。
五、为什么要拆 Agent:单 Agent 不一定错,但边界必须清楚
做系统时,一个很现实的问题是:
到底应该用一个 Agent 处理所有事情,还是拆成多个 Agent?
答案不是固定的,但判断标准通常是职责复杂度。
1. 单 Agent 适合什么场景
如果场景比较集中,动作比较单一,单 Agent 往往更简单。
比如:
  • 周报审计
  • 简单问答助手
  • 某个固定业务查询
  • 某个单流程执行器
优点是:
  • 实现简单
  • 上下文统一
  • 调试方便
缺点是:
  • 容易越长越胖
  • 角色边界不清
  • 功能越来越杂
2. 多 Agent 适合什么场景
如果业务本身已经天然分角色、多阶段、多类型动作,就比较适合拆 Agent。
例如招聘流程可以拆成:
  • 主控 Agent
  • 需求分析 Agent
  • 审批协同 Agent
  • 人才搜寻 Agent
  • 简历评估 Agent
  • 面试 Agent
  • 决策辅助 Agent
这样做的好处是:
  • 每个 Agent 只关心自己的职责
  • Prompt 更清晰
  • 工具权限更容易控制
  • 行为更容易解释
缺点是:
  • 协作复杂
  • 状态流转复杂
  • 容易重复劳动
  • 需要更强的编排层
3. 真正关键的不是“几个 Agent”,而是边界清不清
很多团队把多 Agent 当成炫技,但没想清楚边界,最后只是把复杂度拆碎了。
所以比“要不要多 Agent”更重要的是:
  • 每个 Agent 是否职责单一
  • 是否有清晰输入输出
  • 是否有明确工具权限
  • 是否有清晰交接条件
换句话说,Agent 不是越多越好,而是越清楚越好。
六、Agent 决策时到底在决定什么
当上下文准备好、Prompt 分层完成之后,Agent 开始真正“工作”。
但这里有一个关键认知:
Agent 的第一任务不是回答,而是决定下一步动作。
一个 Agent 在收到当前上下文时,通常至少要做这些判断:
  • 这是直接回答,还是需要工具
  • 这是同步完成,还是异步任务
  • 是否缺少必要信息,需要追问
  • 该调用哪个工具
  • 工具需要调几次
  • 调完工具后是继续推理,还是直接输出
  • 是否应该交给另一个 Agent
所以,模型真正做的是“行动决策”,回答只是最后一环。
一个简单例子
用户说:
“帮我看一下这周还有谁没交周报,并提醒一下。”
Agent 要判断:
  • 这不是纯知识问答
  • 需要访问外部系统
  • 需要用周报检查工具
  • 检查结果出来后,可能还要调用通知工具
  • 如果耗时较长,可能要先回复“处理中”
这就是一次典型的决策过程。
七、工具调用为什么不是“让模型随便调函数”
现在进入这一期最核心的第三部分:工具调用。
很多人一看到 function calling 或 MCP,就会觉得:
“这不就是模型输出个函数名和参数,然后系统帮我执行吗?”
技术上是这样,但系统设计上远远不够。
因为在真实平台里,工具调用必须解决的是这些问题:
  • 模型调的是不是正确工具
  • 参数是否合法
  • 当前用户有没有权限
  • 这个工具风险高不高
  • 超时怎么办
  • 失败要不要重试
  • 结果怎么结构化
  • 调用过程怎么审计
所以,更准确的说法是:
工具调用不是“开放函数给模型”,而是“建立一个受治理的执行体系”。
八、一个成熟的工具定义至少应该包含什么
如果一个工具要能在平台里长期使用,它通常至少要有这些属性。
1. 名称
工具要有稳定名字,而且名字应该表达清楚用途。
比如:
  • `check_weekly_report_status`
  • `send_team_notification`
  • `create_approval_request`
而不是随便叫个 `tool1`、`runTask`。
2. 描述
让模型知道:
  • 这个工具能做什么
  • 什么情况下该调用
  • 不该拿它做什么
3. 输入结构
入参必须可校验。  
否则模型一旦传错参数,系统很难稳定。
4. 输出结构
输出最好是结构化的,让系统和模型都能消费。  
不要返回一大段不可解析的原始字符串。
5. 权限要求
要明确:
  • 谁可以调用
  • 哪类 Agent 可以调用
  • 是否需要额外确认
6. 风险等级
不是所有工具风险一样。
例如:
  • 查询型工具通常低风险
  • 发通知是中风险
  • 审批通过、删数据、转账这类是高风险
7. 执行策略
包括:
  • 超时时间
  • 是否允许重试
  • 是否支持幂等
  • 失败后如何处理
如果这些属性没有建模,工具体系通常很快就会失控。
九、工具调用的完整链路是什么样的
从系统视角看,一次规范的工具调用,通常会经历这些步骤。
第一步:模型决定调用某个工具
模型基于上下文和 Prompt,输出一个结构化动作,例如:
  • 工具名
  • 参数
  • 调用意图
第二步:平台做 schema 校验
检查:
  • 参数格式是否合法
  • 必填字段是否齐全
  • 类型是否正确
  • 值域是否合理
第三步:做权限与策略校验
平台要判断:
  • 当前用户是否有权限
  • 当前 Agent 是否被允许调用这个工具
  • 当前场景是否符合风险策略
  • 是否需要人工确认
第四步:执行工具
这时才真正调用底层实现:
  • API
  • 数据库
  • 浏览器
  • 文件系统
  • 外部服务
第五步:处理结果
执行完成后,平台通常会:
  • 标准化结果
  • 提取关键字段
  • 记录审计日志
  • 更新状态
  • 决定是否回给模型继续推理
第六步:继续决策或结束输出
有些工具结果出来后,Agent 还要继续判断下一步。  
有些则可以直接生成最终回复。
这才是一条完整的工具调用链路。
十、为什么工具调用必须有“边界感”
这点非常重要。
因为一旦系统可以调用工具,它就不再只是“说错一句话”的问题,而可能直接变成“做错一件事”。
1. 工具带来的是执行力,也是风险
例如模型如果答错了一个知识点,最多是误导用户。  
但如果工具调用失控,可能造成的是:
  • 重复发通知
  • 错误发审批
  • 越权读取数据
  • 覆盖错误文档
  • 误删内容
  • 触发错误外部动作
所以工具调用要默认谨慎,而不是默认开放。
2. 平台必须建立风险分级
通常可以粗分成三层:
  • 低风险:查询、读取、检索
  • 中风险:发消息、更新非关键状态
  • 高风险:删除、审批、支付、发版、权限变更
不同风险级别的工具,应该有不同的策略:
  • 是否允许自动执行
  • 是否需要额外确认
  • 是否需要更强审计
  • 是否需要多重校验
3. “模型会不会调错工具”不是唯一问题
更大的问题往往是:
  • 工具本身设计得太粗
  • 权限绑定不严
  • 幂等性没做好
  • 输出太混乱
  • 失败处理不明确
所以工具体系真正的难点,不在 LLM 接口,而在平台治理。
十一、Browser Agent 为什么是“工具体系中的高级成员”
在 OpenClaw 这类平台里,浏览器执行能力通常是一个很有代表性的工具类型。
因为它非常像真实员工在系统里操作:
  • 打开页面
  • 登录系统
  • 找到目标对象
  • 读取页面数据
  • 点击或执行页面内动作
  • 截图或采集状态
  • 回传结果
它的价值在于:
  • 很多企业系统没有完备 API
  • 有些数据只能在页面上拿到
  • 有些动作必须通过真实页面完成
但 Browser Agent 也特别容易出问题。
为什么它更难
因为它要面对:
  • 登录态问题
  • 页面结构变化
  • 网络抖动
  • 页面加载时序
  • DOM 选择器脆弱
  • 不同站点差异
  • API 与页面逻辑混用
所以,成熟系统里 Browser Agent 通常不会被当成“普通函数”,而会做更强封装,比如:
  • 等待页面加载
  • 等待特定条件
  • 页面内执行脚本
  • 统一截图
  • 统一快照
  • 统一异常处理
它本质上是一个“高复杂度执行工具”。
十二、工具调用最容易踩哪些坑
这一部分很关键,因为很多系统问题不是模型错,而是工具体系设计得太随意。
1. 工具输出不结构化
结果就是:
  • 模型难消费
  • 平台难审计
  • 后续流程难串联
2. 工具没有权限边界
结果就是:
  • 谁都能触发高风险动作
  • Agent 越权操作
  • 租户隔离失效
3. 工具没有超时和重试策略
结果就是:
  • 任务卡死
  • 外部系统抖动直接拖垮链路
  • 用户等待时间不可控
4. 工具没有幂等设计
结果就是:
  • 重试一次,多发一次通知
  • 重跑一次,多建一个任务
  • 回调重放导致重复执行
5. 工具粒度太粗或太细
太粗:
  • 一个工具包办太多动作,难以控制
太细:
  • 模型要自己拼装复杂流程,容易出错
所以工具粒度需要刚好适合平台编排。
6. 工具错误信息直接暴露给用户
结果就是:
  • 用户看到大量底层异常
  • 内部实现细节泄露
  • 体验很差
平台应该区分:
  • 面向系统的错误
  • 面向用户的错误表达
下期预告
下一期我们会进入 OpenClaw 里另一个非常关键、也最容易做坏的部分:
《记忆系统怎么做才不翻车:为什么很多 Agent 的记忆,最后会变成污染源》
会重点讲:
  • 会话记忆、用户记忆、任务记忆、知识记忆有什么区别
  • 为什么不能什么都记
  • 记忆什么时候写入、什么时候检索
  • 向量库在这里到底扮演什么角色
  • 记忆污染、错误召回和过期信息怎么处理