DeepSeek Harness System Prompt:Prompt Section、变量、工具 schema 如何组装
JotaroRD

模块定位

packages/core/system-prompt 负责每个 step 的系统提示组装。它不是简单字符串拼接器,而是一个 registry:插件注册 section、runtime context、tool schema provider 和变量,loop 每次请求前按当前 agent scope 组装。

源码入口:

  • packages/core/system-prompt/src/index.ts
  • packages/core/tools/src/index.ts
  • packages/context/*
  • docs/subsystems/system-prompt.md

组装输入

一次 prompt assembly 包含:

  • 静态 harness identity。
  • deployment persona。
  • 插件注册的 prompt sections。
  • runtime contexts。
  • tool schemas。
  • prompt variables。
  • system-prompt/assemble waterfall 的最终变换。
1
2
3
4
5
6
7
8
flowchart LR
A["sections"] --> F["PromptAssembly"]
B["runtime contexts"] --> F
C["tool schemas"] --> F
D["variables"] --> F
E["agent scope"] --> F
F --> G["renderPrompt()"]
F --> H["adapter tool field"]

Section 机制

插件通过:

1
2
3
4
5
ctx.systemPrompt.section({
name,
order,
text,
})

注册 section。Section 按 order 升序拼接。常见 order band:

  • -100:harness identity。
  • 0:deployment persona。
  • 100–199:tool guidance。

同一 scope 下 section name 不能重复。Agent scope 可以 shadow global section。

complete: true 是特殊机制:有效 complete section 会成为完整 system prompt,压过普通 sections。这个能力适合兼容某些部署,但也危险,因为它需要保证 Code Mode、工具协议、runtime context 等仍然一致。

Prompt Variables

变量形如:

1
2
{{model}}
{{cwd}}

插件通过 ctx.systemPrompt.variable(name, provider) 注册变量。渲染时严格检查:

  • 未知变量报错。
  • 已注册但无值报错。
  • malformed braces 报错。

这是 fail loud 设计。它宁可让一次 turn 失败,也不把坏 prompt 发给模型。

Tool Schemas 是 Prompt 的一部分

虽然 provider wire 协议里 tool schemas 往往和 system prompt 分开发送,但在 Harness 里它们同属一次 PromptAssembly。原因很直接:模型被告知“能做什么”必须和 system prompt 一致。

ToolRuntime 会自动注册 tool schema provider。工具 restriction、agent-scoped shadow、Code Mode presentation 都会影响当前 agent 看到的工具 schema。

toolOrder

toolOrder 是配置级工具排序。它要求列表中有一个 '<unlisted-tools>' rest entry。

为什么要这个配置?因为 tool schema 顺序会影响 prompt 和 KV cache。靠插件加载顺序不稳定,显式排序更可控。

错误配置会 fail loud:

  • 没有 rest entry。
  • rest entry 多于一个。
  • 重复工具名。
  • 配置中列出的工具不存在。

Runtime Context

ctx.systemPrompt.context() 注册动态上下文。它每次 assembly 都会被调用,产生带 source 的 runtime context snapshot。includeRuntimeContext: false 或 scoped suppressor 可以禁用 runtime context,但不会禁用底层服务和策略。

典型 runtime context:

  • workspace instructions。
  • 当前时间。
  • tmux context。
  • session reference。

system-prompt/assemble

这是一个 waterfall。Listener 可以修改或替换 assembly。它是非常强的扩展点,也因此要谨慎:如果替换 tools 或 sections,要保证工具协议仍然可用。例如 Code Mode 需要 run_code schema 和 SDK section 一致。

常见坑

第一,prompt section 和 tool guidance 是不同东西。限制工具不会自动删除某个独立 prompt section。

第二,变量没有 escape 语法。需要输出字面 {{...}} 时要小心。

第三,section order 相同会按注册顺序 tie-break,这不是稳定设计来源。

第四,完整覆盖 system prompt 后,要自己维护工具协议。

继续读源码

  • packages/core/system-prompt/README.md
  • docs/subsystems/system-prompt.md
  • packages/context/agent-instructions/README.md
  • packages/core/tools/README.md#code-mode