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分层 layersstable/context/volatile 三层,组装函数唯一知道顺序
opencode按模型族分派9 份 base prompt 按模型 API id 选择
kimi-code模板变量 + profilesystem.md 带 {{变量}},profile 用 extends 派生
dshDSL 注册 + waterfallPromptSection 按 order 排序,插件协作改写
ompHandlebars 模板三套 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 层永远放最后是个精心计算:一次记忆保存只失效最短的缓存前缀,前面的稳定内容继续命中。

系统提示词字节序列(左 = 缓存前缀)

只重写末尾 volatile 段,
前面的稳定前缀继续命中缓存

stable 层
身份、工具指引
全会话固定

context 层
指令文件、规则、git 状态
显式刷新才重读

volatile 层
autoMemory
每次记忆保存重写

一次记忆保存

两条防御条款值得抄。「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 同时在场直接让组装失败。

恰好一个

两个同时在场

各插件注册 PromptSection{name, order, text}

scoped section 同名即遮蔽全局

按 order 排序
-100 harness 身份 · 0 部署 persona · 100~199 工具指引

Cordis waterfall 协作改写
插件依次修改,返回值为权威

有 section 声明 complete?

该段成为唯一提示词

组装直接失败

严格 {{var}} 插值

最终系统提示词

动态上下文以快照注入,每次快照显式声明「取代先前的运行时上下文快照」(: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.mdCLAUDE.md
codex支持,根到 cwd 全拼接不支持
gemini-cli用自家 GEMINI.md 四层不支持
qwen-code支持(兼容层)不支持
opencode支持,首类命中支持
kimi-code支持不支持
dsh支持支持
omp支持支持(另 6 种约定)

注入防御的三层与共同敞口

七家的注入防御可以归为三层,但没有一家做到独立的注入检测模型层:

  1. 变量消毒(被动):注入前对字符串做清洗。gemini 去换行和方括号,qwen 归一零宽字符并转义标签,kimi 用 <untrusted_objective> 包裹加转义。
  2. 契约声明(主动):用提示词教模型区分系统与用户内容。omp 声明 XML 标签语义,qwen 和 kimi 声明 <system-reminder> 是权威系统指令,codex guardian 把转录增量当作不可信证据。
  3. 运行时拦截(事后):omp 的 Harmony 泄漏扫描、qwen 的不得绕道条款、各家的循环纠偏。

共同敞口:没有任何项目在「工具结果入历史前」插独立的注入检测层。工具返回的网页、文件内容是最常见的注入载体,这块完全靠模型自觉。外接 guardrail 时,dsh 的 tools/post-execute waterfall 和 opencode 的消息变换钩子是合适的挂点。

给 Agent 开发者的借鉴清单

  1. 按模型族分派 base prompt。 成本只是多维护几份文本,换来各家族的最优遵循(opencode 的 9 份分派)。
  2. 组装函数唯一知道顺序。 调用方只能分类内容进 slot,防止各处乱序追加(qwen 的 layers 设计)。
  3. 易变内容放最后。 记忆、状态这类频繁重写的部分放在提示词尾部,一次更新只失效最短的缓存前缀。
  4. 动态快照要声明取代关系。 「本快照取代先前快照」一句话,省掉模型混淆新旧上下文的麻烦(dsh)。
  5. 不可信内容进提示词前先包裹转义。 标签逃逸要连零宽字符一起防(qwen 的 xml.ts 是完整样本)。
  6. 写一条「被拒操作不得绕道」条款。 模型很擅长找等效路径绕过拒绝(qwen 的条款原文可以直接抄)。
  7. 兼容主流指令文件约定。 AGENTS.md 已是事实标准,兼容竞品约定能显著降低迁移摩擦。
  8. 提示注入检测层留好挂点。 工具结果入历史前的位置最合适,现在没有项目做,是差异化机会。

文档地图

文章内容速览
总述拆了七大开源 Agent 的源码,最高分竟然不是 Codex总体结论、评估方法与评分卡
01架构对比四种流派与分化根源、主循环与事件机制、插件化与耦合风险
02上下文管理压缩触发阈值、摘要方式、token 计数口径、跨会话记忆
03会话管理持久化模型三层次、并发控制、崩溃恢复与 resume / fork
04工具调用注册与可见性、并行调度四种语义、审批门控、错误处理
05重连与容错重试预算、流中断处理、降级链、副作用安全
06系统提示词与指令遵循四种组装范式、动态注入、注入防御三层与共同敞口
07思维链与工作流编排思维链接入、plan 模式语义、子代理治理、工作流引擎
08性能设计前缀缓存三档分化、启动优化、成本核算
09可扩展性MCP 接入、自定义工具、多 provider、SDK 与 API
10安全与权限控制沙箱两种语义、审批默认姿态、企业管控、敏感数据保护
Logo

葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。

更多推荐