短期记忆
1. 定义与边界
短期记忆(Short-term Memory)是当前线程、会话或任务运行内可见的状态。它通常包括消息历史、工具调用结果、待办事项、临时文件引用、规划步骤和 checkpoint。
短期记忆不是长期用户画像。用户在某一轮说“这次先用英文”可能只是当前任务约束,不能直接写成永久偏好。
2. 为什么重要
短期记忆让 Agent 能完成多轮任务:
- 记住当前目标、约束和已经完成的步骤。
- 在工具调用后把观察结果带回推理。
- 在中断、审批或异常后恢复执行。
- 控制上下文长度,避免完整历史压垮模型。
3. 核心机制
常见存储内容:
| 字段 | 说明 |
|---|---|
messages | 用户、助手、工具消息 |
tool_results | 工具输出摘要和引用 |
plan | 当前任务计划与状态 |
artifacts | 文件、代码、表格、URL 引用 |
interruptions | 等待用户确认或审批的动作 |
last_error | 最近失败原因和恢复建议 |
4. 工程实现
class ThreadState(dict):
thread_id: str
messages: list[dict]
plan: list[dict]
tool_results: list[dict]
artifacts: list[dict]
summary: str | None
version: int
def before_model(state: ThreadState, max_messages: int = 30) -> list[dict]:
recent = state["messages"][-max_messages:]
if state.get("summary"):
return [{"role": "system", "content": "Conversation summary: " + state["summary"]}] + recent
return recent
def after_step(state: ThreadState, event: dict) -> ThreadState:
state["messages"].append(event)
state["version"] += 1
checkpoint(state)
return state
生产系统不要只用进程内 list。至少要有:
thread_id级隔离。- checkpoint 或 session store。
- 乐观锁或版本号,避免并发覆盖。
- 上下文裁剪和摘要策略。
- 恢复和回放能力。
5. 生产实践
- 最近消息优先保留,旧消息通过摘要、事实抽取或 artifact 引用保留。
- 工具返回的长文本不要全量放入短期记忆,只保存摘要、文件 ID、来源和关键片段。
- 用户审批状态要持久化,恢复时必须使用同一 session 或可等价恢复的状态。
- 长任务用
plan.status管理步骤,避免只依赖自然语言 scratchpad。 - 多 worker 部署使用 Redis、PostgreSQL、Dapr state store 或框架提供的持久化 backend。
6. 常见反模式
- 无限追加完整消息,导致成本上升和长上下文退化。
- 把工具大输出直接塞回下一轮模型调用。
- 将当前任务临时偏好自动写入长期记忆。
- 会话状态只存在内存,服务重启后无法恢复。
- 缺少线程隔离,多个会话共享上下文。
7. 评测方法
- 多轮指代成功率:例如“刚才那个文件”“第二个方案”是否解析正确。
- 中断恢复成功率:审批、超时、异常后能否继续。
- 上下文成本:平均输入 token、裁剪后任务成功率。
- 状态一致性:计划、工具结果、最终输出是否匹配。
- 回归测试:同一长对话在摘要前后输出是否保持关键事实。
8. 安全与治理
- 会话状态可能包含敏感信息,要按租户隔离和加密。
- 工具输出是非可信输入,不能因为进入短期记忆就变成系统指令。
- 摘要模型可能遗漏或扭曲关键约束,摘要前后要保留可追溯事件 ID。
- 对包含凭证、密钥、身份证件等内容的消息设置更短 TTL 或禁止持久化。
工程化补强:架构与实现细节
A. 与 RAG 和长期记忆的边界
短期记忆保存的是当前任务仍需要的工作状态:最近消息、计划、工具结果摘要、未完成步骤、错误恢复点和 checkpoint。它不是外部知识库,也不是长期画像。
| 维度 | 短期记忆 | 长期记忆 | RAG |
|---|---|---|---|
| 生命周期 | thread/session 级,任务结束后可压缩或删除 | 跨会话,需审计和复核 | 随文档版本更新 |
| 数据来源 | 当前对话和工具执行 | 多次互动、明确偏好、历史经验 | 文档、网页、代码、数据库 |
| 写入频率 | 每轮或每个 super-step | 低频、需门槛 | ingestion 时批量写 |
| 主要风险 | 上下文膨胀、恢复点不完整 | 错误长期化、隐私风险 | 证据错误、引用漂移 |
| 评测重点 | 恢复成功率、状态完整度、token 节省 | task lift、staleness | recall、faithfulness、citation |
B. 生产级状态流
短期记忆的核心不是“让模型看到所有历史”,而是让 Agent 在有限上下文里保持任务连续性。
C. 推荐 JSON 结构
{
"thread_id": "th_20260509_001",
"checkpoint_id": "ckpt_0008",
"step": 8,
"state": {
"user_goal": "分析代码库并生成修复计划",
"active_plan": [
{"id": "p1", "status": "done", "task": "读取错误日志"},
{"id": "p2", "status": "in_progress", "task": "定位失败模块"}
],
"working_constraints": ["不修改无关目录", "先给出可回滚方案"],
"tool_artifacts": [
{"artifact_id": "log_001", "kind": "tool_output", "summary": "测试在 auth 模块超时"}
],
"last_error": {
"message": "集成测试超时",
"recovery": "先复现 auth 模块测试,再缩小到 token refresh 分支"
}
},
"ttl_days": 7,
"created_at": "2026-05-09T10:30:00+08:00",
"updated_at": "2026-05-09T10:35:00+08:00"
}
长工具输出不应直接进入 state,只保留摘要、对象 ID、来源和必要片段;原始内容放对象存储或 trace store。
D. 写入门槛
| 内容 | 写入短期记忆 | 是否可提升长期 |
|---|---|---|
| 当前目标和约束 | 必须写 | 任务结束后通常不提升 |
| 未完成计划 | 必须写 | 不提升 |
| 工具返回大文本 | 写摘要和引用 | 仅关键经验可提升 |
| 最近失败原因 | 必须写 | 重复出现或有复用价值时写 episode |
| 用户临时口味 | 当前会话可写 | 需要明确长期偏好才提升 |
| 安全/权限变更 | 不由短期记忆决定 | 进入管理员或用户确认流程 |
E. 检索和上下文组装
短期记忆通常不做复杂向量检索,而是按 thread_id 精确读取 checkpoint,再根据任务阶段裁剪。
E.1 LangGraph 短期记忆核对
LangGraph 官方文档把短期记忆描述为 thread 级持久化:状态通过 checkpoint 绑定到一个会话线程,适合多轮对话、中断恢复和查看历史状态。工程设计上,这支持两个判断:
| 设计点 | 落地方式 |
|---|---|
| 线程隔离 | thread_id 是短期状态边界,不能跨用户或跨项目复用 |
| 状态持久化 | checkpoint 保存 graph state,不只是聊天文本 |
| 生产存储 | 原型可用内存,生产应使用持久化 checkpointer |
| 状态管理 | 支持裁剪消息、删除消息、摘要消息和查看 thread history |
因此短期记忆的验收不应只看“能否记住上一句话”,还要看 checkpoint 是否能完整恢复计划、工具 artifact、错误状态和当前约束。
def load_short_term_context(thread_id, stage, token_budget):
checkpoint = checkpointer.get_latest(thread_id)
state = checkpoint.state
selected = {
"goal": state["user_goal"],
"constraints": state["working_constraints"],
"plan": active_items(state["active_plan"]),
"last_error": state.get("last_error") if stage == "recovery" else None,
"recent_messages": trim_messages(state["messages"], token_budget // 2),
}
return compact(selected, token_budget=token_budget)
检索策略按优先级:当前用户明确约束 > 当前计划 > 最近工具结果摘要 > 最近错误 > 低价值闲聊。
F. 压缩与遗忘
| 时机 | 操作 | 验收 |
|---|---|---|
| token 超预算 | 摘要旧消息,保留未解决事项 | 关键约束不丢 |
| 工具结果很长 | 外置原文,保存摘要和 URI | 可回源 fetch |
| 任务完成 | 生成 session summary | 能解释完成了什么 |
| 长时间未活跃 | 归档或删除 checkpoint | 满足保留策略 |
| 用户要求删除 | 删除 checkpoint、缓存和摘要 | tombstone 生效 |
G. 失败模式与修复
| 失败模式 | 早期信号 | 修复动作 |
|---|---|---|
| 恢复后忘记用户约束 | 重启后违反写入范围或格式要求 | 把硬约束放入 state 顶层并优先注入 |
| 上下文膨胀 | 每轮 prompt 越来越长 | 摘要旧消息,工具结果外置 |
| checkpoint 过细 | 写入延迟高、存储暴涨 | 按 super-step 合并写入 |
| checkpoint 过粗 | 中断后丢步骤 | 在工具调用前后保存关键状态 |
| 临时状态污染长期记忆 | 一次性偏好被长期使用 | 提升长期前走 write gate |
| 敏感工具结果残留 | 删除后仍在缓存出现 | 统一缓存失效和删除审计 |
H. 评测指标
| 指标 | 含义 |
|---|---|
| Resume success rate | 中断恢复后能继续完成任务的比例 |
| State completeness | gold 约束、计划、错误、工具 artifact 是否存在 |
| Token saved | 相比全量历史节省的上下文 token |
| Checkpoint latency | 保存/读取 checkpoint 的 p95 延迟 |
| Compaction faithfulness | 摘要是否忠实保留约束和未完成事项 |
| Promotion precision | 从短期提升长期的内容是否真的有长期价值 |
I. 安全治理
- checkpoint 存储按用户、项目、线程隔离,不能跨租户精确读取。
- 工具返回中的 secret、token、PII 在进入 state 前脱敏或外置加密。
- 短期记忆不是权限来源;工具权限必须来自会话授权和后端策略。
- 删除会话时同步删除摘要、缓存、向量副本和对象存储引用。
- 对恢复流程做审计,记录读取了哪个 checkpoint 和注入了哪些状态。
9. 权威资料
- OpenAI Agents SDK Sessions: https://openai.github.io/openai-agents-python/sessions/ (核对日期:2026-05-09)
- OpenAI Agents SDK Sessions for JavaScript: https://openai.github.io/openai-agents-js/guides/sessions/ (核对日期:2026-05-09)
- LangChain Short-term memory: https://docs.langchain.com/oss/python/langchain/short-term-memory (核对日期:2026-05-09)
- LangGraph add memory: https://docs.langchain.com/oss/python/langgraph/add-memory (核对日期:2026-05-09)