简介
会话持久化,就是把Agent对话状态(消息历史、工具调用上下文、会话元数据)保存到存储介质,支持中断后恢复会话,继续之前的对话与工具调用流程。
Claude SDK 本身不自带持久化存储,messages 消息数组就是会话核心状态。
- 适用场景:长任务Agent、多轮工具调用、任务断点续跑、用户跨页面继续对话
- 核心保存对象:完整
messages消息列表、会话ID、创建时间、token统计、自定义业务字段 - 不保存:模型内部记忆,模型无内置状态,所有上下文由传入的 messages 数组决定
区分:Claude Code 的检查点(Checkpoint)是内置会话快照;SDK 需要自己实现会话存储。
前置准备
- Python3.10+ / Node.js18+
- SDK:
anthropic/@anthropic-ai/sdk - 存储可选:本地JSON文件(测试)、SQLite / MySQL、Redis(生产)
核心原理
- 每次API交互后,把新增消息追加到
messages数组 - 将完整 messages 序列化为 JSON,存入数据库/文件,绑定唯一会话ID
- 恢复会话:根据会话ID读取JSON,反序列化得到完整 messages 数组
- 将读取后的 messages 传入SDK接口,继续对话,Agent感知完整历史
- 工具调用场景:
tool_use和tool_result消息块必须完整保存,丢失会导致工具流程断裂
存储方案选型
| 存储方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| JSON文件 | 本地测试、简单脚本 | 无需额外服务,简单 | 并发差,不适合多用户 |
| SQLite | 中小规模单机服务 | 轻量,持久化 | 高并发性能一般 |
| MySQL / PostgreSQL | 正式业务系统 | 稳定,支持查询 | 需要维护数据库 |
| Redis | 高并发对话、临时会话 | 读写极快,支持过期 | 内存成本,数据易丢失(需持久化配置) |
实战1:Python 会话持久化(JSON文件存储)
简易版本:保存会话到本地json文件,实现保存、加载会话
import os import json from pathlib import Path from anthropic import Anthropic client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) SESSION_DIR = Path("./agent_sessions") SESSION_DIR.mkdir(exist_ok=True) # 保存会话 def save_session(session_id: str, messages: list): session_data = { "session_id": session_id, "messages": messages, "updated_at": json.dumps({"time": "now"}), } path = SESSION_DIR / f"{session_id}.json" with open(path, "w", encoding="utf-8") as f: json.dump(session_data, f, ensure_ascii=False, indent=2) # 加载会话 def load_session(session_id: str) -> list | None: path = SESSION_DIR / f"{session_id}.json" if not path.exists(): return None with open(path, "r", encoding="utf-8") as f: data = json.load(f) return data["messages"] # 主会话逻辑 def run_session(): sid = "demo-session-001" messages = load_session(sid) or [{"role": "user", "content": "写一个简单Python工具函数"}] resp = client.messages.create( model="claude-3-5-sonnet-latest", max_tokens=1024, messages=messages ) # 将模型返回消息追加进上下文 messages.append(resp.content[0].to_dict()) print(resp.content[0].text) # 持久化保存 save_session(sid, messages) print(f"会话 {sid} 已保存,下次启动可以继续对话") if __name__ == "__main__": run_session()
实战2:TypeScript 会话持久化(文件存储)
import Anthropic from "@anthropic-ai/sdk";
import fs from "fs/promises";
import path from "path";
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const SESSION_DIR = path.join(__dirname, "agent_sessions");
async function initDir() {
await fs.mkdir(SESSION_DIR, { recursive: true });
}
// 保存会话
async function saveSession(sessionId: string, messages: any[]) {
const filePath = path.join(SESSION_DIR, `${sessionId}.json`);
const data = {
sessionId,
messages,
updatedAt: new Date().toISOString()
};
await fs.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
}
// 加载会话
async function loadSession(sessionId: string) {
try {
const filePath = path.join(SESSION_DIR, `${sessionId}.json`);
const raw = await fs.readFile(filePath, "utf-8");
return JSON.parse(raw).messages;
} catch {
return null;
}
}
async function main() {
await initDir();
const sid = "demo-session-001";
const messages = await loadSession(sid) || [{ role: "user", content: "写一个JS工具函数" }];
const res = await anthropic.messages.create({
model: "claude-3-5-sonnet-latest",
max_tokens: 1024,
messages
});
messages.push(res.content[0]);
console.log(res.content[0].text);
await saveSession(sid, messages);
console.log(`会话 ${sid} 已保存`);
}
main();
工具调用场景持久化重点
工具调用会话,tool_use 和 tool_result 消息块必须完整保存,缺一不可。
完整消息结构示例:
[
{"role":"user","content":"获取当前时间"},
{"role":"assistant","content":[{"type":"tool_use","id":"tu_xxx","name":"get_current_time","input":{}}]},
{"role":"user","content":[{"type":"tool_result","tool_use_id":"tu_xxx","content":"2026-10-11"}]},
]
丢失任意一条 tool_use / tool_result,恢复会话后工具流程直接断裂。
Token 裁剪策略(重要)
会话持续累积,messages 会越来越长,超出模型上下文窗口,导致报错。两种方案:
- 截断策略:保留最近N轮消息,丢弃最早历史(简单,丢失早期信息)
- 摘要压缩策略:定期调用模型,把早期对话压缩成一段摘要,替换原始历史,节省token(推荐长会话)
摘要压缩示例逻辑:
把前面历史对话交给模型,生成对话摘要,用摘要替换旧消息列表,保留最近几轮原始消息。
生产数据库表设计(MySQL示例)
CREATE TABLE agent_session (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
session_id VARCHAR(64) NOT NULL UNIQUE COMMENT '会话唯一ID',
user_id VARCHAR(64),
messages JSON NOT NULL COMMENT '完整消息数组',
total_input_tokens INT DEFAULT 0,
total_output_tokens INT DEFAULT 0,
status TINYINT COMMENT '会话状态:0运行,1完成,2暂停',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
最佳实践
- 会话ID设计:使用UUID作为session_id,避免ID冲突
- 过期清理:给会话设置TTL,长时间未访问自动归档/删除,节省存储与token
- 消息追加原则:每次模型返回、每次tool_result,都要追加并保存,不要覆盖旧消息
- 备份机制:重要会话做备份,防止存储损坏丢失上下文
- 并发锁:多进程同时读写同一会话,增加锁控制,防止消息覆盖
- 会话隔离:不同用户、不同任务会话完全隔离,禁止混用messages数组
常见问题
Q:恢复会话后Agent会忘记之前的内容?
A:只要完整保存所有 messages,Agent就能读取全部历史;如果消息丢失,就会丢失对应上下文。模型本身没有持久记忆,全部依赖传入消息数组。
Q:会话保存后,token开销会不会持续变大?
A:是的,每一轮对话都会增加消息长度。长会话必须做消息压缩或者截断,防止超过模型最大上下文限制。
Q:子代理并行任务,子代理会话需要持久化吗?
A:按需。子代理会话独立于主代理;如果子任务允许断点恢复,单独持久化每个子代理的messages;一次性任务可以不保存。
Q:流式输出如何持久化?
A:流式只是分片返回内容,等完整消息块接收完成之后,再追加保存到会话,不要保存不完整的增量块。
小结
会话持久化核心就是持久化存储完整 messages 消息数组。测试用JSON文件,生产推荐MySQL/Redis。工具调用会话必须完整保存tool_use与tool_result块;长会话需要做消息压缩,防止上下文超限。
0 条笔记