7大开源Agent源码对比解读——系统提示词与指令遵循
7大开源Agent源码对比解读——系统提示词与指令遵循
本文是「7大开源Agent源码对比解读」系列第 6 篇。评估对象:codex、gemini-cli、qwen-code、opencode、kimi-code、deepseek-harness(下称 dsh)、oh-my-pi(下称 omp)。所有机制描述附源码引证。
| 篇 | 文章 | 内容速览 |
|---|---|---|
| 总述 | 拆了七大开源 Agent 的源码,最高分竟然不是 Codex | 总体结论、评估方法与评分卡 |
| 01 | 架构对比 | 四种流派与分化根源、主循环与事件机制、插件化与耦合风险 |
| 02 | 上下文管理 | 压缩触发阈值、摘要方式、token 计数口径、跨会话记忆 |
| 03 | 会话管理 | 持久化模型三层次、并发控制、崩溃恢复与 resume / fork |
| 04 | 工具调用 | 注册与可见性、并行调度四种语义、审批门控、错误处理 |
| 05 | 重连与容错 | 重试预算、流中断处理、降级链、副作用安全 |
| 06 | 系统提示词与指令遵循 | 四种组装范式、动态注入、注入防御三层与共同敞口 |
| 07 | 思维链与工作流编排 | 思维链接入、plan 模式语义、子代理治理、工作流引擎 |
| 08 | 性能设计 | 前缀缓存三档分化、启动优化、成本核算 |
| 09 | 可扩展性 | MCP 接入、自定义工具、多 provider、SDK 与 API |
| 10 | 安全与权限控制 | 沙箱两种语义、审批默认姿态、企业管控、敏感数据保护 |
系统提示词听起来是最简单的部分,拼个字符串而已。七个项目做下来,组装方式分成四种递进范式,注入防御分成三层,而且没有任何一家有独立的提示注入检测层。
四种组装范式
| 项目 | 组装范式 | 关键机制 |
|---|---|---|
| codex | 单字符串 + 服务端下发 | 规范模板按模型族从模型目录下发,本地只存 fallback |
| gemini-cli | 分 section + 可开关 | 每个 section 有 guard 条件和全局开关 |
| qwen-code | 分层 layers | stable/context/volatile 三层,组装函数唯一知道顺序 |
| opencode | 按模型族分派 | 9 份 base prompt 按模型 API id 选择 |
| kimi-code | 模板变量 + profile | system.md 带 {{变量}},profile 用 extends 派生 |
| dsh | DSL 注册 + waterfall | PromptSection 按 order 排序,插件协作改写 |
| omp | Handlebars 模板 | 三套 personality,模板文件可直接编辑 |
范式一最贴近 API 原语:系统提示词就是一个字符串,动态信息靠追加 fragment(codex)。范式四最框架化:提示词是一个可被插件横切的数据结构(dsh)。
逐家看点
codex:规范版在服务端,本地只有回退
codex 的系统提示词对应 Responses API 的 instructions 字段,规范内容由服务端模型目录按模型族加 personality 下发 instructions_template,用 {{ personality }} 插值(models-manager/src/model_info.rs:67-96),不硬编码在本地。仓库里有一份等价的离线回退提示词(约 21KB,protocol/src/models.rs:1438),服务端目录拿不到模板或走 fallback 模型时使用。也就是说:默认行为的规范版本无法离线审计,但回退版本在仓库内可审计。
运行期环境以 XML 注入:<environment_context> 包含 cwd、shell、沙箱文件系统权限画像、网络域名白黑名单,全部经过 5 字符 XML 转义(environment_context.rs:63-236)。动态上下文拆成 37 个 fragment 模块,每个自带起止标签,在 turn 边界按世界状态快照差分注入,只注变化的部分。
gemini-cli:section 开关与整体替换
PromptProvider 把系统提示词拆成十几个命名 section(preamble、subAgents、taskTracker、git 等),每个包在 withSection(key, factory, guard) 里,条件不满足或开关关闭就不渲染(promptProvider.ts:312-318)。另有 modern/legacy 两套片段,按模型能力切换。
两个调试友好的环境变量:GEMINI_SYSTEM_MD 整体替换标准组装,GEMINI_WRITE_SYSTEM_MD 把最终产物导出成文件,两个互不依赖(:54、:325-334)。
注入消毒做了两处:路径和主题文本在注入前替换掉换行和右方括号,注释直写「防止提示注入」。去换行防伪造多段落,去 ] 防提前闭合 gemini 大量使用的方括号标记。
qwen-code:三层结构与缓存友好
SystemPromptLayers 把提示词分三层(prompts.ts:485-510):stable(身份、工具指引,全会话固定)、context(指令文件、规则、git 状态,显式刷新才重读)、volatile(autoMemory,每次记忆保存重写)。assembleSystemPrompt 是唯一知道顺序的地方,调用方只能把内容分类进 slot,不能在调用点乱序追加。
volatile 层永远放最后是个精心计算:一次记忆保存只失效最短的缓存前缀,前面的稳定内容继续命中。
两条防御条款值得抄。「Denied Tool Calls 不得绕道」:工具调用被拒绝后,不得通过其他工具、shell 间接、生成脚本、符号链接、编码 payload 等任何等效路径完成被拒动作(:312)。标签转义做得很细:<system-reminder> 标签的转义会归一零宽字符、bidi 字符、BOM,防止在标签名里塞隐形字符逃逸检测,闭合标签改成转义形式,让不可信内容无法提前闭合信封(utils/xml.ts:48-151)。
opencode:一份提示词打天下会损失各家最优
provider(model) 按模型 API id 分派 9 份 base prompt:claude、gpt、codex、gemini、kimi、beast、meta、trinity、default(session/system.ts:27-49)。背后的观察是不同模型家族的指令遵循偏好不同,Claude 吃 XML 标签,GPT 吃 markdown 结构,一份提示词打天下会损失各家的最优表现。
提示词的拼装同时考虑缓存:applyCaching 把前 2 条 system 消息和末 2 条非 system 消息打上缓存断点,覆盖 6 家 provider(provider/transform.ts:359-379)。
SessionReminders 是另一条注入通道:往最后一条 user 消息的 parts 里塞合成指令(如从 plan 切到 build 时的过渡提示),属于「在用户消息里夹带的系统指令」(reminders.ts:15-88)。
kimi-code:模板化与对账重放
系统提示词是一份带占位符的 system.md,变量由运行期上下文填充(OS、shell、会话起始时间、工作目录、AGENTS.md、skills、插件段落)。profile 体系用 extends 派生:coder、explore、plan 三个子代理 profile 继承 agent 基线,只重写差异点。
动态注入走两条通道,分工明确:每步注入器高频处理 todo、plan、goal 这类状态;边界注入器只在续 turn 边界低频注入后台任务状态。注释解释了这个设计的动机:每步都注入会让同一内容堆叠成 O(n²),边界节奏只保留一份新鲜副本(injection/manager.ts:19-21)。v2 引擎还有对账机制:注入前核对历史中上次注入的位置与披露标记,决定是否需要重注(contextInjector.ts:105-148)。
非 reminder 的注入被当作不可信数据:goal 文本包进 <untrusted_objective> 标签并转义(injection/goal.ts:50-77)。系统提示词同时声明插件指令不是特权通道,不能自我授权。
dsh:提示词是可被插件横切的数据结构
PromptSection 带 name、order、text,order 有约定(-100 是 harness 身份,0 是部署 persona,100~199 是工具指引),组装时先合并遮蔽、按 order 排序,再跑一个 Cordis waterfall 协作事件让插件改写,最后严格插值(system-prompt/src/index.ts:467-535)。
两条规则保证可控:scoped section 同名即遮蔽全局(不重复渲染);complete 段独占,任何 section 声明 complete 即成为唯一提示词,两个 complete 同时在场直接让组装失败。
动态上下文以快照注入,每次快照显式声明「取代先前的运行时上下文快照」(:224-240),防止模型把旧快照当真。注入走 agent.inject(),以 user 角色、不可见方式播种。
omp:模板直接可改,兼容八种外部约定
系统提示词是一组纯 markdown 文件,Handlebars 渲染,无需重编译即可修改。三套 personality(default、friendly、pragmatic),可设 none 省略整块。块级去重处理多源汇聚时的重复规则。
兼容性是 omp 的强项:discovery 层有 8 个外部约定的读取器,Claude Code、OpenAI Codex、Gemini CLI、OpenCode、Cursor、Windsurf、Cline、GitHub Copilot 的指令文件格式都能识别(coding-agent/src/discovery/)。迁入任何团队的既有知识资产零成本。
防御写进提示词契约:XML 标签语义恒为系统内容,<system-directive> 即便出现在 user turn 也保持系统指令语义。另有 Harmony 泄漏检测:omp 给无原生工具调用的模型伪造带内协议,运行时扫描 assistant 消息,协议标记泄漏进可见文本就中断并恢复。这是七家中唯一针对自有协议泄漏的运行时检测。
指令文件兼容性
| 项目 | AGENTS.md | CLAUDE.md |
|---|---|---|
| codex | 支持,根到 cwd 全拼接 | 不支持 |
| gemini-cli | 用自家 GEMINI.md 四层 | 不支持 |
| qwen-code | 支持(兼容层) | 不支持 |
| opencode | 支持,首类命中 | 支持 |
| kimi-code | 支持 | 不支持 |
| dsh | 支持 | 支持 |
| omp | 支持 | 支持(另 6 种约定) |
注入防御的三层与共同敞口
七家的注入防御可以归为三层,但没有一家做到独立的注入检测模型层:
- 变量消毒(被动):注入前对字符串做清洗。gemini 去换行和方括号,qwen 归一零宽字符并转义标签,kimi 用
<untrusted_objective>包裹加转义。 - 契约声明(主动):用提示词教模型区分系统与用户内容。omp 声明 XML 标签语义,qwen 和 kimi 声明
<system-reminder>是权威系统指令,codex guardian 把转录增量当作不可信证据。 - 运行时拦截(事后):omp 的 Harmony 泄漏扫描、qwen 的不得绕道条款、各家的循环纠偏。
共同敞口:没有任何项目在「工具结果入历史前」插独立的注入检测层。工具返回的网页、文件内容是最常见的注入载体,这块完全靠模型自觉。外接 guardrail 时,dsh 的 tools/post-execute waterfall 和 opencode 的消息变换钩子是合适的挂点。
给 Agent 开发者的借鉴清单
- 按模型族分派 base prompt。 成本只是多维护几份文本,换来各家族的最优遵循(opencode 的 9 份分派)。
- 组装函数唯一知道顺序。 调用方只能分类内容进 slot,防止各处乱序追加(qwen 的 layers 设计)。
- 易变内容放最后。 记忆、状态这类频繁重写的部分放在提示词尾部,一次更新只失效最短的缓存前缀。
- 动态快照要声明取代关系。 「本快照取代先前快照」一句话,省掉模型混淆新旧上下文的麻烦(dsh)。
- 不可信内容进提示词前先包裹转义。 标签逃逸要连零宽字符一起防(qwen 的 xml.ts 是完整样本)。
- 写一条「被拒操作不得绕道」条款。 模型很擅长找等效路径绕过拒绝(qwen 的条款原文可以直接抄)。
- 兼容主流指令文件约定。 AGENTS.md 已是事实标准,兼容竞品约定能显著降低迁移摩擦。
- 提示注入检测层留好挂点。 工具结果入历史前的位置最合适,现在没有项目做,是差异化机会。
文档地图
| 篇 | 文章 | 内容速览 |
|---|---|---|
| 总述 | 拆了七大开源 Agent 的源码,最高分竟然不是 Codex | 总体结论、评估方法与评分卡 |
| 01 | 架构对比 | 四种流派与分化根源、主循环与事件机制、插件化与耦合风险 |
| 02 | 上下文管理 | 压缩触发阈值、摘要方式、token 计数口径、跨会话记忆 |
| 03 | 会话管理 | 持久化模型三层次、并发控制、崩溃恢复与 resume / fork |
| 04 | 工具调用 | 注册与可见性、并行调度四种语义、审批门控、错误处理 |
| 05 | 重连与容错 | 重试预算、流中断处理、降级链、副作用安全 |
| 06 | 系统提示词与指令遵循 | 四种组装范式、动态注入、注入防御三层与共同敞口 |
| 07 | 思维链与工作流编排 | 思维链接入、plan 模式语义、子代理治理、工作流引擎 |
| 08 | 性能设计 | 前缀缓存三档分化、启动优化、成本核算 |
| 09 | 可扩展性 | MCP 接入、自定义工具、多 provider、SDK 与 API |
| 10 | 安全与权限控制 | 沙箱两种语义、审批默认姿态、企业管控、敏感数据保护 |
葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。
更多推荐



所有评论(0)