1. Analysis Philosophy¶
本节摘要
LLM 本身是无状态的:每次调用都是一个纯函数 response = f(prompt),不记住上一次的内容。Agent 框架的核心工作就是在 LLM 外部维护一个「状态层」,让无状态的 LLM 表现得像有状态的智能体。本节定义什么是 Agent State、它由哪些组件构成、哪些操作会改变它。
什么是 Agent State¶
LLM 是无 Memory的决策函数——每次 API 调用后内部状态(KV Cache)即丢弃,下次调用从零开始。Agent 要实现多步推理和连贯决策,必须在 LLM 外部构建和维护一个状态层。
Agent State 指:Agent 框架为让 LLM 做出连贯决策而在其外部维护的所有信息。 它包括但不限于 LLM 每次调用时收到的 prompt 内容、可调用的工具集、以及存储在磁盘或内存中的持久化知识。
从形式化角度看,Agent 可建模为一个部分可观测马尔可夫决策过程(POMDP)——Agent 的「状态」永远是环境真实状态的有损压缩。context window 是有限的,不可能装下全部信息。State Management 的核心挑战就是:在有限空间内,维护一个尽可能有用的环境信念。
Agent State 由什么构成¶
Agent State 分布在不同的时间尺度上——有些状态每次 LLM 调用都变化,有些在整个会话内稳定,有些跨会话持久化。
| 组件 | 包含什么 | 时间尺度 | 典型问题 |
|---|---|---|---|
| Context | System prompt、对话历史、环境信息 | 单轮 ~ 会话 | 怎么组装?满了怎么压缩?压缩后恢复什么? |
| Memory | 长期知识、用户偏好、项目约定、自动提取的 Memory | 跨会话 | 记什么?怎么检索?怎么防过时? |
| 工具(Tools) | 可用工具列表、Schema 定义、行为标记 | 会话级(偶尔变化) | 哪些暴露给模型?什么时候动态变化? |
| 技能(Skills) | 可复用的能力模块(SKILL.md) | 会话级(按需激活) | 怎么发现?元数据何时提供?预算怎么控制? |
| Sub-agent | 子 Agent 的生命周期、输入/输出、状态隔离/继承 | 单轮 ~ 会话 | 继承哪些状态?隔离哪些?结果怎么交还? |
| Attachment | 每 turn 动态计算的 Context信息(文件变更、任务提醒等) | 每 turn | 什么时候触发?注入什么?怎么增量更新? |
这些组件最终都汇聚到 LLM 的输入中——但不是简单地全部塞进去,而是经过筛选、压缩、排优先级后注入。
哪些操作影响 State¶
Agent State 不是静态的——它在 Agent 执行任务的全过程中持续变化。影响 State 的操作可以归为四类:
注入(Inject)¶
将信息写入 State,使 LLM 能「看到」:
| 操作 | 影响的 State 组件 | 示例 |
|---|---|---|
| 系统提示组装 | Context | 将身份、规则、环境信息写入 system prompt |
| Memory 召回 | Context + Memory | Sonnet 预取相关Memory 文件,注入用户消息 |
| Skill 列表注入 | Context + Skills | <system-reminder> 中展示可用 Skill |
| 工具池组装 | Tools | 合并内置、MCP、插件工具,传入 API |
| Attachment 注入 | Context | 每 turn 计算文件变更、任务提醒等动态信息 |
| Sub-agent 创建 | Sub-agent | 将父 Agent 的部分状态传递给子 Agent |
更新(Update)¶
在执行过程中修改已有 State:
| 操作 | 影响的 State 组件 | 示例 |
|---|---|---|
| 工具执行结果回灌 | Context | tool_result 追加到对话历史 |
| 动态 Skill 发现 | Skills | 文件操作进入新目录,向上遍历发现新 Skill |
| MCP 热更新 | Tools | 运行时添加/移除 MCP 服务器,工具池重建 |
| 后台Memory 提取 | Memory | Fork Agent 分析对话,写入 AutoMem Memory 文件 |
| Sub-agent 工具过滤 | Tools | 子 Agent 的工具集从父级收紧 |
| Attachment Delta 更新 | Context | Skill 列表、工具变更等只发送增量 |
丢弃(Discard)¶
主动丢弃 State,释放 context window 空间:
| 操作 | 影响的 State 组件 | 示例 |
|---|---|---|
| Context 压缩 | Context | 六层渐进式压缩(从无损清理到 LLM 摘要) |
| 旧 tool_result 清除 | Context | 60 分钟未引用的工具结果文本被清除 |
| Memory 截断 | Memory | CLAUDE.md 超 200 行 / 25KB 时截断 |
| 进程退出 | Context + Sub-agent | 单进程 CLI 退出,对话历史和 Sub-agent 状态消失 |
恢复(Restore)¶
丢弃后重新注入关键信息,防止「失忆」:
| 操作 | 影响的 State 组件 | 示例 |
|---|---|---|
| 压缩后 Rehydration | Context | 恢复最近 5 个文件(50K)+ 活跃 Skill(25K)+ CLAUDE.md |
| 关键约束补注入 | Context | 压缩后重新注入 AGENTS.md 的 Session Startup + Red Lines |
| Memory 验证 | Memory | 召回 Memory 前检查引用的文件路径/函数名是否仍有效 |
| 缓存清理 | Context | 压缩后清除 memoize 缓存,确保重新读取最新状态 |
本报告的分析维度¶
后续章节按状态组件维度展开,每个组件内部追踪其注入、更新、丢弃、恢复的完整生命周期:
graph LR
subgraph persistent ["跨会话"]
Memory
Skills["Skill"]
end
subgraph session ["会话级"]
Tools["工具"]
History["对话历史"]
end
subgraph turn ["每 Turn"]
Attach["Attachment"]
LLM["LLM 决策"]
ToolExec["工具执行"]
end
Memory -->|"召回注入"| LLM
Skills -->|"列表注入"| LLM
Tools -->|"Schema 传入"| LLM
History -->|"消息序列"| LLM
Attach -->|"system-reminder"| LLM
LLM -->|"tool_use"| ToolExec
ToolExec -->|"tool_result 回灌"| History
ToolExec -->|"触发Memory 提取"| Memory
ToolExec -->|"触发 Skill 发现"| Skills
History -->|"压缩 / 丢弃"| History
- Claude Code 专题(Part 2):分析单进程 CLI 架构下各组件的State Management策略
- OpenClaw 专题(Part 3):分析 Gateway 多渠道架构下的对应策略
- 对比分析(Part 4):两者在每个组件上的设计差异与行业共识