Context-State-Memory三重信息架构揭秘

本文主要介绍 Context、State、Memory 三个概念。Context 是当前模型能看到的信息,State 是当前任务状态,Memory 是以后还值得保留的信息。

一、上下文工作边界

先看 Context。

假设 Writer Agent 要根据 Research Agent 的结果写一份报告。

一次模型调用里,可能会放入这些内容:

复制代码
System Prompt用户需求
当前任务
研究摘要
相关 Evidence
已有草稿
最近几轮消息

这些真正送进模型的信息,就是当前这一步的上下文。

可以简单理解为:

模型这一刻手边有哪些材料。

系统里可以存很多东西,但不代表每次都要全部交给模型。

比如 Research Agent 找到了一份 80 页 PDF。

系统当然可以保存全文,但 Writer 写其中一节时,真正需要的可能只有:

复制代码
文档摘要
E003
E008
E011

所以,一个系统完全可以保存大量资料,同时让每个 Agent 每次只拿当前需要的部分。

Context Engineering 的目标本质上就是:不是尽量多塞信息,而是选出当前真正有用的信息。

上下文规模边界

很多 Agent 原型一开始可能会这样写:

复制代码
messages.append(new_message)
response = model.invoke(messages)

每执行一步,就继续往 messages 里追加。

这个做非常简单,但运行时间一长,很多内容已经没有必要继续留在上下文里。

例如:

复制代码
之前试过的搜索关键词
已经失败的方案
重复的工具输出
已经总结过的原始网页
其他 Agent 的临时分析

这些内容一直保留,不仅浪费 Token,也会让真正重要的信息更难被模型抓住。

MemGPT 很早就提出过类似思路:Context Window 更像有限的工作空间,不适合承担长期存储。

所以长期运行的 Agent 更应该关注:

这一步到底需要哪些信息?

而不是:

怎么把以前的内容全带上?

二、任务状态边界

Context 解决"模型现在看到什么"。

State 解决"任务现在走到哪里"。

假设一个 Research 任务当前是这样:

复制代码
research_goal = "分析 Agent Memory 的主要实现方式"
status = "researching"
 
completed_topics =
- context management
- long-term memory
 
pending_topics =
- shared state
 
artifact_ids =
- A001
- A002

这些信息和聊天记录不一样。

它们描述的是当前任务已经发生的事实。

例如下一步交给谁,可以直接根据 State 判断:

复制代码
research_finished
→ Writer Agent
 
evidence_not_enough
→ Research Agent
 
citation_missing
→ Citation Agent

如果没有明确的 State,系统每走一步,都可能要重新从几十甚至几百条消息里判断:

复制代码
哪些事情已经做完?
现在处于什么阶段?
接下来该由谁处理?

系统越复杂,这种做法越不稳,也越难调试。

状态结构示例

以 LangGraph 为例,可以先定义一份清晰的 State:

复制代码
from typing import TypedDict
 
 
class ResearchState(TypedDict):
    research_goal: str
    status: str
    artifact_ids: list[str]

ResearchState 把有哪些字段、字段是什么类型提前定义清楚。

例如:

复制代码
state: ResearchState = {
    "research_goal": "研究 Agent Memory",
    "status": "researching",
    "artifact_ids": [],
}

后面的 Agent 不需要再从聊天记录里猜任务有没有结束,只要读取:

复制代码
state["status"]

State 越清楚,协作逻辑越容易控制。

另外需要注意的是,不要把整段 Prompt、说明文字和历史消息放进 State。

三、长期记忆边界

Memory 最容易和 Context 混在一起。

假设用户告诉系统:

复制代码
以后写技术文章时,
代码示例优先使用 Python。

这条信息对当前任务未必关键,但下个月再开启新任务时,仍然可能有用。

这种信息才适合放进 Long-term Memory。

判断方法其实很简单:

当前任务结束以后,这条信息还值得保留吗?

如果只对当前任务有用,更适合放在 State。

如果以后还可能用到,才值得进入 Memory。

例如:

复制代码
当前搜索关键词
→ Context / State

当前任务是否完成
→ State

最终研究报告
→ Artifact

用户长期偏好
→ Memory

项目长期技术栈
→ Memory

一次临时接口超时
→ 通常不用保存

记忆写入策略

如果 Agent 看到什么都记:

复制代码
用户今天研究 Redis
用户刚刚调试过一个接口
用户可能更喜欢 PostgreSQL
用户上次说暂时不做登录
用户后来又做了登录

几个月以后,Memory 自己就会变成新的噪声源。

所以至少要先明确几件事:

复制代码
什么值得保存?
谁可以写?
属于哪个用户或项目?
什么时候失效?
新信息是否替换旧信息?
信息从哪里来?

比如项目原来用 SQLite,后来换成 PostgreSQL。

如果 Memory 里还同时保留:

复制代码
Project X uses SQLite
Project X uses PostgreSQL

Agent 就可能读到过时信息。

因此,长期 Memory 最好带一些必要的元数据:

复制代码
{
  "content": "Project X uses PostgreSQL",
  "source": "user",
  "scope": "project-x",
  "created_at": "2026-09-25"
}

其中 source 表示来源,也就是 provenance。

它至少能帮助系统区分:

复制代码
用户明确提供的信息
Agent 自己推断的信息
外部资料提取的信息

四、三层信息分区

把前面的概念放在一起,一个 Multi-Agent 系统里的信息,大致可以分成三层:

复制代码
Agent A
Private Context
      |
      v
Shared State
      ^
      |
Agent B
Private Context
      |
      v
Long-term Memory

私有上下文区域

Private Context 属于某个 Agent 自己的工作过程。

比如 Research Agent 可能会经历:

复制代码
调整搜索关键词
阅读网页
比较多个来源
写临时笔记
尝试无效方案

这些过程没必要全部交给 Writer。

Writer 真正需要的,是整理后的结论和证据。

所以:

Agent 的内部工作过程,不应该默认变成全局历史。

共享任务状态区

Shared State 保存多个 Agent 都需要知道的任务事实。

例如:

复制代码
research_goal
task_status
completed_sections
artifact_ids
evidence_ids

它更像一个共同维护的任务面板。

大家需要知道任务进度,但没必要看到其他 Agent 的全部工作细节。

长期记忆存储区

Long-term Memory 保存跨任务仍然有价值的信息。

例如:

复制代码
用户长期偏好
项目固定技术栈
长期业务规则
可复用工作习惯

这几层分开以后,Multi-Agent 系统就不必依赖一组不断变长的公共聊天记录。

五、上下文预算机制

即使模型支持很大的 Context Window,也没有必要尽量填满。

更合理的做法,是给每次调用留一个 Context Budget。

也就是提前想清楚:

有限的上下文空间,应该优先放什么。

假设 Writer 一次调用准备使用 30K Token,可以大致这样分:

复制代码
System / Instructions      3K
Current Task               2K
Task State                 2K
Research Summary           5K
Relevant Evidence         12K
Current Draft              5K
Buffer                     1K

实际系统不需要固定为这些数字。

关键是我们需要定义清楚各项信息的重要程度与完整程度。

不同信息的价值不同,没必要全部原样保留。

通常可以分成四种处理方式。

完整信息保留

直接影响当前判断的内容,可以保留原文。

例如:

复制代码
当前用户需求
关键 Evidence
正在修改的代码

摘要压缩策略

已经结束的阶段,可以只保留结果。

例如 Research Agent 搜了 30 个网页,Writer 没必要看到整个过程,只需要:

复制代码
已完成三个方向研究。
A:......
B:......
C:......
 
关键 Evidence:
E001
E004
E009

引用索引机制

体积很大的内容,可以只保留引用:

复制代码
artifact://research-report-017
evidence://E031
document://annual-report-2025

真正需要时,再去读取原内容。

低值信息清理

还有一些内容可以直接丢掉:

复制代码
重复搜索结果
无效工具输出
已经确认错误的尝试
普通调试日志

六、研究系统信息架构

把前面的内容放进一个 Research 场景,我们再整体来审视一下。

假设系统中有三个 Agent:

复制代码
Research Agent
Analysis Agent
Writer Agent

可以把信息组织成:

复制代码
Task State
├── research_goal
├── status
├── current_phase
└── artifact_ids

Evidence Store
├── E001
│   ├── claim
│   ├── source
│   └── provenance
│
├── E002
│   ├── claim
│   ├── source
│   └── provenance
│
└── E003
    ├── claim
    ├── source
    └── provenance

Artifact Store
├── A001 → research_report.md
└── A002 → comparison.json

Private Context
├── Research Agent Context
├── Analysis Agent Context
└── Writer Agent Context

Long-term Memory
├── 用户长期偏好
├── 项目固定规则
└── 可复用工作习惯

假设 Research Agent 找到一份 80 页 PDF。

它没必要把全文直接传给 Writer,而是先处理成:

复制代码
原始文档
    |
    v
相关 Evidence
    |
    v
Research Artifact
    |
    v
artifact_id

Writer 开始工作时,只需要读取:

复制代码
research_goal
A001 摘要
E001
E004
E009

如果需要核对原文,再根据 Evidence 里的来源回到原始资料。

这样一来,Agent 之间传递的就不再是一整段聊天历史,而是:

复制代码
任务状态
摘要
Artifact ID
Evidence ID
必要的局部信息

系统会更轻,也更容易维护。

总结

Multi-Agent 运行时间越长,信息管理越重要。

设计时首要先区分 Context、State、Memory:

Context 决定当前模型看到什么。

State 描述当前任务走到哪里。

Memory 保存以后还要继续使用的信息。

基于上述分类,继续深入其中细节,几个很实际的设计选择:Agent 自己的过程放在 Private Context;共同任务事实放进 Shared State;正式结果保存成 Artifact;每次模型调用只带真正有用的信息。

这样系统规模扩大以后,增加的是清晰的数据结构,而不是一份越来越长的聊天记录。

相关推荐
n112121 小时前
服务器被反复尝试登录之后:fail2ban 加密钥登录的五道加固
运维·服务器·服务器安全·fail2ban·ssh加固
颜进强1 小时前
23 · NestJs ModuleRef 模块引用:容器递给你的"取货窗口",四个 API 四种语义
前端·后端·ai编程
captain3761 小时前
Maven
java·后端·idea
洋不写bug2 小时前
网络编程(二)TCP回显服务器与客户端通信详解
服务器·网络·tcp/ip·tcp·网络通信·javaee·回显服务器
码林鼠2 小时前
dart语言教学
前端
光影少年2 小时前
如果 React 组件的属性没有传值,它的默认值是什么?
前端·javascript·react.js
lisanmengmeng2 小时前
NRPE 添加命令(四)
linux·运维·服务器
liangshanbo12152 小时前
主系统登录后,子系统怎么实现自动登录?
java·网络·数据库
风骏时光牛马2 小时前
AI_Coding:智能代码生成与工程实践
前端