# 系统提示词与指令文件

> 按模型家族挑选提示词模板，环境信息、Skills 与 MCP 说明如何拼接，AGENTS.md 等指令文件的发现规则，以及 plan 模式提醒的两种注入方式。

- 作者：David（道雾轩）
- 专栏：OpenCode 源码解读（https://daiw.org/manual/opencode.md）
- 最后更新：2026-09-15
- 原文：https://daiw.org/manual/opencode/system-prompt
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

每一步发给模型的 system 由两处代码合作拼成：[主循环](https://daiw.org/manual/opencode/prompt-loop)在 `runLoop` 里准备动态部分，LLM 层的 `llm/request.ts` 再把模型家族模板放到最前面。

## 拼装顺序

`packages/opencode/src/session/llm/request.ts:58`：

```ts
  const system = [
    [
      ...(input.agent.prompt ? [input.agent.prompt] : SystemPrompt.provider(input.model)),
      ...input.system,
      ...(input.user.system ? [input.user.system] : []),
    ]
      .filter((x) => x)
      .join("\n"),
  ]
```

也就是：

1. agent 自带的 `prompt`；没有时按模型家族选模板。explore、compaction、title 这类内置 agent 和自定义 agent 一旦写了 `prompt`，家族模板就整个不用了。
2. `runLoop` 传入的 `input.system`：环境信息、指令文件、MCP 说明、Skills 列表；要求结构化输出时再加一段强制使用 `StructuredOutput` 工具的说明。
3. 这条 user 消息自带的 `system` 字段。

三者用换行拼成**一个** system 字符串。插件可以通过 `experimental.chat.system.transform` 往数组里追加内容；追加后超过两块时，首块之后的内容会被合并成第二块（`request.ts:74`）。顺带一提，`ProviderTransform` 的 `applyCaching` 只给前两条 system 消息和最后两条非 system 消息打缓存标记（`packages/opencode/src/provider/transform.ts:358`）。

## 模型家族模板

`SystemPrompt.provider`（`packages/opencode/src/session/system.ts:28`）对 `model.api.id` 做子串匹配，先中先得：

| 匹配条件 | 模板 | 特点 |
| --- | --- | --- |
| 含 `muse` | `meta.txt` | 把 `{{MODEL_NAME}}` 替换成 Muse Glimmer 或 Muse Spark |
| 含 `gpt-4`、`o1`、`o3` | `beast.txt` | 强调持续迭代、大量联网调研 |
| 含 `gpt` 且含 `gpt-6` | `gpt-astra.txt` | 讲明 harness 的约定 |
| 含 `gpt` 且含 `codex` | `codex.txt` | 编辑约束与 apply_patch |
| 其余 `gpt` | `gpt.txt` | 务实的资深工程师人设 |
| 含 `gemini-` | `gemini.txt` | Core Mandates 条目式规范 |
| 含 `claude` | `anthropic.txt` | 自称“the best coding agent on the planet” |
| 含 `trinity` | `trinity.txt` | 与默认模板相近的简洁风格 |
| 含 `kimi` 或 Moonshot 系提供方 | `kimi.txt` | 通用 agent 人设 |
| 其他 | `default.txt` | 极简，要求“fewer than 4 lines” |

顺序本身就是规则：`gpt-4o` 先命中 `gpt-4` 走 `beast.txt`，轮不到 `gpt.txt`。目录里还有 `copilot-gpt-5.txt` 与 `plan-reminder-anthropic.txt` 两个文件，全仓库没有代码引用它们。

模板里有一句值得单独拎出来，出自 `gpt-astra.txt`：

```text
- `<system-reminder>` blocks are harness instructions, not user-authored content. Read and follow them.
```

OpenCode 往上下文里塞的各种提醒（下文的 plan 模式、读文件时附带的就近指令）都包在 `<system-reminder>` 里，这句话告诉模型如何对待它们。

## 环境信息、Skills 与 MCP

环境信息块（`system.ts:75`，删减后）：

```ts
          [
            `You are powered by the model named ${model.api.id}. The exact model ID is ${model.providerID}/${model.api.id}`,
            `Here is some useful information about the environment you are running in:`,
            `<env>`,
            `  Working directory: ${ctx.directory}`,
            `  Workspace root folder: ${ctx.worktree}`,
            `  Is directory a git repo: ${ctx.project.vcs === "git" ? "yes" : "no"}`,
            `  Platform: ${process.platform}`,
            `  Today's date: ${new Date().toDateString()}`,
            `</env>`,
          ].join("\n"),
```

配置了带描述的项目引用时，后面再跟一个 `<available_references>` 块，列出各引用的名称、路径与描述。

Skills 块只在 agent 的权限没有禁用 `skill` 时出现，列出可用 Skills 的详细版本。注释解释了为什么详细版放在这里（`system.ts:115`）：

> the agents seem to ingest the information about skills a bit better if we present a more verbose version of them here and a less verbose version in tool description, rather than vice versa.

MCP 说明把各服务器声明的 `instructions` 包进 `<mcp_instructions>`，每台服务器一个 `<server>` 节点；工具被权限全部禁用的服务器会被跳过。

## 指令文件

`packages/opencode/src/session/instruction.ts` 负责三类来源：

| 来源 | 规则 |
| --- | --- |
| 全局 | 全局配置目录的 `AGENTS.md`，没有再找 `~/.claude/CLAUDE.md`，只取第一个存在的 |
| 项目 | 依次尝试 `AGENTS.md`、`CLAUDE.md`、`CONTEXT.md`（已弃用），从当前目录逐层向上找到 worktree 根 |
| 配置 `instructions` | 路径或 glob（相对路径同样逐层向上匹配，支持 `~/`），以及 http(s) URL（5 秒超时，失败忽略） |

项目级规则的注释是（`instruction.ts:122`）：

> The first project-level match wins so we don't stack AGENTS.md/CLAUDE.md from every ancestor.

对照代码：第一个在任一层找到的文件名胜出，只要有 `AGENTS.md`，`CLAUDE.md` 就不会再被加载；但同名文件在各层的匹配会全部加入。设置 `OPENCODE_DISABLE_CLAUDE_CODE` 或 `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` 会把 `CLAUDE.md` 从全局与项目两份清单里去掉；`OPENCODE_DISABLE_PROJECT_CONFIG` 则跳过项目级查找。每份内容以 `Instructions from: <路径>` 开头拼进 system。

还有一类**就近指令**。Read 工具读文件时调用 `Instruction.resolve`：从被读文件所在目录向上走到当前工作目录（不含），把沿途尚未加载过的 `AGENTS.md` 等文件附在读取结果末尾的 `<system-reminder>` 里（`packages/opencode/src/tool/read.ts:355`），每条 assistant 消息内同一文件只附一次。子目录里的约定因此只在模型真正读到那片代码时才进入上下文。

## plan 模式提醒

`reminders.ts` 在每一步组装请求前运行，行为取决于 `OPENCODE_EXPERIMENTAL_PLAN_MODE` 开关。

默认模式下：当前 agent 是 `plan` 时，在最后一条 user 消息末尾追加 synthetic 文本 `plan.txt`；历史里有 plan 的回复而当前 agent 是 `build` 时，追加 `build-switch.txt`。两者都只 `push` 进内存里的 Part 列表、不写库，所以每一步重读历史后都会重新追加一次。

实验模式下提醒会持久化：从 plan 切到其他 agent 时写入 build-switch 提醒，若计划文件已存在，再附一句要求按计划执行；刚进入 plan 时写入 `plan-mode.txt`，把其中的 `${planInfo}` 替换成计划文件的状态说明。计划文件路径由 `Session.plan` 决定：有版本控制的项目放在 `.opencode/plans/` 下，文件名是创建时间加 slug；否则放在数据目录的 `plans` 下。

`build-switch.txt` 全文只有一段：

```text
<system-reminder>
Your operational mode has changed from plan to build.
You are no longer in read-only mode.
You are permitted to make file changes, run shell commands, and utilize your arsenal of tools as needed.
</system-reminder>
```

除此之外，最大步数提示见[主循环](https://daiw.org/manual/opencode/prompt-loop)，压缩后的续跑提示见[上下文压缩](https://daiw.org/manual/opencode/compaction)。

下一篇：[上下文压缩](https://daiw.org/manual/opencode/compaction)——上下文快满时，OpenCode 如何修剪、摘要并续上工作。
