9.1 系统提示词的构建

生成模型:Claude Opus 4.6 (anthropic/claude-opus-4-6) Token 消耗:输入 ~450,000 tokens,输出 ~36,000 tokens(本章合计)


在第 7 章和第 8 章中,我们已经深入了解了 PiAgent 运行时如何执行 Agent 循环,以及模型选择和故障转移机制。但在 Agent 向大语言模型发送第一条请求之前,还有一个关键步骤——构建系统提示词(System Prompt)

系统提示词是 LLM 对话的"元指令",它告诉模型"你是谁、能做什么、应该遵循哪些规则"。OpenClaw 的系统提示词不是一段静态文本,而是由多个动态组装的片段拼接而成的。不同的会话类型(主 Agent vs 子 Agent)、不同的运行环境(沙箱 vs 宿主机)、不同的通道(Telegram vs Signal)都会影响最终生成的提示词内容。

本节将剖析系统提示词的三层构建体系:基础模板、运行时参数、以及最终的提示词诊断报告。

9.1.1 基础提示词模板(src/agents/system-prompt.ts

PromptMode:三种提示词模式

OpenClaw 定义了三种提示词模式,用于控制系统提示词的"详尽程度":

// src/agents/system-prompt.ts
export type PromptMode = "full" | "minimal" | "none";
模式
用途
包含内容

"full"

主 Agent 会话

所有功能段落:工具、安全、技能、记忆、消息、语音等

"minimal"

子 Agent 会话

仅保留:工具列表、工作区、运行时信息

"none"

极简模式

仅返回一行身份声明

当模式为 "none" 时,函数直接返回一行字符串:

if (promptMode === "none") {
  return "You are a personal assistant running inside OpenClaw.";
}

衍生解释——System Prompt 与 User Message 的区别

在大语言模型的 API 中,消息一般分为三种角色:system(系统)、user(用户)、assistant(助手)。System Prompt 是放在对话最开头的"隐藏指令",用户通常看不到,但它对模型行为有最强的约束力。OpenClaw 的所有行为规范——从工具使用到安全限制——都编码在 System Prompt 中。

buildAgentSystemPrompt:核心构建函数

buildAgentSystemPrompt 是整个系统提示词的入口。它接受一个庞大的参数对象,涵盖了 OpenClaw 运行时几乎所有可能影响提示词的维度:

函数内部按照固定顺序将各个功能段落组装成一个字符串数组,最后用 \n 连接。下面我们逐一分析每个段落。

段落一:Tooling(工具列表)

这是提示词的第一个核心段落。它将所有可用工具以列表形式呈现给模型:

系统维护了一个工具排列顺序表 toolOrder,确保常用工具(readwriteedit)始终排在前面。对于不在标准列表中的外部工具(如 MCP 提供的自定义工具),则按字母排序追加到末尾:

值得注意的是,工具名是大小写敏感的。OpenClaw 通过 resolveToolName 函数保留调用方传入的原始大小写,同时在内部用小写进行去重和匹配。

段落二:Tool Call Style(工具调用风格)

这一小段指导模型何时应该"默默地"调用工具,何时需要向用户解释:

段落三:Safety(安全规范)

安全段落是 OpenClaw 遵循 Anthropic 宪法式 AI 原则的体现:

衍生解释——Constitutional AI

Constitutional AI(宪法式 AI)是 Anthropic 提出的一种 AI 对齐方法。其核心思想是为 AI 制定一套明确的行为准则("宪法"),并通过训练让模型内化这些准则。OpenClaw 的 Safety 段落就是这种理念的具体实施——通过系统提示词的方式将安全边界植入到每一次 Agent 对话中。

段落四:Skills(技能系统)

技能段落在"full"模式下才会出现(isMinimal 时跳过)。它指导模型如何从 <available_skills> 列表中选择合适的技能:

技能 XML 片段的格式如下(由 Skills 模块生成,详见后续章节):

段落五:Memory Recall(记忆召回)

当工具列表中包含 memory_searchmemory_get 时,记忆段落指导模型在回答涉及历史信息的问题前先搜索记忆文件:

段落六至十:条件性段落

以下段落根据运行时条件决定是否出现:

段落
条件
功能

User Identity

配置了 ownerNumbers 且非 minimal

告知模型哪些号码是"主人"

Current Date & Time

配置了 userTimezone

提供当前时区信息

Reply Tags

非 minimal 模式

指导使用 [[reply_to_current]] 等回复标签

Messaging

非 minimal 且有 message 工具

跨通道消息发送指引

Voice (TTS)

配置了 TTS hint

语音合成行为指导

buildMessagingSection 为例,它的逻辑特别复杂,因为需要处理不同通道的消息能力:

段落十一:Workspace(工作区)

工作区段落始终存在(即使在 minimal 模式下),它告知模型当前的工作目录:

段落十二:Sandbox(沙箱)

当启用沙箱运行时(Docker 隔离环境),会插入详细的沙箱信息:

衍生解释——沙箱(Sandbox)

沙箱是一种安全隔离机制,将程序的执行限制在一个受控环境中,防止其影响宿主系统。OpenClaw 通过 Docker 容器实现沙箱——Agent 的工具调用(如 execwrite)在容器内执行,即使模型产生了危险命令(如 rm -rf /),也不会损害宿主机。沙箱还支持"提权"(elevated)模式,允许在特定条件下执行宿主机命令。

段落十三:上下文文件注入

这是提示词中体积最大的部分。OpenClaw 将工作区中的引导文件(如 AGENTS.md、SOUL.md)以 # Project Context 标题注入:

注意这里对 SOUL.md 文件做了特殊处理——如果存在 SOUL 文件,模型会被指示"体现其人格和语调"。这是 OpenClaw 身份系统的一部分(详见 9.3 节)。

段落十四至十六:静默回复、心跳、运行时

Silent Replies(静默回复):当模型判断无需回复时,返回一个特殊 token(SILENT_REPLY_TOKEN),OpenClaw 据此判断是否需要向用户发送消息。

Heartbeats(心跳):OpenClaw 定期向 Agent 发送心跳消息,如果一切正常,Agent 回复 HEARTBEAT_OK。这个机制用于检测 Agent 是否需要主动报告异常。

Runtime(运行时信息):最后一行包含当前运行时的全部元数据,格式为:

这行信息由 buildRuntimeLine 函数生成:

完整的提示词组装流程

将上述所有段落串联起来,buildAgentSystemPrompt 的完整流程如下:

最终,所有行通过 lines.filter(Boolean).join("\n") 拼接为一个完整的字符串。一个典型的 full 模式提示词可能有 3,000-10,000 字符(不含注入的上下文文件),而加上 AGENTS.md 等文件后可以达到 20,000-50,000 字符

9.1.2 提示词参数(src/agents/system-prompt-params.ts

提示词模板中引用了许多运行时信息——用户时区、当前时间、Git 仓库根目录等。这些参数由 buildSystemPromptParams 函数统一解析。

SystemPromptRuntimeParams 类型

参数解析流程

Git 仓库根目录检测

resolveRepoRoot 函数负责找到当前项目的 Git 根目录。它采用三级优先策略:

findGitRoot 的实现使用了经典的"向上遍历"算法——从起始目录开始,逐级检查父目录中是否存在 .git 文件或目录,最多向上搜索 12 级:

衍生解释——.git 可以是文件?

通常 .git 是一个目录,包含 Git 仓库的所有元数据(objects、refs 等)。但在 Git submodule 和 git worktree 场景下,.git 会是一个文件,内容指向实际的 .git 目录。因此 findGitRoot 同时检查了 isDirectory()isFile() 两种情况。

时区与时间格式

时区解析(resolveUserTimezone)优先使用配置值,回退到系统的 Intl.DateTimeFormat().resolvedOptions().timeZone

时间格式检测(resolveUserTimeFormat)则会根据操作系统进行不同的检测:

  • macOS:读取 defaults read -g AppleICUForce24HourTime

  • Windows:通过 PowerShell 读取 (Get-Culture).DateTimeFormat.ShortTimePattern

  • 其他:使用 Intl.DateTimeFormat 格式化 13:00 查看结果是否包含 "13"

最终的时间格式化结果类似:"Wednesday, February 18th, 2026 — 8:49 AM"。

9.1.3 提示词报告(src/agents/system-prompt-report.ts

当系统提示词构建完成后,OpenClaw 会生成一份诊断报告SessionSystemPromptReport),用于监控和调试提示词的 token 消耗。这对于防止提示词膨胀导致上下文窗口溢出至关重要。

报告结构

技能解析:parseSkillBlocks

报告需要知道每个技能占用了多少字符。parseSkillBlocks 使用正则表达式从技能 XML 中提取各个 <skill> 块:

工具统计:buildToolsEntries

每个工具的描述长度和 JSON Schema 大小都会被统计:

注入文件统计:buildInjectedWorkspaceFiles

对于每个引导文件,报告记录其原始大小、注入后的大小、以及是否被截断:

报告的主要用途

  1. Token 预算监控:通过 systemPrompt.chars 和各子项的字符数,运维人员可以快速发现哪个部分导致了提示词膨胀。

  2. 截断告警:当引导文件超过 bootstrapMaxChars(默认 20,000 字符)被截断时,报告中的 truncated 标志会触发告警。

  3. 工具审计tools.schemaChars 统计了所有工具 JSON Schema 的总大小。当 MCP 提供的外部工具过多时,Schema 可能消耗大量上下文空间,报告帮助识别这类问题。

  4. 技能开销分析skills.entries 列出每个技能块的字符数,帮助识别体积过大的技能定义。


本节小结

  1. 系统提示词是 OpenClaw 控制 Agent 行为的核心机制,采用模块化组装模式——十余个功能段落根据运行时条件动态拼接。

  2. 三种 PromptMode(full/minimal/none)为不同场景提供不同详尽度的提示词:主 Agent 获得完整指令,子 Agent 获得精简版本,极简模式仅保留身份声明。

  3. 运行时参数buildSystemPromptParams)负责解析时区、时间格式、Git 仓库根目录等环境信息,采用"配置优先、系统检测回退"的策略。

  4. 提示词报告buildSystemPromptReport)为每次提示词生成创建详细的统计信息,是防止上下文窗口溢出的第一道防线。

  5. 提示词的体积管理是一个关键挑战——引导文件截断、工具 Schema 统计、技能字符数监控共同构成了 OpenClaw 的 token 预算管理体系。

Last updated