本文总结如何修改 OpenClaw sub-agent 的 system prompt,特别是”只对 sub-agent 生效、主 agent 不受影响”的实现方式。完整 plugin 实现见 subagent-prompt-inject-plugin。
核心机制
System Prompt 生成
Sub-agent 的 system prompt 由 src/agents/subagent-system-prompt.ts 中的 buildSubagentSystemPrompt() 生成,包含以下段落:
# Subagent Context
## Your Role
## Rules
## Output Format
## What You DON'T Do
## Sub-Agent Spawning(按 depth 决定)
## Session Context
各段落含义见 subagent-system-prompt-basics。
buildSubagentSystemPrompt 参数
| 参数 | 类型 | 说明 |
|---|---|---|
requesterSessionKey | string? | 父 agent 的 session key,注入到 ## Session Context |
requesterOrigin | DeliveryContext? | 父 agent 的 channel/to 信息 |
childSessionKey | string | 子 agent 的 session key |
label | string? | spawn 时传入的标签 |
task | string? | 任务描述(注入到 ## Your Role) |
acpEnabled | boolean? | 是否启用 ACP,控制 nativeCommandGuidanceLines 是否注入 |
nativeCommandGuidanceLines | string[]? | Plugin 注册的命令 guidance(仅 acpEnabled=true 时生效) |
childDepth | number? | 子 agent 的嵌套深度(1=sub-agent,2=sub-sub-agent) |
maxSpawnDepth | number? | 最大允许嵌套深度,控制是否显示 spawn 指引 |
注入方式
在 src/agents/subagent-spawn.ts:1159,system prompt 以 extraSystemPrompt 字段追加到 agent 原有 prompt 后面(不是替换):
extraSystemPrompt: childSystemPrompt,Session 类型判断
src/agents/pi-embedded-runner/run/attempt.prompt-helpers.ts:209:
export function resolvePromptModeForSession(sessionKey?: string): "minimal" | "full" {
return isSubagentSessionKey(sessionKey) || isCronSessionKey(sessionKey) ? "minimal" : "full";
}- 主 agent:
promptMode = "full" - Sub-agent:
promptMode = "minimal" - Cron session:
promptMode = "minimal"
配置文件的限制
openclaw.json 的 subagents 配置块(src/config/types.agent-defaults.ts:438)没有 prompt 注入字段:
subagents:
delegationMode, allowAgents, maxConcurrent, maxSpawnDepth,
maxChildrenPerAgent, archiveAfterMinutes, model, thinking,
runTimeoutSeconds, announceTimeoutMs, requireAgentId
AGENTS.md、SOUL.md 等 workspace 文件对主 agent 和 sub-agent 都生效,无法区分。
修改方案对比
| 方案 | 适用场景 | 侵入性 | 是否区分 sub-agent |
|---|---|---|---|
修改 AGENTS.md | 全局行为约束 | 零 | 否(主 agent 也受影响) |
task 参数写指令 | 单次 spawn 临时注入 | 零 | 是(精准控制) |
agentPromptGuidance | Plugin 命令使用说明 | 低 | 仅 ACP 模式 |
ProviderPlugin.transformSystemPrompt | 自动化、永久生效 | 中(需写 plugin) | 是 |
改源码 buildSubagentSystemPrompt() | 全局结构性修改 | 高(需 rebuild) | 是 |
前两种方案(AGENTS.md 和 task 参数)的详细说明见 subagent-system-prompt-basics。
推荐方案:ProviderPlugin.transformSystemPrompt
判断逻辑
transformSystemPrompt(ctx) {
// 主 agent 是 "full",直接跳过
if (ctx.promptMode !== "minimal") return null;
// cron session 也是 "minimal",但没有这个 marker
if (!ctx.systemPrompt.includes("# Subagent Context")) return null;
// 只有 sub-agent 才追加
return `${ctx.systemPrompt}\n\n${EXTRA_INSTRUCTIONS}`;
}ctx 完整字段(ProviderTransformSystemPromptContext)
type ProviderTransformSystemPromptContext = {
config?: OpenClawConfig;
agentDir?: string;
workspaceDir?: string;
provider: string;
modelId: string;
promptMode: PromptMode; // "full" | "minimal" | "none"
runtimeChannel?: string;
runtimeCapabilities?: string[];
agentId?: string;
trigger?: "cron" | "heartbeat" | "manual" | "memory" | "overflow" | "user";
systemPrompt: string;
}hookAliases 机制
transformSystemPrompt 按 provider id 查找(src/plugins/provider-hook-runtime.ts)。通过 hookAliases 可以 hook 进目标 provider 而不注册完整 provider,避免冲突:
api.registerProvider({
id: "subagent-prompt-inject-hook-openai",
hookAliases: ["openai"], // hook 进 openai provider 的 transform 链
auth: [], // hook-only plugin,不提供模型
transformSystemPrompt(ctx) { ... },
});agentPromptGuidance 机制
Plugin 可以通过 registerCommand 注册命令时附带 guidance:
api.registerCommand({
name: "my-command",
agentPromptGuidance: [
"When using my-command, always pass --format json",
"my-command results are cached for 5 minutes",
],
});这些 guidance 通过 listRegisteredPluginAgentPromptGuidance() 收集,注入到 ## Sub-Agent Spawning 段。
限制:只在 acpEnabled=true(启用了 ACP harness)时才注入,普通 sub-agent 场景不生效。
常见误区
subagent_spawning hook 不能注入 prompt
subagent_spawning hook 的返回值 PluginHookSubagentSpawningResult 只能返回路由信息,不能注入 system prompt:
type PluginHookSubagentSpawningResult = {
status: "ok" | "error";
threadBindingReady?: boolean;
deliveryOrigin?: DeliveryContext; // 只能改路由
error?: string;
}该 hook 主要用于 channel thread 绑定。
CliBackendPlugin vs ProviderPlugin 的区别
两个 plugin 类型都有 transformSystemPrompt,但签名不同:
CliBackendPlugin(src/plugins/cli-backend.types.ts:124):有 modelDisplay,没有 promptMode、trigger、runtimeCapabilities。
ProviderPlugin(src/plugins/types.ts:1686):有完整的 promptMode、trigger、runtimeCapabilities。
结论:判断 sub-agent 需要 promptMode 字段,必须用 ProviderPlugin 版本。
关键注意点
- OpenClaw 默认 provider 是
openai(src/agents/defaults.ts),TARGET_PROVIDERS需与实际使用的 provider 一致 agentPromptGuidance只在acpEnabled=true时注入,普通 sub-agent 场景不生效- Sub-agent system prompt 是追加模式,不是替换
promptMode === "minimal"同时匹配 sub-agent 和 cron,需结合# Subagent Contextmarker 精准区分subagent_spawninghook 只能改路由,不能注入 system prompt- 判断 sub-agent 必须用
ProviderPlugin.transformSystemPrompt,CliBackendPlugin版本缺少promptMode字段
相关源码
src/agents/subagent-system-prompt.ts— system prompt 生成src/agents/subagent-spawn.ts— spawn 时注入 extraSystemPromptsrc/agents/pi-embedded-runner/run/attempt.prompt-helpers.ts— promptMode 解析src/plugins/types.ts:1214— ProviderTransformSystemPromptContext 类型定义src/plugins/provider-hook-runtime.ts— hookAliases 匹配逻辑src/agents/defaults.ts— DEFAULT_PROVIDER = “openai”