AI Coding Agent 的上下文栈:组件边界与装配顺序
Coding Agent 的上下文并不是一份不断增长的聊天记录。模型每次决策前看到的输入,来自项目指令、Rules、Skill、工具定义、会话历史、外部记忆和运行时事件。它们由不同组件保存,在不同时间进入工作窗口,也由不同机制负责恢复。
如果不先划清组件边界,几个常见问题会混成一团:AGENTS.md 和 Skill 谁优先,MCP 与 Tool Search 是否相同,Hook 算不算上下文,Subagent 是工具还是新会话,compact 后恢复的是历史还是外部材料。
这套系统更接近一台上下文操作系统。模型只处理当前工作集;Harness 负责装配、换页、执行、隔离和验证。
核验日期:2026-07-17。本文讲稳定组件和边界。各产品的版本差异集中在实现图谱中维护。
上下文系统的五类组件
同一个 Markdown 文件可能同时带有说明、脚本入口和资源链接,但在运行时仍可以按职责拆成五类。
| 组件类别 | 主要对象 | 回答的问题 |
|---|---|---|
| 内容源 | System prompt、AGENTS.md、CLAUDE.md、Rules、Skill、Memory、文件 |
有哪些材料可以进入工作集 |
| 选择器 | 层级覆盖、glob、description 路由、Tool Search、检索器 | 当前任务需要哪些材料 |
| 装配器 | Context builder、message converter、tool registry | 材料以什么顺序和语义进入模型输入 |
| 执行器 | Tool、MCP server、脚本、Subagent、sandbox | 模型选定动作后由谁改变外部世界 |
| 生命周期控制 | Hook、cache、prune、compact、checkpoint、trace | 工作集怎样增长、压缩、恢复和审计 |
flowchart LR
subgraph S["内容源"]
S1["System / Developer"]
S2["AGENTS / CLAUDE / Rules"]
S3["Skills / Commands"]
S4["Files / Memory / History"]
S5["Tool / MCP schemas"]
end
subgraph Q["选择与装配"]
Q1["Scope / precedence"]
Q2["Router / retrieval"]
Q3["Context assembler"]
end
subgraph R["模型工作集"]
R1["Instructions"]
R2["Tools"]
R3["Messages"]
end
subgraph E["执行与隔离"]
E1["Local tools"]
E2["MCP / remote APIs"]
E3["Subagent context"]
end
subgraph L["生命周期"]
L1["Prompt cache"]
L2["Prune / compact"]
L3["Memory / checkpoint"]
L4["Hooks / trace"]
end
S --> Q --> R --> E
E --> R
R --> L
L --> Q
Hook 没有被画进内容源,因为 Hook 本身是事件处理器。它可以生成上下文,也可以只记录日志、修改参数或阻断动作。只有 Hook 的输出被 Context Assembler 接纳时,那部分输出才成为模型上下文。
模型看到的是装配结果
不同 Provider 使用 system、developer、user、assistant、tool 等不同 role,但 Harness 层可以先抽象成三块。
1 | |
某段内容来自 SKILL.md,不代表它必须进入 system role;某个 MCP 工具出现在工具面,也不代表它的说明永远常驻模型上下文。产品可以改变具体消息形态,只要语义和生命周期保持一致。
因此,运行时 trace 只能证明某个版本、某个模型和某种配置下的实现。它不适合直接写成跨版本协议。
持久项目指令
AGENTS.md、CLAUDE.md 和 Project Rules 都属于持久项目指令。它们描述仓库边界、构建命令、目录职责、验证方式和长期约束。
这类文件有三个共同特征:
- 生命周期通常长于单次任务
- 作用域由目录层级、文件模式或产品配置决定
- 内容在任务开始前就应成立,不依赖某个特定工作流是否被调用
它们最适合保存“在这个仓库里一直成立”的规则,例如:
- 哪些目录可写
- 使用哪个包管理器
- 代码修改后运行哪些检查
- 哪些生成目录不能手工编辑
- 子目录是否有更具体的约束
大型操作手册、框架教程和只在少数任务中使用的 SOP 不适合常驻。它们会抬高每次请求的固定基线,也会让关键仓库规则埋在大段说明里。
Rules 是条件式指令
Rules 解决的是“哪些指令在什么作用域生效”。选择条件可以是:
- 无条件应用
- 当前路径或被读写文件匹配 glob
- 模型根据 description 判断
- 用户显式引用
- 更近目录覆盖更远目录
Rules 与 Skill 都可能由 Markdown 表达,但语义不同。Rule 约束当前任务,Skill 提供完成某类任务的方法和资源。Rule 通常不应要求模型“调用自己”;Skill 则需要一次激活动作,才能展开正文和资源。
Cursor 的 Project Rules 同时支持 Always、智能选择、文件模式和手动应用。Codex 与 Claude Code 的项目指令更强调目录层级。产品名称不同,底层都是作用域选择器。
Skill 是动态能力包
Skill 的核心不是一段额外提示词,而是一个可渐进展开的能力包:
1 | |
metadata 进入轻量目录,帮助模型或用户选择。正文只在激活后进入工作集。参考材料和脚本继续留在外部,直到当前分支需要。
这种结构把“知道有这项能力”和“承担这项能力的全部成本”分开。目录承担召回,正文承担工作流,脚本承担确定性动作,资源承担交付素材。
Skill 的详细加载、热更新和 compact 恢复见《AI Coding Agent 的 Skill 加载机制深度解析》。
Tool 与 MCP 属于执行面
Tool 是模型可以请求的动作接口。文件读取、Shell、编辑器操作、浏览器、数据库查询和代码搜索都可以表现为 Tool。
MCP 定义 Host、Client、Server 如何交换 tools、resources 和 prompts。它解决跨进程和跨产品互操作,不替 Harness 决定:
- 当前是否应该调用
- 哪个参数需要审批
- 失败后是否重试
- 结果怎样裁剪
- 停止前需要什么验证
一个 MCP tool 进入 Harness 后仍要经过 Tool Registry、权限规则、Hook 和消息转换。协议接通了能力,运行时负责治理能力。
Tool Search 又处在另一层。它延迟的是完整 tool schema,让模型先看到搜索入口或轻量索引,找到相关工具后再展开定义。它与 Skill 都采用渐进披露,但选择对象不同。
Messages 是短期工作轨迹
Messages 保存当前任务发生过什么:用户目标、模型动作、工具结果、文件观察、失败路径和验证证据。
append-only 历史会混入大量过时状态:
- 已经修正的错误假设
- 被放弃的方案
- 长日志和重复文件内容
- 与当前目标无关的探索
- 已完成子任务的过程细节
Harness 需要 prune、compact、externalize 和 replay 等策略管理它。对话历史并不是长期事实源。仓库真相仍在文件、git、测试、issue 和外部系统中,必要时应该重新读取。
《Messages 数组与 Prompt Cache:六种操纵策略》专门讨论 message array 的增长和缓存边界。
Memory 保存跨轮次和跨会话状态
Memory 不是一种单一文件格式。按生命周期可拆成四层:
| 层级 | 典型内容 | 读取方式 |
|---|---|---|
| 会话工作记忆 | 当前目标、最近观察、未完成动作 | 直接位于工作窗口 |
| Compact 恢复包 | 摘要、保留尾部、外部状态指针 | 压缩后重建 |
| 项目记忆 | 构建命令、目录地图、已验证惯例 | 启动或相关任务时加载 |
| 长期知识 | 历史决策、案例、语义知识、结果反馈 | 检索后按需换入 |
项目记忆与项目规则也有边界。Rule 是必须遵守的约束;Memory 是过去观察到、未来可能有用的信息。把记忆写成绝对规则,会让过期经验长期压住新证据。
Subagent 是上下文隔离器
Subagent 表面上像一个 Tool:主 Agent 给出任务,稍后拿回结果。但它创建的是一块独立工作上下文。
sequenceDiagram
participant P as Parent context
participant O as Orchestrator
participant S as Subagent context
participant W as Workspace / tools
P->>O: 发送有边界的任务与必要证据
O->>S: 创建独立上下文
S->>W: 搜索、读取、执行、验证
W-->>S: 返回局部证据
S-->>O: 结构化结果与引用
O-->>P: 只回灌结论、证据和风险
父上下文不必承担子任务的全部搜索轨迹。隔离的收益来自信息过滤,而不是“多一个人格”。如果任务边界不清、共享状态频繁变化或合并协议缺失,Subagent 只会制造更多同步成本。
Hook 是运行时控制面
Hook 位于 Agent loop 的事件边界,可以观察或干预:
- session start 和用户输入
- tool 调用前后
- permission request
- compact 前后
- subagent start/stop
- stop 与 task completion
Hook 的输出有四种常见去向:
| Hook 动作 | 是否进入模型上下文 |
|---|---|
| 写 trace 或发通知 | 通常不进入 |
| 阻断工具或修改参数 | 改变执行,不一定进入 |
| 返回错误观察 | 作为新观察进入 |
| 注入项目状态或恢复材料 | 明确进入 |
这也解释了为什么 compact 后可能迅速重新膨胀。压缩器刚清掉旧历史,PostCompact Hook、项目记忆和 hot paths 又把大段材料回灌,窗口仍然会很重。恢复层需要预算、去重和外部指针。
Plugin 是分发单元
Plugin 可以打包 Skill、Hook、MCP server、Subagent、Rule 和资源,但它本身通常不定义统一的上下文加载算法。
安装一个 Plugin 不等于包中所有内容都进入 prompt:
- Skill 仍走目录和按需正文
- MCP tool 仍走工具注册、权限和可能的延迟发现
- Hook 仍在对应事件触发
- Subagent 仍创建隔离上下文
- 静态 Rule 才可能成为常驻或条件式指令
把 Plugin 画成能力分发层,比把它画成另一种 Skill 更准确。
两条正交坐标
上下文组件可以用“存活多久”和“何时激活”两条坐标定位。
| 对象 | 典型存活时间 | 典型激活方式 |
|---|---|---|
| Harness baseline | 产品版本级 | 每次会话 |
| 项目指令 | 仓库级 | 启动和目录作用域 |
| Rules | 仓库或用户级 | always、路径、智能或手动 |
| Skill metadata | 安装级 | catalog 装配 |
| Skill body | 任务或会话级 | 显式或模型调用 |
| Tool schema | 会话级或动态 | 注册或 Tool Search |
| Tool result | 当前任务轨迹 | 工具执行 |
| Compact summary | 会话后半段 | 达到阈值或手动触发 |
| 项目记忆 | 跨会话 | 启动、检索或恢复 |
| Subagent context | 子任务级 | 编排器创建 |
“文件是不是 Markdown”无法说明它的运行时位置。成本和可靠性取决于作用域、选择器、装配位置、恢复规则和可观测性。
一次 Agent Turn 的装配顺序
不同产品的消息 role 和内部函数不同,但端到端过程可以稳定描述。
flowchart TD
A["读取 Harness 基线与项目作用域"] --> B["建立 Rules / Skills / Tools 目录"]
B --> C["接收用户目标"]
C --> D["选择相关 Rules、Skill、Memory 与文件"]
D --> E["装配 instructions + tools + messages"]
E --> F["模型选择下一步动作"]
F --> G{"动作类型"}
G -->|local tool| H["权限 / Hook / Sandbox"]
G -->|MCP| I["Host / Client / Server"]
G -->|subagent| J["创建隔离上下文"]
H --> K["执行结果"]
I --> K
J --> K
K --> L["追加观察与验证证据"]
L --> M{"工作集是否接近阈值"}
M -->|否| F
M -->|是| N["prune / compact / externalize"]
N --> O["恢复项目指令、记忆指针和必要能力"]
O --> F
装配顺序并不等于优先级。更晚进入消息尾部的内容可能位置更近,但 system 或 developer 指令通常有更高协议优先级;项目内更近目录的指令也可能覆盖根目录规则。内容冲突时需要同时检查协议 role、目录作用域、产品规则和时间新旧。
组件冲突的判断顺序
上下文冲突适合按四步定位。
- 先确认对象层级。模型限制、API 行为、Harness 配置和项目指令不能互相代替。
- 再确认作用域。全局、仓库、子目录、当前文件和当前 Skill 的适用范围不同。
- 检查时间状态。长期规则、当前计划、旧记忆和最新工具结果的新旧程度不同。
- 再检查协议优先级与执行门禁。高优先级指令仍可能被权限或 sandbox 拦截。
旧的配置文件全景常把文件按名字分类。更稳定的办法是按时间状态分类:
- 存量知识:长期文档、历史决策、案例和术语
- 当前对齐:项目指令、架构边界、工作约定
- 迭代状态:plan、task、diff、测试结果、阻塞点
- 运行时观察:工具输出、日志、浏览器状态、权限结果
同一个文件可以在不同阶段迁移。例如 plan 完成后不应继续作为当前指令常驻,它应该沉淀为决策记录或被删除。
设计检查表
评审一个 Agent Harness 时,“支持哪些文件”只够回答入口问题。还需要检查:
- 目录如何发现,重名如何覆盖
- catalog 是否有预算和截断告警
- 自动路由失败能否追踪
- Skill 正文和 Tool schema 在哪里展开
- 动态变化是否破坏稳定缓存前缀
- prune 与 full compact 是否分开
- compact 后哪些外部材料自动恢复
- Subagent 回灌的是结论还是完整轨迹
- Hook 能否阻断、改参数或注入上下文
- Plugin 的来源、权限和更新是否受治理
- trace 能否证明一次动作为什么发生
这些问题共同决定上下文系统是否可维护。文件格式只是最外层接口。
系列文章
- AI Coding Agent 的上下文操作系统:组件、生命周期与阅读地图
- 从 Rules 到 Agent Skills:能力加载机制的演变
- AI Coding Agent 的 Skill 加载机制深度解析
- 一次 Agent Turn:Hook、Loop、Tool 与 Messages
- Messages 数组与 Prompt Cache:六种操纵策略
- Context Paging:Compact、外部化、恢复与 Memory 生命周期
- 2026 Coding Harness 实现图谱
