系统提示词是 LLM 对话的"元指令",它告诉模型"你是谁、能做什么、应该遵循哪些规则"。OpenClaw 的系统提示词不是一段静态文本,而是由多个动态组装的片段拼接而成的。不同的会话类型(主 Agent vs 子 Agent)、不同的运行环境(沙箱 vs 宿主机)、不同的通道(Telegram vs Signal)都会影响最终生成的提示词内容。
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 中。
Default: do not narrate routine, low-risk tool calls (just call the tool).
Narrate only when it helps: multi-step work, complex/challenging problems,
sensitive actions (e.g., deletions), or when the user explicitly asks.
const safetySection = [
"## Safety",
"You have no independent goals: do not pursue self-preservation, " +
"replication, resource acquisition, or power-seeking...",
"Prioritize safety and human oversight over completion...",
"Do not manipulate or persuade anyone to expand access or disable safeguards...",
];
function buildSkillsSection(params: {
skillsPrompt?: string;
isMinimal: boolean;
readToolName: string;
}) {
if (params.isMinimal) return [];
const trimmed = params.skillsPrompt?.trim();
if (!trimmed) return [];
return [
"## Skills (mandatory)",
"Before replying: scan <available_skills> <description> entries.",
`- If exactly one skill clearly applies: read its SKILL.md at <location> ` +
`with \`${params.readToolName}\`, then follow it.`,
"- If multiple could apply: choose the most specific one...",
"- If none clearly apply: do not read any SKILL.md.",
trimmed, // 实际的技能 XML 列表
];
}
<available_skills>
<skill>
<name>git-master</name>
<description>MUST USE for ANY git operations...</description>
<location>/path/to/SKILL.md</location>
</skill>
</available_skills>
function buildMemorySection(params: {
isMinimal: boolean;
availableTools: Set<string>;
citationsMode?: MemoryCitationsMode;
}) {
if (params.isMinimal) return [];
if (!params.availableTools.has("memory_search") &&
!params.availableTools.has("memory_get")) {
return [];
}
const lines = [
"## Memory Recall",
"Before answering anything about prior work, decisions, dates, " +
"people, preferences, or todos: run memory_search on MEMORY.md + " +
"memory/*.md; then use memory_get to pull only the needed lines.",
];
// 根据 citationsMode 决定是否要求引用来源
if (params.citationsMode === "off") {
lines.push("Citations are disabled...");
} else {
lines.push("Citations: include Source: <path#line>...");
}
return lines;
}
function buildMessagingSection(params: {
isMinimal: boolean;
availableTools: Set<string>;
messageChannelOptions: string; // 如 "signal|telegram|discord"
inlineButtonsEnabled: boolean; // 当前通道是否支持内联按钮
runtimeChannel?: string; // 当前运行通道
}) {
if (params.isMinimal) return [];
return [
"## Messaging",
"- Reply in current session → automatically routes to the source channel",
"- Cross-session messaging → use sessions_send(sessionKey, message)",
params.availableTools.has("message")
? [
"### message tool",
"- Use `message` for proactive sends + channel actions...",
`- If multiple channels, pass \`channel\` (${params.messageChannelOptions}).`,
params.inlineButtonsEnabled
? "- Inline buttons supported..."
: `- Inline buttons not enabled for ${params.runtimeChannel}...`,
].join("\n")
: "",
];
}
## Workspace
Your working directory is: /home/user/.openclaw/workspace
Treat this directory as the single global workspace for file operations.
params.sandboxInfo?.enabled ? [
"## Sandbox",
"You are running in a sandboxed runtime (tools execute in Docker).",
params.sandboxInfo.workspaceDir
? `Sandbox workspace: ${params.sandboxInfo.workspaceDir}`
: "",
params.sandboxInfo.elevated?.allowed
? "Elevated exec is available for this session."
: "",
// ...更多沙箱细节
].filter(Boolean).join("\n") : ""
const contextFiles = params.contextFiles ?? [];
if (contextFiles.length > 0) {
const hasSoulFile = contextFiles.some((file) => {
const baseName = file.path.split("/").pop() ?? file.path;
return baseName.toLowerCase() === "soul.md";
});
lines.push("# Project Context",
"The following project context files have been loaded:");
if (hasSoulFile) {
lines.push(
"If SOUL.md is present, embody its persona and tone. " +
"Avoid stiff, generic replies; follow its guidance..."
);
}
for (const file of contextFiles) {
lines.push(`## ${file.path}`, "", file.content, "");
}
}