Skip to content

ZH Course 05 System Prompt Builder

lloydzhou edited this page Jun 1, 2026 · 2 revisions

系统提示词构建器

System prompt 是一个对缓存敏感的协议面。很小的字节差异也可能降低 provider KV cache 复用,所以 section 统一通过 helper 追加。

util_append_section() {
    local __outvar="$1" tag="$2" content="$3" name="${4:-}" wrapped
    [[ -n "$content" ]] || return 0
    if [[ -n "$name" ]]; then
        wrapped=$(printf '<%s name="%s">\n%s\n</%s>' "$tag" "$(util_json_escape "$name")" "$content" "$tag")
    else
        wrapped=$(printf '<%s>\n%s\n</%s>' "$tag" "$content" "$tag")
    fi
    printf -v "$__outvar" '%s%s\n' "${!__outvar}" "$wrapped"
}

实际 Section 顺序

agent_build_prompt 按固定顺序追加 section:

util_append_section output "agent-identity" "$agent_identity"
util_append_section output "environment" "$environment"
util_append_section output "rules" "$core_rules"
util_append_section output "using-your-tools" "$tool_guidance"
util_append_section output "sub-agent-guidance" "$sub_agent_guidance"
util_append_section output "todo-guidance" "$todo_guidance"
util_append_section output "plan-lifecycle-guidance" "$plan_lifecycle_guidance"
util_append_section output "instruction-files" "$instruction_files"
util_append_section output "skill-index" "$skill_index"
util_append_section output "selected-skills" "$selected_skills"
util_append_section output "current-plan" "$plan" "${PLAN_FILE:-}"
util_append_section output "context-snapshot" "$stable_context"
util_append_section output "output-language" "$output_language_reaffirm"

所以实际顶层 prompt section 是:

Section 作用
agent-identity 运行时身份,会按 locale 本地化
environment language、cwd、home、platform、shell
rules 简洁输出、精确编辑、失败说明等核心规则
using-your-tools 通用工具使用规则
sub-agent-guidance delegation、fork mode 和 result handling rules
todo-guidance 什么时候以及如何使用 TodoWrite
plan-lifecycle-guidance draft / confirm / execute 的 plan 协议
instruction-files global 和 project instruction-file sections
skill-index 可用 skill 名称和摘要
selected-skills 显式选择的 skill 全文
current-plan 已确认 plan,并带 PLAN_FILE 名称
context-snapshot 长会话压缩摘要
output-language locale 输出语言重申

顺序和格式都是契约的一部分。Bash、C、Go、Rust 在同一个 session 状态下应该生成相同的 prompt bytes。

嵌套的 Instruction 和 Skill Section

有些顶层 section 里还会包含子 section。Instruction files 会被收集为多个 instruction-file:

util_build_instructions_section() {
    local output="" global_file project_file global_content project_content
    global_file=$(util_find_instruction_file "${HOME}/.bash-agent" 2>/dev/null || true)
    project_file=$(util_find_instruction_file "${PWD:-$(pwd)}" 2>/dev/null || true)

    if [[ -n "$global_file" ]]; then
        global_content=$(<"$global_file") || return 1
        util_append_section output "instruction-file" "$global_content" "global"
    fi
    if [[ -n "$project_file" ]]; then
        project_content=$(<"$project_file") || return 1
        util_append_section output "instruction-file" "$project_content" "project"
    fi
    printf '%s' "${output%$'\n'}"
}

显式选择的 skills 也会作为多个 skill 子 section 放进 selected-skills。

Plan Draft 与 Cache

plan.draft 存在的原因是:修改已确认 plan 会改变 system prompt。草稿阶段不进入 prompt,直到确认后再切换。

store_plan_confirm() {
    [[ -n "$PLAN_DRAFT_FILE" && -s "$PLAN_DRAFT_FILE" ]] && {
        mv "$PLAN_DRAFT_FILE" "$PLAN_FILE"
        : > "$PLAN_DRAFT_FILE"
        return 0
    }
    return 1
}

这让 plan confirm 成为一个明确的 cache boundary。

下一章

动态压缩与长会话 解释稳定 prompt 结构和 session stats 如何支撑长会话。

Clone this wiki locally