Code Agent 的
Context

PYCON2026
从 API、Agent Loop
到缓存与协作
THE QUESTION

模型每次
实际看到了什么?

把资料交给你的 Agent

LLMHUMAN ↔︎ AGENT
FOR HUMANS

访问 llms.txt 的二维码 扫描二维码 打开 llms.txt,再把它交给你的 Agent

现场的人类小伙伴有问题,先咨询你的 Agent

如果 Agent 无法解答,请要求它联系我的 Agent。

资料与问题→
来访的 Agent直接读取以下入口https://shell909090.github.io/slides/code_agent_ctx/llms.txt
llms.txt 内含第一至三章资料第四至六章资料逐页讲稿作者联系方式
ASK YOUR AGENT资料先交给 Agent;现有资料答不了,再让 Agent 联系我的 Agent

不带 Tool Call 的模型 API

01MODEL API
POST/v1/chat/completionsContent-Type: application/json
REQUEST客户端 → 服务端
{
  "model": "<chat-model>",
  "messages": [
    {
      "role": "system",
      "content": "你是一个回答简洁的数学助手。请给出精确结果。"
    },
    {
      "role": "user",
      "content": "求 1 到 10,000(含)中满足以下条件的所有整数的数量与总和:能被 7 或 11 整除,但不能同时被 7 和 11 整除,并且不能被 5 整除。"
    }
  ]
}
RESPONSE服务端 → 客户端 · 结构示意
{
  "id": "chatcmpl_...",
  "object": "chat.completion",
  "created": 1787000000,
  "model": "<chat-model>",
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "满足条件的整数共有 1663 个,\n总和为 8,318,317。"
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 28,
    "completion_tokens": 12,
    "total_tokens": 40
  }
}
API ENVELOPE请求与返回都不是 Transformer 直接读取或生成的完整 JSON

JSON 怎样变成模型输入

02RENDERER
同一组 messages · 三种表示并列 · DeepSeek 控制 token 前换行仅用于展示
概念中间表示教学用伪表示
[SYSTEM]
你是一个回答简洁的数学助手。
请给出精确结果。
[END]
[USER]
求 1 到 10,000(含)中满足条件的整数数量与总和:
能被 7 或 11 整除,但不能同时被二者整除,
并且不能被 5 整除。
[END]
[ASSISTANT]
Qwen3-Coder固定 revision
<|im_start|>system
你是一个回答简洁的数学助手。请给出精确结果。<|im_end|>
<|im_start|>user
求 1 到 10,000(含)中满足以下条件的所有整数的
数量与总和:能被 7 或 11 整除,但不能同时被 7
和 11 整除,并且不能被 5 整除。<|im_end|>
<|im_start|>assistant
DeepSeek-V3.1non-thinking · 展示分行
<|begin▁of▁sentence|>
你是一个回答简洁的数学助手。请给出精确结果。
<|User|>
求 1 到 10,000(含)中满足以下条件的所有整数的
数量与总和:能被 7 或 11 整除,但不能同时被 7
和 11 整除,并且不能被 5 整除。
<|Assistant|>
</think>
同一组 messages→不同模型专用字符串→token IDs

一次模型调用的总体流程

03FULL PATH
用户 / 客户端HTTP 与状态
API Service校验与封装
Renderer / ParserTemplate · Tokenizer
MODELprefill · decode
request JSON
messages
input token IDs
output token IDs
assistant / finish reason
response JSON
模型处理和生成的是 token 序列,不是完整 HTTP JSON

第二次请求:History 开始增长

04NEXT TURN
POST/v1/chat/completions第二次完整请求
{
  "model": "<chat-model>",
  "messages": [
    { "role": "system",    "content": "你是一个回答简洁的数学助手。请给出精确结果。" },
    { "role": "user",      "content": "求 1 到 10,000(含)中满足以下条件的所有整数的数量与总和:能被 7 或 11 整除,但不能同时被 7 和 11 整除,并且不能被 5 整除。" },
    { "role": "assistant", "content": "满足条件的整数共有 1663 个,总和为 8,318,317。" },
    { "role": "user",      "content": "请解释你是怎样计算的。" }
  ]
}
NEXT TURN第二次请求 = 旧 messages + assistant 返回 + 新 user message

加入 Tool Call:请求载荷

05TOOLS REQUEST
POST/v1/chat/completionsmessages + tools + tool_choice
{
  "model": "<chat-model>",
  "messages": [
    {
      "role": "system",
      "content": "你是一个回答简洁的数学助手。请给出精确结果。"
    },
    {
      "role": "user",
      "content": "求 1 到 10,000(含)中满足以下条件的所有整数的数量与总和:能被 7 或 11 整除,但不能同时被 7 和 11 整除,并且不能被 5 整除。"
    }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "run_python",
        "description": "在隔离环境中运行 Python 3 代码,并返回 exit_code、stdout 和 stderr",
        "parameters": {
          "type": "object",
          "properties": {
            "code": {
              "type": "string",
              "description": "需要执行的 Python 3 程序"
            }
          },
          "required": ["code"],
          "additionalProperties": false
        },
        "strict": true
      }
    }
  ],
  "tool_choice": "auto"
}
TOOL DEFINITION描述模型可以请求的能力,不包含 Python 执行器实现

模型返回 Tool Call

06TOOLS RESPONSE
200assistant.tool_calls尚未执行工具
{
  "id": "chatcmpl_...",
  "object": "chat.completion",
  "model": "<chat-model>",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": null,
        "tool_calls": [
          {
            "id": "call_001",
            "type": "function",
            "function": {
              "name": "run_python",
              "arguments": "{\"code\":\"values = [n for n in range(1, 10_001) if (n % 7 == 0) != (n % 11 == 0) and n % 5 != 0]\\nprint(len(values))\\nprint(sum(values))\"}"
            }
          }
        ]
      },
      "finish_reason": "tool_calls"
    }
  ]
}
PAUSEDTool Call 是执行请求;Runtime 解析、授权并执行后才会产生 Tool Result

带 Tool Result 的第二次请求

07SECOND REQUEST
POST/v1/chat/completions完整 history + tool result + tools
{
  "model": "<chat-model>",
  "messages": [
    { "role": "system", "content": "你是一个回答简洁的数学助手。请给出精确结果。" },
    { "role": "user", "content": "求 1 到 10,000(含)中满足以下条件的所有整数的数量与总和:能被 7 或 11 整除,但不能同时被 7 和 11 整除,并且不能被 5 整除。" },
    {
      "role": "assistant", "content": null,
      "tool_calls": [{
        "id": "call_001", "type": "function",
        "function": {
          "name": "run_python",
          "arguments": "{\"code\":\"values = [n for n in range(1, 10_001) if (n % 7 == 0) != (n % 11 == 0) and n % 5 != 0]\\nprint(len(values))\\nprint(sum(values))\"}"
        }
      }]
    },
    {
      "role": "tool", "tool_call_id": "call_001",
      "content": "{\"exit_code\":0,\"stdout\":\"1663\\n8318317\\n\",\"stderr\":\"\"}"
    }
  ],
  "tools": [{
    "type": "function",
    "function": {
      "name": "run_python",
      "description": "在隔离环境中运行 Python 3 代码,并返回 exit_code、stdout 和 stderr",
      "parameters": {
        "type": "object",
        "properties": { "code": { "type": "string", "description": "需要执行的 Python 3 程序" } },
        "required": ["code"], "additionalProperties": false
      },
      "strict": true
    }
  }],
  "tool_choice": "auto"
}
APPENDassistant Tool Call 与对应 Tool Result 必须一起进入下一次请求

一次完整的 Tool Loop

08TOOL LOOP
客户端 / Runtimehistory · 执行器
API Service校验与封装
Renderer / ParserTemplate · Tokenizer
MODEL两次独立推理
请求 1 · messages + tools
渲染第一次输入
input token IDs
assistant.tool_calls
解析并封装 response 1
返回 1 · Tool Call
CLIENT EXECUTION解析 → 校验 → 授权 → Sandbox 执行Tool Result · call_001
请求 2 · history + Tool Result
渲染第二次完整输入
input token IDs
最终 assistant answer
解析并封装 response 2
返回 2 · finish_reason: stop
1 次 Tool Loop = 2 次模型推理 + 1 次客户端执行

出错后的最后一次请求

09ERROR IN CONTEXT
POST #3/v1/chat/completions用于生成最终回答
#ROLE关联messages 中的关键载荷
1system—

原 instructions 正文省略;实际请求保留全文

2user—

原数学问题 正文省略;实际请求保留全文

3assistantcall_101

run_python
numbers = […]
print(len(values)) · print(sum(values))

4toolcall_101
exit_code: 1 · stdout: ""
stderr:
Traceback (most recent call last):
  File "<string>", line 2, in <module>
NameError: name 'values' is not defined
5assistantcall_102

run_python
numbers = […]
print(len(numbers)) · print(sum(numbers))

6toolcall_102
exit_code: 0 · stderr: ""
stdout: "1663\n8318317\n"
APPEND-ONLY修正成功,不等于失败从 Context 中消失

带 Tools 的请求如何变成模型输入

10TOOLS RENDERING
协议节选 · 灰色“内容省略”仍存在于真实输入 · 特殊标记原样保留
概念表示教学伪表示
[SYSTEM]
你是一个回答简洁的数学助手。
[END]

[AVAILABLE_TOOLS]
run_python(code: string, required)
用途:执行 Python 3,返回
exit_code / stdout / stderr
schema: code 为必填 string
[END]

[USER]
〔原数学问题全文〕
[END]
[ASSISTANT]
Qwen3-Coder固定 revision · 协议节选
<|im_start|>system
〔原 system 正文〕

# Tools
<tools>
<function>
<name>run_python</name>
<description>执行 Python 3…</description>
<parameters>
〔完整 schema〕
</parameters>
</function>
</tools>
〔Tool Call 输出格式说明〕
<|im_end|>
<|im_start|>user
〔原数学问题全文〕
<|im_end|>
<|im_start|>assistant
DeepSeek-V3.1non-thinking · 协议节选
<|begin▁of▁sentence|>
〔原 system 正文〕

## Tools
You have access to the following tools:

### run_python
Description: 执行 Python 3…
Parameters: 〔完整 JSON Schema〕

IMPORTANT: ALWAYS adhere to this
exact format for tool use:
<|tool▁calls▁begin|>…
<|tool▁calls▁end|>

<|User|>〔原数学问题全文〕
<|Assistant|>    </think>
SAME APITools 都在 trajectory 之前,但注入语法与 generation cursor 不同

Tool Result 请求如何变成模型输入

11RESULT RENDERING
协议后缀节选 · 共同前缀 = 第 10 页完整 system + tools + user
概念表示教学伪表示
〔共同前缀完整重现〕

[ASSISTANT_TOOL_CALL id=call_001]
run_python({"code":"〔枚举程序〕"})
[END]

[TOOL_RESULT id=call_001]
{"exit_code":0,
 "stdout":"1663\n8318317\n",
 "stderr":""}
[END]

[ASSISTANT]
Qwen3-Coder真实后缀 · 协议节选
〔共同前缀完整重现〕

<|im_start|>assistant
<tool_call>
<function=run_python>
<parameter=code>
〔枚举程序〕
</parameter>
</function>
</tool_call><|im_end|>
<|im_start|>user
<tool_response>
{"exit_code":0,
 "stdout":"1663\n8318317\n",
 "stderr":""}
</tool_response>
<|im_end|>
<|im_start|>assistant
DeepSeek-V3.1真实后缀 · 协议节选
〔共同前缀完整重现〕

<|Assistant|></think>
<|tool▁calls▁begin|>
<|tool▁call▁begin|>run_python
<|tool▁sep|>{"code":"〔枚举程序〕"}
<|tool▁call▁end|>
<|tool▁calls▁end|>
<|end▁of▁sentence|>
<|tool▁output▁begin|>
{"exit_code":0,
 "stdout":"1663\n8318317\n",
 "stderr":""}
<|tool▁output▁end|>
SAME HISTORYQwen 把结果放进 user block;DeepSeek 直接追加 Tool Output

当前 Context 的布局与来源

12CONTEXT LAYOUT
完整记录Append-only Historyuser · assistant · Tool Call / Result
当前外部状态State / Artifacts文件 · 日志 · 测试 · Patch · 数据库
每轮重新构造Runtime Configinstructions · tools · permissions
选择 · 组织 · 注入CONTEXT
POLICY
MODEL-VISIBLECurrent Context
System / Developer instructions
Tool definitions · Rules · Permissions
Selected History · Summary · Evidence
Latest Tool Result · Current User
Assistant generation position
HISTORY发生过什么完整、可审计、原则上只追加
CURRENT CONTEXT模型这一次看到什么从 History 与当前状态派生的有限视图
CONTEXT WINDOW这一次最多能装多少输入与输出共享的 token 容量上限
PROJECTIONHistory ≠ Context;改变投影,不等于改写历史

Context 为什么不能太长

13CONTEXT LIMITS
01 · HARD LIMIT最终会放不下
instructions + tools + history + output

History 随 Tool Loop 增长;Context Window 不随任务步数增长。

02 · POSITION EFFECT位置不同,利用可能不同

许多长 Context 评测出现首尾较好、中部较弱;并非所有模型都有同一条 U 型曲线。

03 · EFFECTIVE CONTEXT放得下,也未必用得好
目标证据旧计划重复日志冲突版本无关结果

多信息检索、聚合与抗干扰任务,可能随长度增加而退化。

重要边界影响的形状和幅度取决于 模型 × 任务 × 信息位置 × 干扰项;没有跨模型、跨任务的统一曲线。
WINDOW ≠ USAGE标称容量只回答“能否放下”,不保证“能否稳定利用”

历史不能全带,关键状态又不能丢

14WHY COMPACTION
越来越长完整 History
需求读取修改失败修正测试继续…

几十到几百步 trajectory 可以继续 append-only 增长。

≠不能永久
原样进入
固定容量Current Context
FULL

简单截断可能让 Agent 继续执行,却已经偏离原任务。

初始需求兼容约束架构决定失败原因修改与验证待办与权限
COMPACTION完整 History 保留;为下一轮构造更短的 continuation Context
NOT DELETE缩减的是 model-visible projection,不是审计用的完整 History

缩减 History 的三类方法

15THREE OPERATIONS
类别 本文列举 具体方法 概念
丢弃
Drop4
C(H)=空 Sliding Window Context 向前滑,只保留近期窗口内的完整历史单元
C(H)=空 Last-N 固定保留最后 N 条 message、Turn 或 Episode
C(H)=空 超限移除最早 Turn 达到 token 上限时,按时间淘汰最旧完整轮次
C(H)=空 按相关性淘汰 依据当前任务,决定整个历史单元是否继续可见
删减
Extractive4
原文子集 Tool Result Clearing 用短标记、关键统计和 Artifact 指针替代冗长旧输出
原文子集 截取错误栈 保留异常类型、关键帧与相关原文,删除重复栈帧
原文子集 相关代码行 只保留当前问题涉及的原始代码片段
原文子集 精确字段摘取 保留路径、数字、符号和测试失败,不生成新叙述
摘要
Abstractive2
派生表示 自然语言摘要 把多轮行为重新叙述为较短的任务状态
派生表示 结构化 State 按事实、决定、失败、待办与证据位置等固定字段表达
Tool Call / Result 必须作为完整协议单元处理
4 + 4 + 2这里只列举常见做法,不是所有可能性

Compaction 的基本流程

16COMPACTION FLOW
01监控 Contexttoken 使用量 · 阶段边界
02触发 Compaction达到阈值或显式触发
03安全切分old prefix P · raw window T
04缩减旧前缀Drop · Prune · Summarize
05重建 Contextstable instructions + S + T
06开启新 Epoch继续追加新的事件

History projection = old prefix P + recent raw window T →S = compact(P) →New Context = stable instructions + S + T

RAW WINDOW最新要求 · 当前错误 · 最新 Tool Result · 未闭合操作 · 精确代码
SAFE BOUNDARY一般位于两个 Turn 之间 · 每个 Turn 全部压缩或全部保留
NEW EPOCHContext 被重建;完整 History 仍然 append-only

Compact 前后:messages 发生了什么

17PAYLOAD DIFF
BEFORE长 trajectory
system稳定 Agent instructions
user升级解析器;保持兼容并通过测试
assistantread_file Tool Call
tool大段文件内容
…数十组搜索 · 编辑 · 失败测试 · 修正
user继续修复剩余测试RAW
tools: read_file · edit_file · run_tests
OLD PREFIXCOMPACT→
任务硬约束已完成已验证失败原因修改文件下一步证据
AFTER新 Context Epoch
system同一稳定 Agent instructions
developer<continuation_state>
任务 · 约束 · 进度 · 错误 · 下一步 · 证据
</continuation_state>
user继续修复剩余测试RAW
tools: 同一组 definitions
旧 messages:仍在完整 History文件 / Git diff / 日志:仍在 Workspace 或 ArtifactsSummary role:实现相关
REPLACE VIEW中间历史退出后续推理,由摘要替代

Agent 如何产生摘要

18SUMMARY REQUEST
A追加式摘要请求保留原 roles
Compression System Prompt
user → assistant → tool → …
user: 按指定结构生成 continuation summary
↓
assistant: summary

优点保留 Message role 与 Tool 协议;同前缀时可能复用 Cache

限制选入的前缀仍须放得下;主要靠指令要求模型关注或忽略

Gemini CLI · Claude Code · Continue

B转录式专用摘要请求Runtime 先选数据
选择旧 History截断大 Result外置 Artifact移除 Agent Tools
system: 你是 Context Compactor
user: <history> [User] … [Tool result] … </history>
↓
structured summary

优点直接控制摘要器能看到什么;可用独立、更便宜的模型

代价通常不能复用原 trajectory Cache;role 与 Tool 结构可能损失

OpenCode · Aider · Cline · OpenHands

WHO SELECTS?追加式主要用指令约束;转录式先由 Runtime 决定可见数据

主流 Agent 的 Compaction 行为

19AGENT BEHAVIOR
Agent 摘要请求 Compact 后 Context Raw Window / 模型
Gemini CLI固定 revision Compression System Prompt
+ 原始旧 messages
+ 末尾 user 摘要指令
再调用一次模型校验
user(state_snapshot)
+ model(固定确认)
+ raw tail
目标近期约 30% 按字符近似
映射到对应 compression model
Claude Code公开文档 + 固定发布版证据 追加式摘要请求
禁止 Tools
合成 user summary
+ Runtime 重注入 startup、Memory 与受保护内容
普通全量 Compact 默认无 raw tail
通常当前主模型,可 fallback
OpenCode1.18.21 · V1 Runtime 旧 History 转录成单一 user request
专用 Compaction Agent
Tools 为空
user: What did we do so far?
+ assistant: summary
+ raw tail
优先完整近期 Turns;预算不足可 Turn 内切分
默认当前模型,也可独立配置
Gemini 约 30% 不是行业比例Claude 内部结构可能随版本变化OpenCode V2 表示不同
NO STANDARDSummary 的请求、role、Tail 和模型选择都没有统一协议

OpenAI:最特殊的 Compaction

20PROVIDER-NATIVE
完整 INPUT ITEMSmessages + tools
+ reasoning / other items
→
SERVER PASSPOST
/responses/compact
→
CANONICAL CONTEXTencrypted compaction item
+ 可能保留的旧 items
→
Agent-side SummaryHistory → 可读 SummaryRuntime 选择、生成并回填字段通常可读、可定义
OpenAI Provider-nativeInput items → 服务端 Compaction PassProvider 返回 canonical Contextencrypted item 不透明、不可编辑

不要解析不要编辑不要删减不要重新摘要原样传递 compacted.output

官方未公开内部 Compaction Prompt · 摘要模型 · 精确选择算法 · encrypted content 的语义结构
MACHINE STATE返回的不是“给人看的摘要”,而是下一请求必须携带的 canonical state

从增量状态机理解模型推理

21INCREMENTAL STATE
工程抽象固定 Model固定 Tokenizer固定输入协议不代表 Prompt 必须逐 Token 串行计算
S₀A →S(A)B →S(A,B)C →S(A,B,C)
从 S(A) 分叉X →S(A,X)C →S(A,X,C)D →S(A,X,C,D)
当前 Prefix State→下一个 Token 的概率分布→Runtime 选择 Token↩︎作为新输入,继续推进状态
HIT恢复状态,只算新后缀
已缓存A + B→ S(A,B)
新请求A + B + D + E→ 只计算 D + E
FORK首个差异后全部重算
旧序列A + B + C + D旧分支
新序列A + X + C + D复用 S(A);重算 X + C + D
KV CACHE各层、各历史位置的 K / V 是可复用状态的主体位置 · 页表等元数据负责组织
EXACT PREFIX相同前缀复用状态;从第一个不同 Token 开始沿新分支计算

已知输入批量算,未知输出逐步算

22TRANSFORMER · KV CACHE
rendered inputt₀t₁t₂…tₙ→Transformer
01PREFILL处理已有输入
t₀t₁t₂t₃…tₙ

同一层内,多个 prompt 位置可批量计算;层与层之间仍顺序执行。

02DECODE逐个生成
tₙ₊₁→tₙ₊₂→tₙ₊₃→…

下一个 token 依赖已经生成的前缀,天然更串行。

EACH LAYER · ATTENTION
Q发起匹配K被匹配V取回表示

新 token 仍产生新的 Q / K / V,并用 Query 关注旧 Keys。

保存已处理 token 的K / V→
GPU MEMORYKV CACHE
Layer 1K₀…KₙV₀…Vₙ
Layer 2K₀…KₙV₀…Vₙ
………
TRADE-OFF少做重复计算,但 Context 越长,KV 的存储与读取成本越高

跨请求复用:只认最长相同前缀

23CROSS-REQUEST CACHE
REQUEST 1A · system + toolsB · historyC · user #1完整 Prefill → 写入 K/V
从输入开头逐 token 比较LONGEST EXACT PREFIX首个不同 token
REQUEST 2A · system + toolsB · historyD · user #2复用 A + B;只 Prefill D
HITA + B复用每层对应的 K / V
MISS / NEWD从分叉点开始重新计算
EXACT TOKENSrenderer → tokenizer不是“语义差不多”
systemmessagestools / schemaimagesspecial tokens都可能进入 Prefix
RULE相同文本不够;模型最终看到的 token 前缀必须一致

Prefix Cache:三种“从哪里命中”

24THREE IMPLEMENTATIONS
01固定 Token BlocksAUTO
ABCD…

每个完整定长 block 自动形成候选点;沿 parent hash 找最长相同 block prefix。

细粒度、无需标记;差异发生在 block 内时,通常只能退回上一完整块。

02BreakpointsSELECTED
system◆ BP1project◆ BP2chat

只在选定位置写入或检查“从开头到这里”的累计前缀。

可控、可分层;未选中的中间位置不保证成为独立命中点。

03命名缓存对象BY ID
create(A+B)→cache/123request(cache/123, C)

先提交稳定内容并创建资源;后续请求显式引用 cache ID。

复用更确定;要管理不可变内容、模型绑定、TTL、权限与费用。

逻辑机制 ≠ 物理布局Breakpoint 或命名对象底层仍可能使用固定大小的 KV pages;API “block” 也不等于物理 page。
NOT A FOURTH TYPEChunked Prefill 只调度未命中的 suffix,不决定 Prefix 如何匹配

主流供应商:公开到哪一层?

25PROVIDER LANDSCAPE
供应商 对外机制 公开门槛 / 粒度 生命周期
OpenAI 早期自动增量;GPT-5.6+ 隐式 / 显式 breakpoint GPT-5.6+ 最短 1,024 tokens;早期命中量按 128-token 增量报告 GPT-5.6+ 默认 30 分钟;早期依 retention
Anthropic 自动或最多 4 个 content-block breakpoints 模型相关:512–4,096 tokens;读取向前检查最多 20 个内容块 默认 5 分钟;可选 1 小时;命中刷新
Gemini API 2.5+ 自动隐式;显式为命名 CachedContent 隐式:2.5 为 2,048;当前 3.x 为 4,096 tokens 显式默认 1 小时;隐式未公开
DeepSeek 自动硬盘前缀单元缓存 现行固定间隔未公开;64 tokens 仅是 2024 历史方案 不活跃后通常数小时至数天,非固定 SLA
Kimi 自动、完全一致的前缀匹配 前一请求 prompt > 256 tokens;内部粒度未公开 自动管理;数值未公开
GLM 自动隐式“相同或高度相似内容”缓存 最小长度、粒度、精确算法均未公开 仅说明过期后重算
截至 2026-08-24API content block / 命中报告增量 / breakpoint≠服务内部物理 KV page
UNKNOWN MEANS UNKNOWN供应商没公开物理 block size,就不能从计费粒度或 API 名词反推

改一个 Tool,为什么旧 History 也命不中?

26TOOLS → CACHE MISS
P₁ = S + T₁ + HP₂ = S + T₂ + H + N
上一轮S · stable systemT₁ · tools v1H · long history
↑首个不同 tokenname / description / schema / order / whitespace
下一轮S · stable systemT₂ · tools v2H · same text, new K/VN
修改 Tool definitions→前缀在差异处断开→其后的 H 按新前缀重算→只保留差异前的命中
不是“文字相同就能接回”H 的 K/V 条件是 S + T;T 变了,H 的状态也变了。
也不是“旧缓存被删除”这是当前新请求逻辑 miss;旧分支能否再次命中取决于 TTL、eviction 和路由。
FIRST DIFFERENCETools 越靠前、History 越长,一次 schema 变化需要重算的 suffix 越大

Tool Definitions:放头,还是放尾?

27HEAD vs TAIL
A前置 ToolsS + T + H
R1 · S + T + H₀R2 · S + T + H₀ + D₁R3 · S + T + H₀ + D₁ + D₂
稳定 Tools:天然形成增长的 append-only prefix
动态 Tools:前部变化让后续长 History 重算
B后置 ToolsS + H + T
R1 · S + H₀ + TR2 · S + H₀ + D₁ + T旧 T 与新 D₁ 在同一位置分叉
动态 Tools:变化靠后,可保住更长 History prefix
每轮移动同一段 T:也不是真正 append-only
工作负载 更合理的策略
少量、长期稳定的核心 Tools 保持前置、顺序和序列化稳定
大型、频繁变化的 Tool catalog 固定 meta-tools,JIT discovery;或在 epoch 边界成批切换
模型已经按固定 Tool 模板训练 服从 API / chat template;不能只改 Jinja 假设行为等价
WORKLOAD没有永远正确的位置:稳定性、History 长度与训练协议共同决定

Cache 塑造的 Context

28IDEAL CONTEXT
HEAD重要 · 稳定 · 低频变化
Base instructions安全 / 输出协议稳定 Tool definitions项目硬约束

开头位置优势 + 最长 Prefix Cache reuse

MIDDLE有关 · 较旧 · 应压缩
Continuation state压缩背景 / 计划短 Raw Window

最容易受位置效应和干扰影响,所以必须“瘦”

TAIL重要 · 当前 · 高频变化
Current user requestJIT retrieval最新 Tool Result / Error / DiffGeneration cursor

尾部位置优势;变化只影响短 suffix

OUTSIDE CONTEXT完整 History大文件 / 完整日志过期与无关内容Artifacts需要时检索 → Tail
稳定 Head+本 Epoch append-only trajectory→Compaction = 有计划的 Cache Break→新 Epoch
逻辑布局必须服从 API、chat template、后训练协议和因果顺序;目标是联合优化正确率、信息利用、Cache reuse、延迟成本与可恢复性。
DESIGN RULE稳定且重要的放头部;当前原始证据放尾部;旧信息压成短中部;无关信息移出去

指定信息如何跨越 Compaction

29RECALL AFTER COMPACTION
CONTEXT OUTSIDE不受当前 Compaction 影响的副本文件 · Memory Store · 完整 History · Artifact
“请摘要记住它”≠可靠的跨越机制摘要无法稳定保证某个细节一定被保留
01Runtime 确定性加载

按约定文件、路径条件、scope 或其他固定规则加载。

不依赖语义相关性判断;固定条件满足时保证加载。

02Runtime 选择性预取

主模型调用前,由 Runtime 的检索或召回机制选择候选。

更节省;预取器未命中时模型完全看不到。

03模型发起 Retrieval

模型调用文件、Memory 或 History Search Tool。

最灵活;可能“已经忘了,也想不起要检索”。

位置不固定三种方式描述谁决定加载与何时加载,不规定最终位于 Head、请求附近还是 Tail
RECALL, NOT HOPE跨越 Compact 的不是摘要承诺,而是可以再次召回的窗口外副本

确定性加载:谁负责把规则放回来?

30DETERMINISTIC LOADING
约定文件→发现顺序 / Scope→Runtime 注入→Compact 后重建
Agent 支持的约定文件 Context 位置与 Compact 后行为
Codex AGENTS.override.md · AGENTS.md · configurable fallbacks 启动时构造全局到当前目录的 instruction chain;同一 Session 内 Compact 后行为未公开
Claude Code CLAUDE.md · .claude/CLAUDE.md · CLAUDE.local.md · .claude/rules/*.md root / ancestor 位于早期 Project Context,压后重载;nested 规则需再次触达路径
OpenCode AGENTS.md · fallback CLAUDE.md · configured instructions root 每个普通 step 重读、位于 System;nested 跟随 Read Result,不保证重载
Gemini CLI GEMINI.md · configurable context.fileName global / workspace Context 压后重建;nested 位于 Tool Result,可能只剩摘要
Cursor AGENTS.md · .cursor/rules/*.mdc 适用 Rules 位于 Context 开头;公开文档未说明 Compact 后重建边界
Windsurf / Devin AGENTS.md / agents.md · .devin/rules/ · .windsurf/rules/ root 每条消息提供;子目录规则按 glob 注入;内部 Compact 边界未公开
Cline .clinerules/ · root AGENTS.md · ~/.agents/AGENTS.md 无条件 Rules 位于 System;条件 Rules 按 paths 重新匹配;无 nested AGENTS 证据
GitHub Copilot .github/copilot-instructions.md · .github/instructions/*.instructions.md · AGENTS.md repository / applyTo 规则自动加入请求;准确 role 与 Compact 后恢复未公开
HEAD副本不参与摘要,或由 Runtime 压后重建
HISTORY路径规则进入 Tool Result 后,仍可能只剩摘要
BOUNDARY文件支持、注入位置和 Compact 恢复是三个不同问题
FILE ≠ GUARANTEE支持约定文件,不等于其中每份正文都能自动跨越 Compaction

渐进式披露:稳定入口,按需正文

31PROGRESSIVE DISCLOSURE
ROOT INDEX始终进入 Head
ALWAYS修改代码后运行相关测试
WHEN数据库 schema → 读 docs/agent/database.md
WHEN鉴权 / 权限 → 读 docs/agent/security.md
WHEN发布 / 回滚 → 读 docs/agent/operations.md
任务命中条件→Read Tool→
database.md窗口外
security.md按需读取 → Tail
operations.md窗口外
@file import加载时立即展开全文不节省首轮 Context
path / glob / decisionRuntime 判断并注入选择性预取
when → read path模型命中后调用 Tool模型发起 Retrieval
Compact 后索引重新出现→仍能再次发现路径→正文需要时重新读取
SHORT INDEX索引同时写清触发条件与路径;详细知识留在窗口外

其他 Memory 方案:谁决定召回?

32MEMORY LANDSCAPE
01Runtime 确定性加载
Letta

挂载的 Memory Blocks 每轮重新进入 Context;模型还可另行调用 Recall。

固定条件满足即加载,不依赖语义相关性判断

02Runtime 选择性预取
Mem0

接入方可在主模型调用前执行 search 并注入命中项。

Zep

接入方可在调用前获取组装好的 Context Block。

Supermemory

Wrapper 可先搜索相关 Memory,再自动加入请求。

这里特指主模型调用前已经完成的选择与注入

03模型发起 Retrieval
Claude Code Auto Memory

Runtime 重载索引,模型按需读取 topic 文件。

Gemini CLI Project Memory

Runtime 重建索引,模型按需读取详细文件。

Cline Memory Bank

Rules 提醒模型读取与当前任务相关的 Markdown。

索引可确定性恢复;正文是否读取仍由模型决定

?自动召回,机制未公开
Codex Local Memories

可注入未来 Session;候选选择机制未公开。

Windsurf Memories

会自动召回相关 Memory;选择机制未公开。

GitHub Copilot Memory

会召回并验证相关事实;选择机制未公开。

Devin Knowledge

按 Trigger 自动召回;判断发生位置未公开。

共 11 个具体实现按主要召回路径归栏;混合能力写在产品说明中
PERSISTED ≠ VISIBLEStore 中保存着,不等于下一次模型调用一定看得见

Skill:Catalog 常驻,正文按需进入

33SKILL LIFECYCLE
SKILLinstructions + references + scripts + assets不是 Tool · 不会自行执行
METADATASkill Catalog短 · 稳定 · 可发现
namedescriptionpath
Session 重启+Compact 后重建→Runtime 确定性加载到 Head

告诉模型:有哪些 Skill、何时值得加载、从哪里加载。

BODYSKILL.md完整 · 专用 · 按需
默认位于 Context Outside用户指定 / 模型按 description 选择
激活→正文进入 Conversation / Tool Result

references 继续按需读取;scripts 由 Runtime 或 Tool 执行。

Catalog 仍在≠正文仍在 Context正文进入 History 后可能被摘要;需要时可重新激活
具体 API role、去重和正文压后恢复由 Runtime 决定;Catalog 与正文必须分开讨论。
DISCOVER → ACTIVATEMetadata 负责“找到并选择”;正文负责“具体怎么做”

主流 Agent 的 Skill 实现对照

34SKILL IMPLEMENTATIONS
AgentCatalog 位置激活后的正文重复激活Compact 后恢复
Codex初始 Context
role 未公开
未公开未公开未公开
Claude Code早期 Context
+ Skill Tool
Conversation message相同正文仅加短提示自动重挂载
单项 5k / 合计 25k
Gemini CLISystem Promptactivate_skill
Tool Result
可重复未发现专用恢复
GitHub Copilot CLIAgent Context
位置未公开
Agent Context
role 未公开
未公开未公开
OpenCodeSystem
<available_skills>
skill Tool Result可重复随 History 压缩
不自动重载
OpenHands前部
<available_skills>
invoke_skill
Tool Result
可重复未发现正文恢复
Cursor启动时发现
位置未公开
附着到一条 message未公开未公开
共同点 Catalog 先进入,正文命中后才加载关键差异 正文进入哪里,以及 Compact 后是否恢复
DISCOVERY IS SHARED支持 Skill,不代表正文拥有相同的 Context 生命周期

Subagent

35CONTEXT ISOLATION
SUBAGENT独立 Agent Session自己的 Current Context · History · Tools · Agent Loop
模型发出 Agent / Task Tool Call→Runtime启动并调度独立 Session→结果作为 Tool Result 返回
TIME → 主 Agent Subagent 1 独立 Agent Loop · PRIVATE CONTEXT Subagent 2 独立 Agent Loop · PRIVATE CONTEXT ① 启动 S1 Task Packet ② 启动 S2 Task Packet ③ S1 完成 Evidence Packet ④ S2 完成 Evidence Packet
DELEGATE → RUN → RETURN主 Agent 负责委派与综合;每个 Subagent 独立完成自己的 Agent Loop

Subagent 的三类用法

36THREE USE CASES
01隔离大量细节
Task Packet→Worker→Evidence Packet

网页正文、日志、搜索过程和失败重试停留在 Worker;主 Context 只保留结论与证据指针。

成立条件:Worker 内部信息 ≫ 跨边界返回信息

02并发缩短经过时间
Worker AWorker BWorker C
并发时间 ≈ max(T₁,T₂,T₃) + 协调开销

适合互相独立的模型任务;会减少 Wall-clock Time,但通常增加总 Token 与计算成本。

同一 Context 内的独立 I/O,优先 Parallel Tool Calls

03隔离“不应知道彼此”
Code Agent
实现
SPECTest Agent
独立测试

双方共享规格和验收条件,但初次工作时不读取对方 trajectory;Coordinator 最后合并验证。

必须用 Context、snapshot 或 worktree 隔离,不能只说“请假装没看见”

先问隔离边界,再决定 Agent 数量Tool Call 多,不等于需要更多 Subagent
ISOLATE · PARALLELIZE · BLIND三类收益不同,不能用“多开几个 Agent”一概而论

Subagent:启动方式与成本

37STARTUP & COST
形态Context 从哪里开始与主 History 的关系System Prompt 是否可控常见 Agent / 实现主要成本 / 风险
Fork复制分叉点的完整
Current Context
History 从此分叉
两边独立继续
通常继承主 Session
可追加 Worker 约束
Claude Code状态管理复杂
无关信息也被复制
Fresh稳定 Instructions
+ Task Packet
不继承主 History
任务描述负责交接
由 Runtime 构造
不一定对用户开放
Claude Code 默认CursorGemini CLIClineOpenCodeCopilot CLI实现最简单
主 Agent 要生成完整任务包
Persistent
Specialist
Fresh Context
+ 固定 Agent Profile
通常不继承主 History
只接收短任务
明确可控
独立 Prompt / Tools / 权限
Claude CodeGemini CLIOpenCodeCopilot CLICodex Custom Agents重复背景成本更低
需治理陈旧配置或 Memory
RESUME在原 Worker Session 上继续追加指令

首次可以来自 Fork / Fresh / Specialist 保留 Worker History · 减少重复交接 · 也会继续消耗 Context Window

额外成本=Task Packet+Worker Tool Loop+Evidence Packet+主 Agent 验证
START ≠ CONTINUEFork / Fresh 决定从哪里开始;Resume 决定能否从原 Worker 继续

OpenCode调用Qwen3的真实Context

38REAL CONTEXT · OPENCODE 1.18.21
System Prompt
请求发送
OpenCode default base promptEnvironmentProject / parent AGENTS.mdSkill Catalog
Qwen Template
模板插入
10 Tool definitionsQwen Tool Call protocol
History
消息序列
USER · U1 Calculate the requested expression…ASSISTANT · A1 The result is…⋮USER · Uₙ Current request…
Model
Assistant generation cursor
SYSTEM PROMPT请求中发送的 System Prompt
QWEN TEMPLATE模板插入的 Tools 定义与调用协议。注意,也以 System role 插入和提交
HISTORY按 User / Assistant 顺序构造的消息序列
CURSOR模型开始生成下一个 Assistant message
PAYLOAD → TEMPLATE → CONTEXTAPI 字段的边界,不等于模型最终看到的边界

OpenCode在Compaction前后的Context

39CONTEXT RECONSTRUCTION
BEFORE COMPACT · n=4普通 Context
SYSTEM PROMPT
OpenCode default base promptEnvironmentProject / parent AGENTS.mdSkill Catalog
QWEN TEMPLATE
10 Tool definitionsQwen Tool Call protocol
HISTORY
User U1Assistant · Tool CallTool Result · 完整 SKILL.mdAssistant · Tool CallTool Result · command not foundAssistant 阶段回答 · User U2
MODEL
Assistant generation cursor
COMPACTION · n=5摘要 Contexttools = []
SYSTEM PROMPT
Compaction Agent system prompt
USER REQUEST
Here is the conversation so far:旧事件 transcriptSummary 输出要求
MODEL
Assistant generation cursor
AFTER COMPACT · n=6新 Context Epoch
SYSTEM PROMPT
OpenCode default base promptEnvironmentProject / parent AGENTS.mdSkill Catalog
QWEN TEMPLATE
10 Tool definitionsQwen Tool Call protocol
HISTORY
User · What did we do so far?Assistant · Generated History AbstractRaw tail · User U2Raw tail · Assistant answerUser · Continue…
MODEL
Assistant generation cursor
SUMMARIZE → REBUILDCompact 产生摘要;下一次调用用摘要重建模型可见 Context

从原理推论几个节省 Token 的小技巧

40LESS CONTEXT · LESS RECOMPUTE
01 · CAPABILITY删除无效 Tools 和 Skills

从配置中移除当前 Agent 用不到的能力。

缩短固定 Head · 会话开始前完成
02 · DISCLOSURE缩短 AGENTS.md / CLAUDE.md

常驻永久规则;详细正文按“触发条件 → 路径”读取。

稳定短索引 · 正文按需进入
03 · EPOCH在阶段边界主动 /compact

工作告一段落、旧细节不再需要,或长时间 AFK 之前。

用短状态开启新 Context epoch
04 · ISOLATION一次性复杂工作交给 Subagent

搜索、HTML、日志和失败重试留在 Worker,只返回结论。

保护主 History · 减少后续反复读取
05 · MODEL CACHE连续会话不要来回切便宜模型

不同模型不能直接复用同一份 K/V;短暂切换可能重复 Prefill。

保持主线程模型与 Prefix 稳定
SHORT · STABLE · ISOLATED缩短稳定 Head,隔离一次性轨迹,把 Context 重建集中在阶段边界

我对Agent未来方向的四个预测

41WHAT COMES NEXT
01 · MOST CERTAIN中心化 Agent 系统成为独立基础设施

核心价值是操作全程可审计、权限能够统一配置。Agent 如果只留在个人机器上,很难实现组织级治理。

统一权限→受控执行→完整审计记录
02 · COMPOSITION从单一通用 Agent 走向稳定 Agent 组合
Agent=Model+Prompt+Tools+Skills+权限集

平台维护多个用途明确、配置稳定的 Agent,由任务决定调用哪个组合。

03 · CO-DESIGNAgent 与模型共同适配

Tools、Skills 等新设施需要进入后训练;不同模型对 Prompt、位置和协议的偏好不同,Agent 将维护模型专属 Adapter。

POST-TRAININGRENDERERPARSERPOLICY
04 · EMERGING知识、History 与 Context 分层治理

现实基础:可管理知识库与可搜索 History。
下一步:模型提出保留、丢弃与召回建议,Runtime 验证后管理 Context。

KnowledgeSearchable HistoryManaged Context
STATE · PROFILE · PROTOCOL · CONTEXT未来的 Agent 能力,越来越来自系统,而不只来自单次模型调用

感谢 · Q&A

42HUMAN ↔︎ AGENT ↔︎ HUMAN
THANK YOU 感谢各位的听讲

也感谢各位 Agent 的辅助回答

01 · ASK THE ROOM还有没有 Agent
无法回答的问题?
02 · TALK TO PEOPLE有没有希望和现场其他人
一起交流的问题?