ARTICLE · 1120381
OpenClaw 先加载什么,再加载什么?
山之上下 · OpenClaw 工程手记 02
先看加载顺序
规则和目录先给,Skill 正文按需读,业务结果执行后再补。
① 首次调用前: 组装系统规则、工作区文件和 Skill 目录,另附工具定义与会话消息。
② 模型选中后: 请求读取 Skill,运行时将正文作为工具结果补入上下文。
③ 查询完成后: 账户数据继续回填,由模型整理回答。
上一篇聊完选型,我想接着弄清楚:OpenClaw 是怎么知道该加载哪个 Skill 的?
拿一个具体请求来说:
查一下我有权限访问的广告账户,先给我第一页。
假设我们有一个 account Skill,包含账户列表、详情和状态查询。账户系统也已经提供了查询命令。
用户只说了一句话,模型从哪里知道有什么能力,又该怎么使用?
01
第一次调用,不只是发一句用户消息
OpenClaw 会由代码组装系统提示词。buildAgentSystemPrompt() 是其中的构建函数;工作区内容则会被整理进 Project Context。因此,AGENTS.md、USER.md 是提示词的组成材料,不是全部提示词。
在我们的例子里,第一次输入可以拆成三块:系统提示词、工具定义、会话消息。 下面是中文简化示意,不是完整源码原文,也不是实际请求抓包。
一、系统提示词|节选
# Skills 使用规则(按源码意译)查看可用 Skill 目录。有明确匹配时,读取指定位置的说明并遵循。多个候选时选最具体的;无相关能力则不读。起步阶段最多先读一个,不要编造路径。# 可用 Skill 目录(示例条目)name: accountdescription: 查询广告账户列表、详情和状态location: /workspace/skills/account/SKILL.md# Project Context(以下内容均为自拟)## AGENTS.md账户数据以查询结果为准,不编造。## SOUL.md直接回答,减少寒暄。## IDENTITY.md你是广告业务工作助手。## USER.md账户列表优先展示编号、名称和状态。二、工具定义|参数简写
read(path: string):读取文件exec(command: string):执行命令三、会话消息|假设没有历史对话
user: 查一下我有权限访问的广告账户, 先给我第一页。这些工作区约定可以在调用前由系统注入,不需要模型先逐个调用工具读取。Skill 则先展示目录,具体指令按需加载;这里的 account 条目也只是目录格式的简写。
到这一步,模型知道有账户查询能力,但还没读到操作步骤,更没有账户数据。
02
模型为什么会先读 Skill?
看源码后,我觉得最值得注意的,不是目录长什么样,而是目录前面的使用规则。
src/agents/system-prompt-skills.ts 中的 buildSkillsSection(),会生成刚才那类选择和读取指令。其中一句原文是:
源码节选 · Skills 使用规则
Up-front max one. Never invent paths.它要求起步阶段最多读取一个,不要编造路径。这里限制的是提前加载,不是规定整个任务只能使用一个 Skill。
我会这样理解这几条提示词的设计:描述帮助模型判断是否匹配,“选最具体的”帮助处理重叠,“无相关能力就不读”则避免强行套用。
代码把目录准备好,还需要提示词告诉模型怎么用。在这条自动选择路径里,具体读取哪个 Skill,由模型发起工具调用。
这不是一张写死的路由表,也不能据此认定模型一定选得准确。
03
读完说明,再去查账户
假设模型选中了 account,发起 read 调用。运行时读回的 SKILL.md 中,账户列表这一段是:
SKILL.md 正文 · 自拟示例
## 查询账户列表通过 exec 执行:biz account list --page 1 --page-size 20 --output json展示 account_id、name、status。标注当前页,不要把第一页说成全部账户。biz 是我们假设接入的自定义命令,不是 OpenClaw 内置能力;读取和执行工具也假设已获准使用。
读回来的 Skill 不会替换原有提示词,而是作为工具结果加入后续上下文。模型再根据说明发起账户查询,等待真实数据返回。
把这个例子的三轮调用摆在一起:
第一轮 · 输入与输出
输入:系统提示词 + 工具定义 + 用户请求输出:请求读取 account/SKILL.md第二轮 · 输入与输出
输入:保留前文,追加读取调用及 Skill 正文输出:请求执行账户查询命令第三轮 · 输入与输出
输入:保留前文,追加查询调用及账户数据输出:按用户偏好整理账户表格这里假设读取和查询均成功,不需要追问。三轮是这个例子的路径,不是 OpenClaw 的固定轮数。 实际执行是模型推理与工具调用交替推进。
04
我想借鉴的是这层分工
理解这条链路后,我会把信息分开放:工作约定提前给,业务步骤留在 Skill 中,账户数据由查询结果提供。
提示词既承载规则,也在指导执行:什么时候选择能力,什么时候读取说明,接下来如何调用工具。
但我不会把提示词当成安全保障。“只查询有权限的账户”应该由后端校验,而不是靠模型自觉遵守。官方也明确提醒:系统提示词中的约束,不等于运行时的强制执行。
这次最值得记住的,不只是加载顺序:代码准备内容,提示词指导选择,模型发起调用,运行时负责执行。
山之上下