OpenClaw 提示词管理系统深度剖析

Jul 8, 2026 分钟阅读

目标读者:核心开发者 / 贡献者
范围:OpenClaw 运行时如何为每一次 Agent 运行组装、缓存、注入 system prompt,以及 Skill prompt、Provider 贡献、子代理提示词等周边机制。


1. 引言:什么在管理“提示词”

在 OpenClaw 中,所谓“提示词管理”并不是单一文件或类,而是一个以 src/agents/system-prompt.ts 为核心的分层装配流水线。它的输入是:

  • 当前 Agent 的配置(openclaw.json)
  • 运行时事实(workspace、channel、capabilities、tools、sandbox、model 等)
  • 项目上下文文件(AGENTS.md、SOUL.md、TOOLS.md、MEMORY.md、HEARTBEAT.md、BOOTSTRAP.md)
  • Skill 元数据与可用技能列表
  • Provider 插件贡献的模型专属提示词片段

输出是一个完整的 system prompt 字符串,被注入到 LLM 请求中。所有与“最终 prompt 长什么样”相关的决策,几乎都在这条流水线里完成。

文档 docs/concepts/system-prompt.md 是这套系统的官方设计说明;本文则从源码层面系统化拆解其结构、数据流与扩展点。


2. 总体架构:三层流水线

官方文档把 system prompt 组装划分为三层:

  1. 渲染层(Renderer) — src/agents/system-prompt.ts
    纯函数 buildAgentSystemPrompt,只接受显式参数,不直接读全局配置。
  2. 配置解析层(Config Resolver) — src/agents/system-prompt-config.ts
    resolveAgentSystemPromptConfig 把 openclaw.json 里与 prompt 相关的字段解析成渲染层能理解的参数。
  3. 运行时适配层(Runtime Adapters) — 分散在 embedded runner、CLI、auto-reply、compaction 等模块
    收集实时事实(tools、sandbox、channel capabilities、context files、provider contributions),调用配置过的 prompt facade。

这种分层的目的:让导出/调试 prompt 表面与真实运行保持一致,同时避免把每个运行时细节都塞进一个巨型 builder。

 1openclaw.json + agent defaults
 2        │
 3        ▼
 4resolveAgentSystemPromptConfig
 5        │
 6        ▼
 7embedded/cli/auto-reply runtime  ──►  buildAgentSystemPrompt  ──►  system prompt string
 8        │                                    ▲
 9        └──── runtime facts ────────────────┘
10              tools, channel, sandbox,
11              context files, provider contrib

3. 渲染层核心:src/agents/system-prompt.ts

3.1 入口函数

buildAgentSystemPrompt(params) 是核心入口(src/agents/system-prompt.ts:682)。它接收一个庞大的 options 对象,涵盖:

  • workspaceDir:工作目录
  • toolNames / capabilityToolNames / toolSummaries:可用工具
  • contextFiles:项目上下文文件数组
  • bootstrapMode / bootstrapTruncationNotice:BOOTSTRAP 状态
  • skillsPrompt / heartbeatPrompt:技能与心跳提示词
  • runtimeInfo:agentId、session、channel、capabilities、model 等
  • promptMode:full | minimal | none
  • silentReplyPromptMode / sourceReplyDeliveryMode:回复投递模式
  • subagentDelegationMode / acpEnabled:子代理/ACP 配置
  • promptSurface:prompt 表面类型
  • promptContribution:Provider 贡献
  • 各种 owner、timezone、TTS、model alias、memory、sandbox 等配置

函数内部按顺序拼接固定区块,最终返回一个字符串。

3.2 Prompt 模式

类型定义在 src/agents/system-prompt.types.ts:

1export type PromptMode = "full" | "minimal" | "none";
2export type SilentReplyPromptMode = "generic" | "none";
  • full:主 Agent,包含所有区块。
  • minimal:子代理,省略 Memory、Self-Update、Model Aliases、User Identity、Messaging、Silent Replies、Heartbeats 等。
  • none:只保留基础身份行。

isMinimal 在渲染器内部被频繁用来开关各区块。

3.3 固定区块与职责

区块构建函数说明
Tooling主函数内联列出可用工具、tool schema 延迟加载提示、工作流提示
Sub-Agent DelegationbuildSubagentDelegationPreferenceSectionprefer 模式下强化子代理委派
Tool Call StylebuildOverridablePromptSection可被 Provider 覆盖
Execution BiasbuildExecutionBiasSection强调“ actionable request 立即行动”
Safety主函数内联防止权力寻求、绕过监管
OpenClaw Control主函数内联优先用 gateway 工具,不 invent 命令
OpenClaw Self-Update主函数内联gateway 配置/更新指南
SkillsbuildSkillsSection如何按需读取 SKILL.md
Skill WorkshopbuildSkillWorkshopPromptSectionSkill Workshop 工具说明
MemorybuildMemorySectionmemory 工具与引用模式
Workspace主函数内联工作目录、FS policy
DocumentationbuildDocsSectiondocs/source 路径
Project ContextbuildProjectContextSection注入的上下文文件
Assistant Output DirectivesbuildAssistantOutputDirectivesSectionMEDIA:、message tool 输出规则
Silent Replies主函数内联NO_REPLY 规则
Webchat CanvasbuildWebchatCanvasSectionwebchat 富渲染
MessagingbuildMessagingSection当前会话/跨会话消息、子代理编排
VoicebuildVoiceSectionTTS hint
HeartbeatsbuildHeartbeatSection心跳轮询行为
Runtime主函数内联 + buildRuntimeLine运行时元数据

3.4 项目上下文文件处理

contextFiles 是 EmbeddedContextFile[]。渲染器会:

  1. 过滤掉无效路径。
  2. 按 CONTEXT_FILE_ORDER 排序:agents.md → soul.md → identity.md → user.md → tools.md → bootstrap.md → memory.md。
  3. 区分 stable 与 dynamic 文件;目前 HEARTBEAT.md 是唯一的 dynamic 文件。
  4. 对 HEARTBEAT.md 内容做特殊过滤,防止触发 Claude Code 订阅模式拒绝。
  5. 渲染为 ## <path> 段落。

3.5 缓存边界与 Stable Prefix 缓存

OpenClaw 在 prompt 中插入一个内部缓存边界 SYSTEM_PROMPT_CACHE_BOUNDARY(定义在 src/agents/system-prompt-cache-boundary.ts)。

  • Stable Prefix(边界之上):项目上下文、工具说明、Safety、Workspace 等跨 turn 变化较小的内容。
  • Dynamic Suffix(边界之下):Messaging、Runtime、Heartbeat、Group Chat Context 等随 turn 变化的内容。

为了进一步提升性能,buildAgentSystemPrompt 对 stable prefix 做了进程内 LRU 缓存:

1const stablePromptPrefixCache = new Map<string, StablePromptPrefixCacheEntry>();
2const SYSTEM_PROMPT_STABLE_PREFIX_CACHE_LIMIT = 64;

缓存 key 通过对一组稳定输入做 sha256 得到(hashStablePromptInput),包含 workspaceDir、toolLines、ownerLine、reasoningLevel、runtimeChannel、capabilities、context files 等。

3.6 工具名称解析

渲染器内部维护了一个 canonicalByNormalized Map,保留调用方传入的工具大小写,同时按小写去重:

1const canonicalByNormalized = new Map<string, string>();
2for (const name of canonicalToolNames) {
3  const normalized = name.toLowerCase();
4  if (!canonicalByNormalized.has(normalized)) {
5    canonicalByNormalized.set(normalized, name);
6  }
7}

核心工具按固定 toolOrder 输出,额外工具按字母排序输出。


4. 配置解析层:src/agents/system-prompt-config.ts

4.1 职责

这一层把 openclaw.json 的复杂配置映射为 buildAgentSystemPrompt 的参数。核心函数:

  • resolveAgentSystemPromptConfig({ config, agentId })(src/agents/system-prompt-config.ts:35)
  • buildConfiguredAgentSystemPrompt(params)(src/agents/system-prompt-config.ts:58)

4.2 解析的字段

 1type ResolvedAgentSystemPromptConfig = Pick<
 2  AgentSystemPromptRenderParams,
 3  | "ownerDisplay"
 4  | "ownerDisplaySecret"
 5  | "subagentDelegationMode"
 6  | "ttsHint"
 7  | "modelAliasLines"
 8  | "memoryCitationsMode"
 9  | "fsWorkspaceOnly"
10>;
  • ownerDisplay / ownerDisplaySecret:来自 resolveOwnerDisplaySetting
  • subagentDelegationMode:从 config.agents.list[].subagents.delegationMode 或 defaults 读取,默认 suggest
  • ttsHint:来自 buildTtsSystemPromptHint
  • modelAliasLines:来自 buildModelAliasLines
  • memoryCitationsMode:config.memory.citations
  • fsWorkspaceOnly:resolveEffectiveToolFsWorkspaceOnly

这样,渲染层本身不需要知道 openclaw.json 的结构;测试渲染层时也可以直接传参。


5. 提示词表面与运行时适配

5.1 Prompt Surface:src/agents/prompt-surface.ts

Prompt Surface 决定工具提示词如何根据运行环境变化。类型 AgentPromptSurfaceKind 来自 src/plugins/types.ts,常见值:

  • openclaw_main:标准 OpenClaw 运行时
  • subagent:子代理
  • acp_backend:ACP harness(如 Codex)

resolveAgentPromptSurfaceForSessionKey 根据 session key 判断 surface:

1export function resolveAgentPromptSurfaceForSessionKey(sessionKey?: string): AgentPromptSurfaceKind {
2  if (sessionKey && isAcpSessionKey(sessionKey)) {
3    return "acp_backend";
4  }
5  return sessionKey && isSubagentSessionKey(sessionKey) ? "subagent" : "openclaw_main";
6}

buildOpenClawToolFallbackText 在 openclaw_main 表面下提供完整工具说明;在其他表面下只给出通用提示。

5.2 子代理提示词:src/agents/subagent-system-prompt.ts

buildSubagentSystemPrompt 生成子代理会话的专属提示词,包含:

  • Your Role:明确只是执行任务,不是主 Agent
  • Rules:专注、完成任务、不主动、不心跳、信任 push-based completion
  • Output Format:最终回复应包含什么
  • Sub-Agent Spawning:是否能继续 spawn(由 childDepth 与 maxSpawnDepth 决定)
  • Session Context:requester session、channel 等

5.3 心跳提示词:src/agents/heartbeat-system-prompt.ts

为 heartbeat 轮询提供行为规则,例如无事项时回复 HEARTBEAT_OK。

5.4 Bootstrap 提示词:src/agents/bootstrap-prompt.ts

处理 BOOTSTRAP.md 的两种模式:

  • full:完整 BOOTSTRAP 工作流
  • limited:受限运行,提示 Agent 无法安全完成完整流程

6. Provider 贡献机制

6.1 类型:src/agents/system-prompt-contribution.ts

Provider 可以通过 ProviderSystemPromptContribution 在不替换整个 prompt 的前提下影响最终输出:

1export type ProviderSystemPromptContribution = {
2  stablePrefix?: string;           // 缓存边界之上
3  dynamicSuffix?: string;          // 缓存边界之下
4  sectionOverrides?: Partial<Record<
5    ProviderSystemPromptSectionId,
6    string
7  >>;
8};

可覆盖的 section:

  • interaction_style
  • tool_call_style
  • execution_bias

6.2 GPT-5 覆盖:src/agents/gpt5-prompt-overlay.ts

针对 OpenAI GPT-5 家族的 overlay,添加模型专属指导:persona latching、concise output、tool discipline、parallel lookup、deliverable coverage 等。

6.3 处理流程

在 buildAgentSystemPrompt 中:

  1. normalizeProviderPromptBlock 对 contribution 文本做归一化(去回车、去行尾空白、trim)。
  2. providerStablePrefix 在 stable prefix 区域追加。
  3. providerSectionOverrides 通过 buildOverridablePromptSection 替换对应区块。
  4. providerDynamicSuffix 在 dynamic 区域追加。

7. Skill 提示词管理

Skill 不是直接塞进 system prompt 的大段文本,而是通过可用技能列表让模型按需读取。

7.1 技能格式化:src/skills/loading/skill-contract.ts

formatSkillsForPrompt(skills) 把 skill 列表渲染为 XML:

1<available_skills>
2  <skill>
3    <name>...</name>
4    <description>...</description>
5    <location>...</location>
6    <version>sha256:...</version>
7  </skill>
8</available_skills>

模型被指示:当任务匹配描述时,用 read 工具读取对应 SKILL.md。

7.2 技能解析与预算:src/skills/loading/workspace.ts

resolveSkillsPromptForRun(src/skills/loading/workspace.ts:1503)决定最终注入的 skill prompt:

  1. 如果 skillsSnapshot.prompt 存在,优先使用 snapshot。
  2. 否则从 entries 构建:
    • buildWorkspaceSkillsPrompt 筛选 eligible skills
    • compactSkillPaths 压缩路径(如 ~/...)
    • applySkillsPromptLimits 应用字符预算
    • buildRenderedSkillsPrompt 渲染最终文本

预算来源:

  • 全局默认:skills.limits.maxSkillsPromptChars
  • 单 Agent 覆盖:agents.list[].skillsLimits.maxSkillsPromptChars

7.3 Skill Prompt Blob:src/config/sessions/skill-prompt-blobs.ts

当 skill prompt 很大时,OpenClaw 会把它外置到内容寻址的 blob 文件,而不是直接内联在 session store 中:

  • 目录:skills-prompts/sha256/<prefix>/<hash>.txt
  • 阈值:MIN_PROMPT_BLOB_CHARS = 512
  • 上限:MAX_PROMPT_BLOB_BYTES = 512 * 1024

关键函数:

  • projectSessionStoreForPersistence:把 store 中 inline 的 skill prompt 替换为 promptRef
  • ensureSessionStorePromptBlobsForPersistence:确保 blob 文件写入
  • hydrateSessionStoreSkillPromptRefs:从 blob 还原 prompt;若 blob 缺失/损坏则删除整个 snapshot

这减少了 session store 体积,同时保证内容寻址的完整性。


8. 缓存稳定性与文本归一化

8.1 src/agents/prompt-cache-stability.ts

提供两个核心工具:

  • normalizeStructuredPromptSection(text):统一换行符、去掉行尾空白、trim。用于 prompt 哈希或快照比较前。
  • normalizePromptCapabilityIds(capabilities):小写、去重、排序 capability ids,保证 prompt payload 稳定。

8.2 src/agents/sanitize-for-prompt.ts

sanitizeForPromptLiteral 对要插入 prompt 的字符串做转义处理,防止破坏提示词结构。


9. 测试与快照机制

9.1 单元测试

  • src/agents/system-prompt.test.ts:主渲染器行为
  • src/agents/prompt-composition.test.ts:prompt 组合
  • src/agents/system-prompt-cache-boundary.test.ts:缓存边界
  • src/agents/system-prompt-stability.test.ts:稳定性归一化
  • src/agents/prompt-overlay-runtime-contract.test.ts:overlay 运行时契约
  • src/skills/loading/prompt-resolution.test.ts:skill prompt 解析

9.2 Prompt 快照

目录:test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/

这些快照覆盖 Telegram direct、Discord group、heartbeat 等典型 turn,包含:

  • 固定的 Codex gpt-5.5 model prompt fixture
  • OpenClaw developer instructions
  • turn-scoped collaboration-mode instructions
  • user turn input
  • dynamic tool specs 引用

生成与校验命令:

1pnpm prompt:snapshots:gen      # 重新生成
2pnpm prompt:snapshots:check    # 校验漂移
3pnpm prompt:snapshots:sync-codex-model  # 同步 Codex model fixture

CI 在 boundary shard 中运行 drift check,确保 prompt 变更与快照更新绑定在同一 PR。


10. 扩展与定制指南

10.1 修改 System Prompt 内容

直接编辑 src/agents/system-prompt.ts 中对应区块的构建函数。注意:

  • 保持缓存边界上下内容的语义区分。
  • 若新增跨 turn 稳定内容,考虑加入 stable prefix cache key。
  • 若新增 Provider 可覆盖区块,在 ProviderSystemPromptSectionId 中声明。

10.2 添加新的 Provider 覆盖

  1. 在 src/agents/system-prompt-contribution.ts 的 ProviderSystemPromptSectionId 中扩展可覆盖区块(如需)。
  2. Provider 插件在运行时返回 ProviderSystemPromptContribution。
  3. 渲染层通过 buildOverridablePromptSection 合并。

10.3 添加新的 Prompt Surface

  1. 在 src/plugins/types.ts 扩展 AgentPromptSurfaceKind。
  2. 在 src/plugins/agent-prompt-surface-kind.ts 添加归一化判断。
  3. 在 src/agents/prompt-surface.ts 添加对应 fallback 文本与 workflow hint 规则。

10.4 扩展 Skill 提示词

Skill 本身的文本由 skill 作者决定;OpenClaw 侧主要控制:

  • formatSkillsForPrompt:修改 XML 格式
  • applySkillsPromptLimits:修改预算逻辑
  • skill-prompt-blobs.ts:修改 blob 阈值或存储布局

10.5 调试

  • 使用 /context list 或 /context detail 查看每个注入文件对 prompt 的贡献。
  • 运行 openclaw status 查看当前会话状态。
  • 查看 test/fixtures/agents/prompt-snapshots/ 对比预期输出。

11. 关键数据流总结

一次典型 Agent 运行的 prompt 组装流程:

 11. 运行时(embedded/cli/auto-reply)收集事实
 2   ├─ tools, capabilities, channel, chatType
 3   ├─ workspaceDir, contextFiles
 4   ├─ sandboxInfo, runtimeInfo
 5   ├─ skillsPrompt / heartbeatPrompt
 6   └─ provider prompt contribution
 7
 82. resolveAgentSystemPromptConfig({ config, agentId })
 9   └─ 解析 ownerDisplay、ttsHint、modelAliasLines、
10      subagentDelegationMode、memoryCitationsMode、fsWorkspaceOnly
11
123. buildConfiguredAgentSystemPrompt({ ...runtimeFacts, ...configParams })
13   └─ 调用 buildAgentSystemPrompt
14
154. buildAgentSystemPrompt 内部
16   ├─ 计算 stable prefix cache key
17   ├─ 命中缓存则复用;否则构建 stable prefix
18   │   ├─ Tooling、Safety、Skills、Memory、Workspace、Project Context
19   │   └─ 插入 SYSTEM_PROMPT_CACHE_BOUNDARY
20   ├─ 追加 dynamic suffix
21   │   ├─ Messaging、Voice、Group/Subagent Context、Reactions
22   │   ├─ Provider dynamicSuffix
23   │   └─ Heartbeats、Runtime
24   └─ 返回最终字符串
25
265. 最终 system prompt 进入 LLM 请求

12. 设计取舍与注意点

  1. 渲染器保持纯函数:buildAgentSystemPrompt 不直接读全局配置,便于测试和复现。
  2. 配置与运行时分离:配置解析一次,运行时事实每次可能变化。
  3. 缓存边界是内部约定:不是模型 API 的 cache control,而是 OpenClaw 自己用于 stable prefix 缓存和 Provider 贡献分区。
  4. Skill prompt 不内联大文本:通过 <available_skills> 列表 + 按需 read 控制上下文窗口。
  5. Blob 外置是存储优化:不改变 prompt 语义,只是让 session store 更小。
  6. Provider 贡献受限:只能覆盖三个 section 和注入 prefix/suffix,防止 Provider 破坏 OpenClaw 核心提示词结构。
  7. Prompt 快照是契约测试:任何对 prompt 文本的修改都会触发快照漂移,强制作者在 PR 中同步更新。

13. 相关文件索引

文件作用
src/agents/system-prompt.ts核心 system prompt 渲染器
src/agents/system-prompt.types.tsPromptMode / SilentReplyPromptMode 类型
src/agents/system-prompt-config.ts配置解析层
src/agents/prompt-surface.tsPrompt surface 工具提示
src/agents/subagent-system-prompt.ts子代理提示词
src/agents/heartbeat-system-prompt.ts心跳提示词
src/agents/bootstrap-prompt.tsBOOTSTRAP 提示词
src/agents/system-prompt-contribution.tsProvider 贡献类型
src/agents/gpt5-prompt-overlay.tsGPT-5 overlay
src/agents/prompt-cache-stability.ts缓存稳定性归一化
src/agents/sanitize-for-prompt.tsPrompt 字面量清理
src/agents/system-prompt-cache-boundary.ts缓存边界标记
src/plugins/agent-prompt-surface-kind.tsSurface kind 归一化
src/skills/loading/skill-contract.tsSkill XML 格式化
src/skills/loading/workspace.tsSkill prompt 解析与预算
src/config/sessions/skill-prompt-blobs.tsSkill prompt blob 存储
docs/concepts/system-prompt.md官方设计文档
test/fixtures/agents/prompt-snapshots/提交级 prompt 快照

14. 结语

OpenClaw 的提示词管理系统是一个高度结构化、分层、可测试、可扩展的装配流水线。它把“最终 prompt 是什么”这个问题拆成了:

  • 配置解析
  • 运行时事实收集
  • 纯函数渲染
  • Provider 贡献合并
  • Skill 提示词按需注入
  • 缓存与存储优化

理解这条流水线的关键是抓住三个层次和三个边界:

  • 三层:渲染器、配置解析器、运行时适配器
  • 三边界:stable/dynamic prompt 缓存边界、Provider 贡献边界、OpenClaw 核心与 Plugin 扩展边界

如果要从一个文件开始阅读,首选 src/agents/system-prompt.ts;如果要理解整体契约,先读 docs/concepts/system-prompt.md。