Skip to content

系统指令 (System Instructions)

上下文视角:系统指令是注入每个 API 请求的“行为基准”——它为 Agent 设定了身份、规则和目标,是 LLM 收到的第一份、也是优先级最高的上下文。

它是如何工作的

上一节说了,Agent 负责编排上下文。系统指令就是 Agent 在每次 API 请求中最先注入的那份上下文。

你打字之前,它就已经在了。

SYSTEM INSTRUCTIONS "The First Principle" Instructions.md DO: Define Role Set Tone Guide Output AVOID: Negatives "Don't do X..." Strategy: "Frame the Path" Context Stack SYSTEM PROMPT (Injected First) History (Noise) USER INPUT Aligned MODEL Behaves as defined
SYSTEM INSTRUCTIONS "The First Principle" Instructions.md DO: Define Role Set Tone Guide Output AVOID: Negatives "Don't do X..." Strategy: "Frame the Path" Context Stack SYSTEM PROMPT (Injected First) History (Noise) USER INPUT Aligned MODEL Behaves as defined

── 第 1 轮 ──

json
// → REQUEST(agent → LLM API)
{
  "system": "你是一个 AI 编程助手。遵循 Google TypeScript 风格指南。只编写或修改代码,不回答与编程无关的问题。",
  "messages": [{ "role": "user", "content": "帮我写一个斐波那契函数" }]
}
json
// ← RESPONSE(LLM API → agent,SSE 流)
{
  "role": "assistant",
  "content": "function fibonacci(n: number): number { ... }"
}

── 第 2 轮 ──

json
// → REQUEST(agent → LLM API)
{
  "system": "你是一个 AI 编程助手。遵循 Google TypeScript 风格指南。只编写或修改代码,不回答与编程无关的问题。",
  "messages": [
    { "role": "user", "content": "帮我写一个斐波那契函数" },
    { "role": "assistant", "content": "function fibonacci(n: number)..." },
    { "role": "user", "content": "加上 JSDoc 注释和输入验证" }
  ]
}

messages 变长了,但 system 一字不变

对话跑 50 轮,它还是一模一样。系统指令不是对话的一部分——是对话的规则

它包含什么

  • 身份:告诉 LLM 它扮演什么角色
  • 能力:告诉 LLM 它能做什么操作
  • 规则:必须遵守的约束和规范
  • 目标:它的工作目标是什么
  • 输出格式:结果用什么格式呈现

这些把通用 LLM 变成你的专属工具。

谁写的?

系统指令有三个来源:

  1. Agent 开发者:他们编写了大部分基础指令,定义了 Agent 的核心能力和行为模式。大多数情况下你改不了这部分。

  2. 你 (用户):大多数 Agent 工具都提供了自定义指令的入口,例如 CLAUDE.mdAGENTS.md 或工具内的配置选项。

  3. Agent 在对话中生成/更新:Agent 和 LLM 自己也能成为作者。这通常在两种情况下发生:

    • 用户直接指示:“把这个约定加到规则文件里去。”
    • 系统指令本身授权 Agent 在特定条件下更新自己:“如果发现新的代码约定,就把它追加到指令文件。”

    这让系统指令从一份静态配置,演变成一份可以随着项目进展而“活”起来的文档。

用户自定义指令是你手里最有效的手段

用户自定义的系统指令,是你能用来影响 Agent 行为的最有效手段

你不需要改 agent 的内核代码,也不需要理解它的内部实现。

用自然语言写清楚你的规则和期望,就能全局改变 Agent 的行为。

System instructions: injected first, unchanged every round Two request envelopes show the system prompt staying identical while messages grow across rounds. A user customization pill attaches at the system layer, illustrating why system instructions are a high-leverage handle. System instructions are the baseline, every round Messages grow with the conversation — the system prompt stays identical (and is injected first). User custom instructions (highest leverage) → REQUEST (ROUND 1) system base rules + your custom instructions "You are an AI coding assistant…" Injected first • highest priority messages[] [ user: "…" ] Runtime context (grows every round) → REQUEST (ROUND 2) system exactly the same string "You are an AI coding assistant…" Unchanged across rounds messages[] [ user, assistant, user… ] Longer history, more runtime context system unchanged Rule of thumb: if it should apply to every session, put it in system instructions. If it is task-specific, inject it at runtime.
System instructions: injected first, unchanged every round Two request envelopes show the system prompt staying identical while messages grow across rounds. A user customization pill attaches at the system layer, illustrating why system instructions are a high-leverage handle. System instructions are the baseline, every round Messages grow with the conversation — the system prompt stays identical (and is injected first). User custom instructions (highest leverage) → REQUEST (ROUND 1) system base rules + your custom instructions "You are an AI coding assistant…" Injected first • highest priority messages[] [ user: "…" ] Runtime context (grows every round) → REQUEST (ROUND 2) system exactly the same string "You are an AI coding assistant…" Unchanged across rounds messages[] [ user, assistant, user… ] Longer history, more runtime context system unchanged Rule of thumb: if it should apply to every session, put it in system instructions. If it is task-specific, inject it at runtime.

想让它遵循团队独特的代码风格?写进系统指令。 想让它避免接触某个敏感模块?写进系统指令。 想让它在每次提交前都执行特定检查?写进系统指令。

比如你的指令文件里可以这么写:

markdown
## 代码风格

- 所有函数必须有 JSDoc 注释
- 变量命名用 camelCase,常量用 UPPER_SNAKE_CASE

## 安全边界

- 不要读写 .env 和 credentials/ 目录

## 工作流

- 修改代码后必须执行测试,全部通过才算完成

这些用户层面的指令通常会被追加到 Agent 的基础指令之后,或者通过特定语法覆盖默认行为。

精心打磨的几十行指令,投入产出比极高——远超你花大量时间去摸索 Agent 的默认行为。

项目里已有的工程约束——tsconfig strict、lint 规则、pre-commit hooks——对人和 Agent 都有价值,只是方式不同。人写代码时,这些检查帮你守住底线;Agent 生成代码量更大,每一行都过同一套关卡,效果更显著。你编码一次的规则,每一行生成的代码都受益。

写好指令的两个方向

想让 Agent 好用,别总想着怎么"管住"它,多想想怎么让它"融入"你的工作流。

方向一:画路,别砌墙

想禁止 Agent 删文件,别跟它说"不要删文件"。否定式指令容易被模型忽略,正面描述期望行为效果更好。

  • ❌ "不准用 delete_file。"
  • ✅ "只在用户明确要求'删除'时,才用 delete_file。"
  • ✅✅ "调用 delete_file 前,必须检查用户输入是否包含'删除'二字。不含则拒绝。"

给它画一条清晰的路,而不是把所有的坑都围起来。

方向二:把它当新同事,不是新 linter

如果你的指令文件里只有"用 tabs 不用 spaces"这种代码风格规则,那你只是多了个 linter。

把它当成一个新来的同事,告诉他"我们是怎么做事的":

  • 我们修 bug 的流程是"复现 -> 测试 -> 提交",不是"看日志 -> 瞎猜 -> 等用户反馈"。
  • 我们希望你是个能提出异议的队友,不是只会执行命令的机器。如果我的要求可能搞坏架构,直接拒绝,然后给出你的替代方案。

指令是份对齐预期的协议。

指令是可维护资产

别把你的系统指令当成一次性的便条。它是一份活的文档,是需要像代码一样维护的资产

你可以把项目级指令文件理解成"组织教训库"——每一条规则背后都是一次真实的踩坑教训。

但指令文件不只是踩坑记录。那些经过反复验证、沉淀下来的成功做法——同样写在里面。

Instructions as assets: write positive, govern changes Two panels. Left: write instructions as positive invariants (conditions + checks) rather than broad negative bans. Right: treat the instruction file like code—version it in Git, review changes via PR, and iterate based on runtime feedback. Instructions are a maintainable asset Write positive invariants • Version changes • Review like code • Iterate from runtime feedback WRITE: POSITIVE INVARIANTS Make constraints conditional and testable (avoid broad negations). Negative ban "Don't do X." Positive invariant "Only do X when condition Y." Best: write it as a check if not Y → refuse; else → proceed GOVERN: VERSION + REVIEW + ITERATE Team-level changes should be traceable and reviewable. Git versioned file PR review who is affected? Merge new baseline Runtime feedback drift, conflicts, incidents Update instructions add rule + rationale repeat
Instructions as assets: write positive, govern changes Two panels. Left: write instructions as positive invariants (conditions + checks) rather than broad negative bans. Right: treat the instruction file like code—version it in Git, review changes via PR, and iterate based on runtime feedback. Instructions are a maintainable asset Write positive invariants • Version changes • Review like code • Iterate from runtime feedback WRITE: POSITIVE INVARIANTS Make constraints conditional and testable (avoid broad negations). Negative ban "Don't do X." Positive invariant "Only do X when condition Y." Best: write it as a check if not Y → refuse; else → proceed GOVERN: VERSION + REVIEW + ITERATE Team-level changes should be traceable and reviewable. Git versioned file PR review who is affected? Merge new baseline Runtime feedback drift, conflicts, incidents Update instructions add rule + rationale repeat

踩坑教训告诉 Agent 什么路走不通,验证过的好做法告诉它应该怎么走。 两者合起来,才是完整的团队智慧。

"画路别砌墙"针对的是指令的写法——用正面描述替代否定句。这里说的"踩坑教训"是指令的内容来源——记录团队真实犯过的错,把经验固化成规则。两者不矛盾:内容来自踩坑,写法要正向引导。

  • 版本化:用 Git 管理你的指令文件,追踪每次变更。
  • Review:让同事 review 你的指令,就像 review 代码一样。
  • 迭代:根据 Agent 的行为反馈,持续优化和追加新规则。

一份好的系统指令集,是你所在项目知识沉淀的一部分。

团队级指令治理

一个人用,指令迭代就行。一个团队用,就需要上升到治理。

  • 指令文件必须进 Git。 后来回看时,git blame 能告诉你是谁、为什么加了这条规则。不在版本控制里的指令,出了问题没人能追溯。
  • 变更必须 Review。 一行指令的变更,威力不亚于改一行核心代码。一个人加了"永远用 tabs",另一个人加了"永远用 spaces",冲突要到下个会话才炸。指令变更应该走 PR,让团队知道"这条规则会影响谁"。
  • 项目变,指令跟着变。 技术栈升级了、架构调整了、依赖换了——指令里相关的规则也得同步更新。这不是"有空再说",这是"下一个会话就会基于过时的规则做决策"。

本节小结

  • 上下文流动:系统指令是上下文的"静态层"——每轮请求都原样存在,为后续所有动态上下文(用户输入、工具返回)提供稳定的行为基准。
  • 风险:Agent 基础指令和你的自定义指令冲突时,LLM 行为会变得不可预测。Agent 表现怪异?先查指令冲突。
  • 可审计性:系统指令完全可读——打开 Agent 的默认指令和你自己的自定义指令,就能精确知道什么在驱动它的行为。

下一节看工具——工具定义和返回值如何进入同一个上下文回路。