跳转到内容

运行时提示词叠加层:动态注入会话上下文到 Agent 系统提示

运行时提示词叠加层:动态注入会话上下文到 Agent 系统提示

学习目标

读完本章后,你将能够:

  • 设计运行时提示词叠加层(Runtime Overlay),在 Agent 系统提示中动态注入会话上下文
  • 使用 HTML 注释标记实现叠加层的幂等应用与剥离
  • 实现会话作用域模型指令文件的三层合并
  • 理解代码地图生成与缓存策略
  • 设计压缩协议(Compaction Protocol)防止上下文压缩时丢失关键状态

前置知识


核心概念

1. 为什么需要运行时叠加层

Agent 的系统提示(如 AGENTS.md)通常是静态文件,存储在用户目录或项目目录中。但在每次会话启动时,需要注入会话作用域的上下文

需要注入的信息为什么不能写入静态文件
会话 ID 和时间戳每次会话不同
当前活跃的模式状态模式状态随工作流变化
代码地图(项目目录结构)代码库会演进
项目记忆摘要从运行状态中动态提取
团队编排器指令仅团队模式需要

运行时叠加层的方案是:在会话启动时读取静态文件,注入运行时上下文,将合并后的内容写入会话作用域的文件。会话结束时剥离叠加层,不修改源文件。

2. HTML 注释标记与幂等应用

叠加层使用 HTML 注释标记界定注入范围:

AGENTS.md 源文件:
# Project Agent Guidelines
...(用户编写的内容)...
会话启动时的叠加层注入后:
# Project Agent Guidelines
...(用户编写的内容)...
<!-- OMX:RUNTIME:START -->
## Session Metadata
Session ID: omx-1717567890-abc123
Timestamp: 2026-06-05T02:10:00Z
## Native Subagent Routing
...
<!-- OMX:RUNTIME:END -->

幂等性保证

伪代码:
function applyOverlay(agentsMdContent, overlay):
// 先剥离已有的叠加层
content = stripOverlay(agentsMdContent)
// 再注入新的叠加层
return content + "\n\n" + wrapWithMarkers(overlay)
function stripOverlay(content):
return content.replace(
/<!-- OMX:RUNTIME:START -->.*?<!-- OMX:RUNTIME:END -->/gs,
""
)

为什么需要幂等:如果叠加层已经被部分应用(如上一次会话未正常清理),重新应用不应产生重复内容。

多标记类型

标记用途
<!-- OMX:RUNTIME:START/END -->主叠加层
<!-- OMX:TEAM:WORKER:START/END -->团队 worker 叠加层
<!-- OMX:MODELS:START/END -->模型路由叠加层
<!-- omx:generated:agents-md -->生成的 AGENTS.md 标记

3. 叠加层注入内容(优先级排序)

叠加层内容按优先级排序,溢出时截断:

溢出保护:总上限 3500 字符,优先保留 Required 部分。Optional 部分按优先级依次注入,直到达到上限。

4. 代码地图生成与缓存

代码地图是项目目录结构的轻量级快照:

伪代码:
function generateCodebaseMap():
mtime = getGitIndexMtime()
if cache.mtime == mtime and cache.map exists:
return cache.map
files = run("git ls-files --cached")
dirs = groupByTopLevelDirectory(files)
map = ""
for dir, count in dirs (max 14 directories):
map += formatDirectory(dir, files[dir] (max 10 files))
cache.mtime = mtime
cache.map = truncate(map, 1000) // 上限 1000 字符
return cache.map

缓存策略:基于 git 索引的 mtime 判断是否需要重新生成。git 索引未变更时直接返回缓存。

5. 会话作用域模型指令文件

会话启动时,系统创建一个会话作用域的合并文件,合并三个来源:

阴影技能过滤:如果项目级 AGENTS.md 引用了与用户级 AGENTS.md 相同的技能,则删除项目级的阴影引用(避免技能定义冲突)。

6. 压缩协议(Compaction Protocol)

当 Codex 的上下文窗口接近上限时,会自动进行上下文压缩(compaction)。压缩协议确保关键状态不被丢失:

叠加层中的压缩协议指令:
"Before context compaction occurs, checkpoint all active states:
1. Write current mode state via `omx state write`
2. Record skill active state
3. Save progress ledger entries
4. Then proceed with compaction"

为什么需要压缩协议:上下文压缩会丢弃早期对话历史。如果关键状态(如当前技能阶段、迭代计数)只存在于对话历史中,压缩后 Agent 会”忘记”当前进度。

7. 文件锁与并发安全

叠加层的写入使用目录级文件锁:

伪代码:
function withOverlayLock(operation):
lockDir = mkdir(".omx/locks/overlay") // 原子操作
try:
return await operation()
finally:
rmdir(".omx/locks/overlay")
// 如果 PID 不存在,说明锁持有者已崩溃,直接删除

死 PID 回收:如果锁目录的 PID 对应的进程不再存在,直接删除锁目录,允许后续操作继续。

8. Ralph 规划门控

Ralph 规划门控是叠加层的动态部分,根据规划工件的存在性显示状态:

当 .omx/plans/ 中存在 PRD 和 test-spec 时:
## Ralph Planning Gate
Status: UNLOCKED — PRD and test-spec artifacts exist.
否则:
## Ralph Planning Gate
Status: BLOCKED — No PRD found. Run $ralplan first.

门控的目的:防止 Ralph 在没有批准方案的情况下直接实现代码。

陷阱与对策

陷阱后果对策
叠加层标记不匹配源文件被污染严格使用 HTML 注释标记,正则剥离时 s 模式匹配跨行
代码地图超过字符上限叠加层被截断代码地图单独限制 1000 字符,溢出时丢弃低优先级内容
并发写入竞争AGENTS.md 损坏目录级文件锁 + 死 PID 回收
压缩丢失状态Agent 忘记当前进度压缩协议强制先持久化状态
会话作用域文件残留新会话使用旧叠加层会话启动时先 strip 再 apply
阴影技能冲突Agent 使用错误的技能定义合并时检测并删除项目级的阴影引用

参考来源

  • OpenAI Codex CLI — AGENTS.md runtime overlay and session-scoped model instructions
  • HTML comment parsing patterns — Standard HTML comment syntax