Skip to content

上下文:Agent 的视野

本章摘要

每次 API 请求的上下文由三大块组成:system(系统提示词)、messages(消息历史)、tools(工具定义)。为了缓存的稳定性,上下文只可增,不可改

每次与 Agent 对话,表面是一问一答。但背后,每次 API 调用都在向大模型发送一个庞大的上下文——不止你的提问,还包含系统规则、对话历史、工具定义、环境信息、文件内容、记忆片段等。

上下文是 Agent 的"记忆与视野":它决定了 Agent 此刻能看到什么、知道什么、能做什么。

开始之前:使用缓存来降低模型成本

在进入上下文的细节之前,先讲一个贯穿全文的底层机制——提示缓存(prompt caching)

为什么要缓存

一次典型的 Agent 会话往往包含几十次甚至上百次 API 调用,每次调用都会把整个上下文重新发给模型,上下文不断累加,成本会快速失控,延迟也会越拖越长。

但这个过程有个特点,绝大部分内容在两次调用之间是不变的,变化的只是末尾新增的那几条。模型就不需要重头从第一个字开始重新构建它的整个推理流程,只要从缓存中去读取已完成的推理流程的中间参数。

这引出一个问题:到底请求哪一部分内容是已经在缓存中了——也就是前缀匹配

前缀匹配:为什么"顺序"很重要

缓存是前缀匹配——系统从前往后检查,遇到第一个不一致的字节就断开,断开之后的内容全部失效。

请求 A:[工具定义] [系统提示词] [消息1] [消息2]
请求 B:[工具定义] [系统提示词] [消息1] [消息3]
                                   └── 完全相同,整段命中缓存
                                        └── 只有 [消息3] 需要新处理

请求 C:[工具定义] [系统提示词改了] [消息1] [消息2]
                            └── 这里不一致,从这里开始全部失效
                            └── 后面所有内容都要重新写入

这也是为什么后面会反复强调:

  • 静态内容放前面(系统提示词的静态区域、工具定义)
  • 动态内容放后面(环境信息、当前任务、消息历史)
  • 已有的内容只追加不修改(一旦改动历史消息,整段缓存全废)

一句话总结:上下文的结构设计,本质上是为了让缓存尽可能多地命中,越是静态不变的内容越放在前部。

上下文全景:一次 API 调用发送了什么

每次 API 请求的上下文由三大块组成:

┌────────────────────────────────────────────────────┐
│                     API 请求                       │
├────────────────────────────────────────────────────┤
│  system                                            │
│  ├─ 静态区块(全局缓存)                           │
│  │  ├─ 身份与安全                                  │
│  │  ├─ 任务执行原则                                │
│  │  ├─ 工具使用指导                                │
│  │  └─ 语调与风格                                  │
│  └─ 动态区块(会话缓存 + 按需刷新)                │
│     ├─ 环境信息(当前目录、操作系统、模型等)      │
│     ├─ 语言偏好(语言、输出风格等)                │
│     ├─ 会话特定指导(工具、技能、MCP 指令)        │
│     └─ 自动记忆(记忆机制、预算、清理提醒)        │
├────────────────────────────────────────────────────┤
│  messages                                          │
│  ├─ [0] <available-deferred-tools>(延迟工具列表) │
│  ├─ [1] <system-reminder> AGENTS.md + 记忆 + 日期  │
│  ├─ [2] user: "帮我修复这个 bug"                   │
│  ├─ [3] assistant: 文本回复 + 工具调用             │
│  ├─ [4] user: tool_result(工具执行结果)          │
│  ├─ [5] assistant: 文本回复 + 工具调用             │
│  ├─ ...                                            │
│  └─ [n] attachment: 动态注入的附件(如:记忆检索) │
├────────────────────────────────────────────────────┤
│  tools                                             │
│  ├─ BashTool: name, description, input_schema      │
│  ├─ FileReadTool: name, description, ...           │
│  └─ ...(所有可用工具的定义)                      │
└────────────────────────────────────────────────────┘

三大块各司其职:

作用体积特征
system定义 Agent 是谁、怎么做事相对固定,几 KB 到十几 KB
messages对话历史和动态注入内容持续增长,是上下文的主体
tools声明可用的工具列表固定,几 KB 到十几 KB

三大块各司其职——system 是"出厂设置"、messages 是"工作记录"、tools 是"能力清单"。

发送 API 请求后,模型侧的内部处理顺序其实是:

system → tools → messages

最稳定的内容置于最前,提示缓存的前缀匹配窗口尽可能大。系统提示词和工具定义往往跨会话完全不变(因为系统版本一致时,内置工具不会发生变化,延迟工具会放在 messages 中),messages 持续变化。

系统提示词:Agent 的世界观

大语言模型每次调用都是无状态的——它不记得"上次说过什么",完全靠你传给它的内容来理解当前任务。系统提示词在每次调用时定义 Agent "是谁"、"怎么做事"、"用什么工具"、"怎么说话"——是整个行为的底层蓝图。

系统提示词的质量直接决定 Agent 的行为质量

静态与动态的分离

系统提示词由多个段落拼装而成,分为两大区域,中间有一条明确的缓存边界

区域内容性质缓存策略
静态区域通用行为准则,对所有用户一致全局缓存,跨会话复用
动态区域用户/会话/环境特定的信息会话缓存,关键事件按需刷新

静态区域是 Agent 的"出厂设置"——不关心当前项目,只规定 Agent 作为某种角色(比如编程助手)的基本行为准则。

  • 你是谁:你是帮助用户完成任务的交互式 Agent,不是闲聊机器人。
  • 基础系统规则:定义了如何处理输出、权限、外部输入等——确保行为安全、可控且符合用户预期。
  • 怎么做任务:先读文件再动手,做最小必要修改,不顺手做其他事,不假装验证通过。
  • 什么事要谨慎:本地可逆操作可以直接做;删除文件、覆写文件这类高风险操作要先确认。
  • 怎么用工具:有专用工具就优先用专用工具,多个独立工具调用可以并行。
  • 怎么说话:简洁、直接,不用 emoji;引用其他文件时给出路径和行号。

动态区域描述本次运行的环境、用户偏好和可用能力。它不是一整段上下文,而是一组独立片段,每个片段负责一个具体维度(环境信息、用户偏好、能力指令等):

片段名称内容
环境信息工作目录、平台、Shell、操作系统、当前模型名称和 ID等
语言偏好用户设定的语言偏好指令
输出风格输出风格配置(如简洁程度、表格偏好等)
会话指导工具的使用指导——如 Agent 工具说明、技能调用说明等
记忆系统指令记忆系统的行为指令(如何读写记忆,并非实际的记忆内容)
临时文件会话临时文件目录(如 /tmp/)的使用说明(Agent 可写入临时产出)
MCP 指令已连接 MCP 服务器的使用说明
Token 预算Token 预算目标的指导(仅在启用时注入)

静态与动态分离的核心价值是缓存效率——静态内容对所有用户相同,缓存一次全网复用;动态内容大多数时间可以跨会话共享,但用户间不共享。

消息历史:上下文的主体

系统提示词定义 Agent 的"出厂设置",但真正让它理解当前任务进展的,是消息历史——占据上下文绝大部分 token 预算。接下去依次介绍其组成成分。

延迟工具列表

<available-deferred-tools>
mcp__browser_click
mcp__browser_navigate
...
</available-deferred-tools>

这条消息列出所有延迟工具的名称(详见:工具系统:Agent 的双手),不含任何 Schema。模型必须先通过 ToolSearch "发现"延迟工具再执行调用。

AGENTS.md

紧接着,系统自动插入一条 <system-reminder> 消息(AGENTS.md 章节和记忆系统章节已介绍):

<system-reminder>
[AGENTS.md 及其引用文件的内容 + 自动记忆]

# currentDate
Today's date is 2026/05/29.
</system-reminder>

旧事重提为什么 AGENTS.md 不放在系统提示词中? 核心原因是权限隔离——模型后训练时,会提升系统提示词对模型的影响权重,如果把 AGENTS.md 放入系统提示词,容易遭受恶意 AGENTS.md 的安全攻击。

消息角色与流转

消息历史按时间顺序排列,每条消息带有"角色"和"内容"。三种角色循环往复:

user: "帮我整理一下这份旅游攻略"

assistant: "我先看一下你提供的资料" + [工具调用:读取文件]

user: [工具结果:资料内容...]

assistant: "找到了,开始整理" + [工具调用:写入新文件]

user: [工具结果:写入成功]

assistant: "整理完成。结构是这样..."

用户消息主要包括用户输入的文本,或工具执行结果(如果模型/助理上次返回了一次工具调用的消息)

助理回复是消息历史的核心,包含两种内容:

  • 文本内容:用户可见的回复——解释、分析、总结、提问
  • 工具调用声明:模型表达"我要用这个工具、传这些参数",系统随后将执行结果以 user 消息拼回

attachment 指动态注入的附件,主要为了告知模型随着时间变化,某些内容

模型就是这样"边想边做":看文件内容 → 发现问题 → 调用编辑工具 → 看到结果 → 确认正确 → 给出文字回复。

附件注入

每轮工具循环结束后,系统向消息列表注入各种附件(attachment),共 40 多种类型,是动态上下文的核心来源。按用途可以归纳为几类:

类别典型触发条件注入内容举例
用户引用用户输入包含 @path被引用文件的完整内容
模式状态处于计划/自动模式提醒保持当前模式、自主推进任务
任务状态后台任务变化、长期未操作任务进度、当前未完成的任务列表
能力清单增量可用的 Agent / 技能 / MCP 工具发生变化新增或移除的能力名称与描述
记忆变化自动记忆被新增/更新触发记忆写入的提示与上下文
运行环境监控每轮自动生成、文件被修改、出错或警告Token 用量、已修改文件列表、错误与警告

设计要点:附件是按需注入的——只有触发了相应条件,对应附件才会出现在消息列表里。这一机制让上下文既能携带丰富的动态信息,又不会无差别地膨胀。

技能描述的注入有严格的 token 预算——通常不超过上下文窗口的 1%(约 8000 字符),每条技能描述被截断到 250 字符以内。内置技能不受此限制,始终展示完整描述;用户自定义和项目级技能则可能被截断。

附件注入时机

Agent Loop 的每一轮只追加消息、不改历史,附件注入同样遵循此规则。但注入时机并非简单的"每轮一次",而是分两个窗口

窗口一:用户提交输入时。即 Agent Loop 的第一轮——用户输入刚刚到达,模型尚未开始推理。此时注入的附件均源自用户行为:@path 引用的文件、@agent 引用的 Agent、MCP 资源等。模型在首次回复前即拥有这些上下文。

窗口二:每轮工具执行结束后。即 Agent Loop 的后续轮次——模型调用工具,系统执行完毕并返回结果。此时注入的附件反映工具执行的副作用:已修改文件列表、诊断信息更新、任务状态变化、Token 消耗量等。模型在下一轮推理前即感知到刚才的操作对环境的影响。

工具定义:能力的声明

每次 API 请求还包含所有立即可用的工具的名称、描述和参数定义,需要注意三点:

  • tools 字段只存放立即可用的工具,而非延迟工具(详见工具系统章节);
  • tools 字段全程不变,因为在模型侧提示词拼接时,它会被放在系统提示词后(system -> tools -> messages);

Subagent 的系统提示词

Subagent 走另一条独立路径——它的系统提示词只包含 Agent 自己的提示词 + 少量固定附加内容(环境信息、行为备注),不使用默认提示词中的任何静态或动态段落

这种"独立路径"的设计哲学是角色隔离——不同 Agent 有各自的"出厂设置",避免无关上下文污染子任务。

本章要点

  • 上下文由 system / messages / tools 三大块组成
  • system 定义 Agent 的出厂设置——身份、行为准则、工具使用规范
  • messages 是上下文的主体——对话历史、工具调用和结果
  • tools 是能力声明——既影响 token 消耗,也影响行为边界
  • 静态与动态分离是为了缓存效率——稳定内容可跨会话复用
  • Subagent 有独立的系统提示词路径,不共享主 Agent 的静态/动态段落