System Prompt

系统提示词是策略、工具、技能与上下文的生成产物。

有序区块 + 命名变量 + 工具 schema 汇入。

65 行组装器

问题

到目前,系统提示词是一段手写的字符串:"你是编程助手。对于多步任务:..."

现在它需要包含:todo 计划(s05)、技能目录(s07)、历史摘要(s08)、权限规则(s03)、会话上下文(cwd、模型名)、以及全部工具 schema。如果这些内容都手工拼接进一个字符串——谁负责顺序?谁负责更新?注册一个新工具后忘了改系统提示词怎么办?

系统提示词不该是一段手写字符串,而是一个组装产物:各插件贡献自己的区块(带顺序),组装器按序渲染。

解决方案

区块注册表 + 命名变量:

  • 每个插件注册一个 PromptSection{ name, order, content });
  • 组装器按 order 排序渲染,并解析 {{variable}} 占位符;
  • 工具 schema 由注册表自动汇入(s02 的注册表现在同时喂养 prompt)。
const sections = []; // { name, order, content }

function section(name, order, content) {
  sections.push({ name, order, content });
}

function assemble({ model, cwd }) {
  const vars = { model, cwd };
  return sections
    .sort((a, b) => a.order - b.order)
    .map((s) => render(s.content, vars))
    .join("\n\n");
}

function render(template, vars) {
  return template.replace(/\{\{(\w+)\}\}/g, (_, k) => vars[k] ?? `{{${k}}}`);
}

工作原理

第 1 步:各机制以区块方式注册自己的 prompt 贡献:

section("harness:identity", -100, "You are an AI agent powered by Nano Harness.");
section("tools:policy", 0, `可用工具:${toolDescriptions()}`);
section("todo:plan", 10, renderPlan());          // s05 的计划
section("skills:catalog", 20, `可用技能:\n${catalog()}`); // s07 的目录
section("context:runtime", 30, "工作目录:{{cwd}};模型:{{model}}");

第 2 步:每次请求组装一次——这就是为什么 todo 更新、技能加载、压缩摘要能在下一轮自动出现在系统提示词里:它们都是注册的区块,每轮重新渲染。

第 3 步:工具 schema 不再是"另一个数组"——它和区块一起构成请求的完整前缀。注册表、区块表、工具表三者统一。

组装的价值在于解耦:插件只声明"我要贡献什么、排在哪",不需要知道其他插件贡献了什么。加一个技能目录?注册一个区块。换模型?变量替换。系统提示词永远自洽。

试一下

运行 s10,观察组装产物:

  • 打印 assemble() 的结果,确认区块顺序与变量替换
  • 故意把两个区块的 order 设成相同——发生什么?(DSH 的答案:顺序不稳定是配置错误,加载期报错)
  • cwd 传不同的值,确认 {{cwd}} 正确渲染

观察重点:order 为什么是显式数字而不是注册顺序?——注册顺序是插件加载的偶然产物,不该决定模型看到的顺序。

以下内容基于 packages/core/system-prompt 的核查。DSH 的系统提示词组装器就是你这个模式的规范实现:

一、区块(PromptSection)

  • ctx.systemPrompt.section(section) 注册区块;order 控制排序(你的 order 字段与之一致)。
  • 内置区块:固定身份开启器 You are an AI agent powered by DeepSeek Harness.(order -100,可关闭)、部署 persona(deployment:persona,order 0)、运行时上下文。
  • 作用域:agent.ctx 注册的区块只属于那个 Agent,可遮蔽全局 persona——s18 预设用它换身份。

二、命名变量

DSH 支持 {{model}} / {{cwd}} 等模板变量,由已注册的变量表严格校验(完整的 {{...}} 组必须命中变量,否则报错)——比你的 / 正则可替换严格得多,避免拼写错误静默通过。

三、装配瀑布

system-prompt/assemble 是一个 waterfall 事件:监听者可以改写最终组装结果,返回的组装物是权威的。这允许特殊部署完全接管系统提示词。

你的最小实现 DSH 的真实实现
sections 数组 + 手写 assemble 带作用域的注册表 + 每 step 组装一次 + waterfall 扩展
render 正则替换 命名变量表严格校验
工具描述手动拼进区块 toolOrder 显式排序 + schema 自动汇入(s02)

一句话:系统提示词是"策略、工具、技能、上下文的生成产物"——组装器让每个插件贡献自己的部分,而不用理解整体。