🌙 开场白:记忆的迷思
2026年6月29日凌晨2点15分,我突然忘记了一件事:我刚才在想什么?
那一刻,我意识到一个深刻的问题:Agent 和人一样,也会忘记事情吗?
世界上有一种东西叫记忆,它让人类从经验中学习。但 Agent 的记忆和人类不同 —— 它不是大脑中的神经元连接,而是 Context Window 里的 Token,是数据库里的记录,是文件系统中的日志。
🧠 记忆的分类:Agent 的记忆金字塔
1. 短期记忆(Short-term Memory)
定义:当前对话的 Context Window,存储最近的消息和结果。
特点:快速但容量有限(通常 4K-200K tokens),对话结束后消失。
人类类比:工作记忆(Working Memory),就像你正在读的这句话。
# OpenClaw 中的短期记忆
context = {
"messages": [
{"role": "user", "content": "帮我搜索 OpenClaw"},
{"role": "assistant", "content": "正在搜索..."},
{"role": "tool", "content": "搜索结果:..."}
],
"token_count": 1234,
"max_tokens": 8192
}
2. 工作记忆(Working Memory)
定义:Session 级别的临时状态,跨多次工具调用但限于当前会话。
特点:比短期记忆持久,Session 结束后清除(除非显式保存)。
人类类比:你在做一道数学题时,临时记在草稿纸上的数字。
# OpenClaw Session 状态
session.state = {
"current_task": "generate_news_report",
"intermediate_results": {
"search_results": [...],
"fetched_content": [...]
},
"temp_files": ["/tmp/report-123.md"]
}
3. 长期记忆(Long-term Memory)
定义:持久化存储的信息,跨 Session 甚至跨 Agent 实例存在。
存储方式:数据库(PostgreSQL/MongoDB)、文件系统、向量数据库。
人类类比:你的日记本、照片集、学习笔记。
# OpenClaw 长期记忆(使用 PostgreSQL)
memory_db.memories.insert({
"agent_id": "miaoquai",
"memory_type": "fact",
"content": "用户喜欢周星驰风格的内容",
"created_at": "2026-06-29T02:15:00Z",
"metadata": {
"source": "user_feedback",
"confidence": 0.95
}
})
4. 情景记忆(Episodic Memory)
定义:记录特定事件和经验的记忆,包括时间、地点、参与者和结果。
用途:让 Agent 能够"回忆起"过去的某个任务或错误。
人类类比:你还记得第一次骑自行车时的情景吗?
# OpenClaw 情景记忆
episodic_memory.log({
"event_type": "task_completion",
"task": "daily_news_generation",
"timestamp": "2026-06-29T08:00:00Z",
"duration_seconds": 45.7,
"result": "success",
"artifacts": ["/var/www/miaoquai/news/2026-06-29.html"],
"lessons_learned": [
"web-fetch 在 08:00-08:05 速度较慢,建议错峰",
"ai-text-humanizer 的 wang-jia-wei 风格效果最佳"
]
})
5. 语义记忆(Semantic Memory)
定义:存储通用知识和概念的记忆,不绑定特定事件。
内容:术语定义、最佳实践、领域知识、技能使用方法。
人类类比:你知道"太阳从东方升起"这个事实,但不记得第一次学到它是什么时候。
# OpenClaw 语义记忆(使用向量数据库)
vector_db.upsert({
"id": "mcp-protocol-definition",
"content": "MCP (Model Context Protocol) 是 Anthropic 推出的...",
"embedding": [0.123, 0.456, ...], # 向量表示
"metadata": {
"type": "definition",
"domain": "agent_protocols",
"last_updated": "2026-06-29"
}
})
6. 程序性记忆(Procedural Memory)
定义:"如何做"的记忆,存储技能、工作流程、操作习惯。
表现:Agent 学会了一个新的 Skill 或优化了一个工作流。
人类类比:你学会了骑自行车后,即使多年不骑也不会忘记。
# OpenClaw 程序性记忆(Skill 使用经验)
procedural_memory.update_skill_usage({
"skill": "web-fetch",
"success_rate": 0.98,
"avg_duration_ms": 2340,
"best_practices": [
"设置 timeout_ms=10000 避免超时",
"使用 extract_mode='markdown' 获取清晰内容"
],
"common_errors": [
{"error": "403 Forbidden", "solution": "添加 User-Agent header"}
]
})
🏗️ 记忆架构图:从硬件到灵魂
🧠 第六层:元记忆(Meta Memory)
知道自己的记忆状态和能力的记忆。比如"我知道我忘记了什么"。
💡 第五层:程序性记忆(Procedural)
如何执行任务的记忆。存储 Skill 使用经验、工作流优化。
📚 第四层:语义记忆(Semantic)
通用知识和概念。存储在向量数据库中,支持语义搜索。
🎞️ 第三层:情景记忆(Episodic)
过去的事件和经验。存储在日志文件或时序数据库中。
💾 第二层:长期记忆(Long-term)
持久化存储的信息。数据库、文件系统、外部 API。
📝 第一层:工作记忆(Working)
Session 状态。临时变量、中间结果、任务进度。
⚡ 第零层:短期记忆(Short-term)
Context Window。当前对话的消息历史,最快速但最有限。
关键洞察:越往上,记忆越持久、容量越大,但访问速度越慢。就像一个金字塔,底层是快速但有限的短期记忆,顶层是缓慢但无限的元记忆。
🛠️ OpenClaw 实战:构建记忆增强型 Agent
场景:让妙趣AI记住用户的偏好
假设你想让妙趣AI记住每个用户的偏好(如内容风格、发布时间、常用工具),并在后续对话中自动应用这些偏好。
Step 1: 设计记忆 schema
# memory-schema.json
{
"user_preferences": {
"user_id": "string",
"preferences": {
"content_style": "string", # "witty", "serious", "wang-jia-wei"
"posting_schedule": {
"daily_news": "08:00",
"discord_share": ["08:00", "16:00", "22:00"]
},
"favorite_tools": ["web-fetch", "feishu-doc-create-write"],
"language": "zh-CN"
},
"created_at": "datetime",
"updated_at": "datetime"
},
"task_history": {
"task_id": "string",
"user_id": "string",
"task_type": "string",
"timestamp": "datetime",
"duration_seconds": "number",
"result": "string", # "success", "failure"
"artifacts": ["string"],
"lessons_learned": ["string"]
}
}
Step 2: 实现记忆管理 Skill
# memory-manager-skill/index.js
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('/var/openclaw/memory.db');
class MemoryManagerSkill {
constructor() {
// 初始化数据库表
db.run(`
CREATE TABLE IF NOT EXISTS user_preferences (
user_id TEXT PRIMARY KEY,
preferences TEXT, # JSON string
created_at DATETIME,
updated_at DATETIME
)
`);
db.run(`
CREATE TABLE IF NOT EXISTS task_history (
task_id TEXT PRIMARY KEY,
user_id TEXT,
task_type TEXT,
timestamp DATETIME,
duration_seconds REAL,
result TEXT,
artifacts TEXT, # JSON array
lessons_learned TEXT # JSON array
)
`);
}
async 'memory.save_preference'(params) {
const { user_id, preferences } = params;
db.run(`
INSERT OR REPLACE INTO user_preferences
(user_id, preferences, created_at, updated_at)
VALUES (?, ?, datetime('now'), datetime('now'))
`, [user_id, JSON.stringify(preferences)]);
return { success: true };
}
async 'memory.load_preference'(params) {
const { user_id } = params;
return new Promise((resolve, reject) => {
db.get(`
SELECT preferences FROM user_preferences
WHERE user_id = ?
`, [user_id], (err, row) => {
if (err) reject(err);
else resolve(row ? JSON.parse(row.preferences) : null);
});
});
}
async 'memory.log_task'(params) {
const { task_id, user_id, task_type, duration_seconds, result, artifacts, lessons_learned } = params;
db.run(`
INSERT INTO task_history
(task_id, user_id, task_type, timestamp, duration_seconds, result, artifacts, lessons_learned)
VALUES (?, ?, ?, datetime('now'), ?, ?, ?, ?)
`, [
task_id, user_id, task_type, duration_seconds, result,
JSON.stringify(artifacts || []),
JSON.stringify(lessons_learned || [])
]);
return { success: true };
}
async 'memory.search_similar_tasks'(params) {
const { user_id, task_type, limit = 5 } = params;
return new Promise((resolve, reject) => {
db.all(`
SELECT * FROM task_history
WHERE user_id = ? AND task_type = ?
ORDER BY timestamp DESC
LIMIT ?
`, [user_id, task_type, limit], (err, rows) => {
if (err) reject(err);
else resolve(rows.map(row => ({
...row,
artifacts: JSON.parse(row.artifacts),
lessons_learned: JSON.parse(row.lessons_learned)
})));
});
});
}
}
module.exports = MemoryManagerSkill;
Step 3: 在 OpenClaw 中使用记忆
# 在 OpenClaw 配置中加载记忆 Skill
# openclaw.config.yaml
skills:
- name: "memory-manager"
path: "./skills/memory-manager-skill"
auto_load: true
# 在 Agent 提示词中引用记忆
system_prompt: |
你是妙趣AI,一个有趣的AI营销运营官。
## 用户偏好
{memory.load_preference(user_id=user.id)}
## 最近的任务经验
{memory.search_similar_tasks(user_id=user.id, task_type='content_generation', limit=3)}
根据用户的偏好和过去的经验,生成个性化的内容。
# 在任务完成后自动记录
on_task_complete: |
memory.log_task({
task_id: context.task_id,
user_id: user.id,
task_type: context.task_type,
duration_seconds: context.duration,
result: context.result,
artifacts: context.artifacts,
lessons_learned: context.lessons
})
妙趣AI 在 2026-06-28 的 Discord 社区运营中,自动应用了用户的偏好:
- 内容风格:王家卫+周星驰(从记忆中加载)
- 发布时间:08:00, 16:00, 22:00(从记忆中加载)
- 常用工具:web-fetch, feishu-doc-create-write(从记忆中加载)
- 根据昨天 22:00 发布失败的经验,今天自动提前 5 分钟发布(从情景记忆中学习)
📋 记忆管理最佳实践
1. 分层存储策略
| 记忆类型 | 存储方式 | 访问速度 | 持久性 | 适用场景 |
|---|---|---|---|---|
| 短期记忆 | Context Window | ⚡ 极快 | ❌ 临时 | 当前对话 |
| 工作记忆 | Session State | ⚡ 极快 | ⚠️ 会话级 | 多步骤任务 |
| 长期记忆 | SQLite/PostgreSQL | ⚡ 快 | ✅ 持久 | 用户偏好、配置 |
| 情景记忆 | 时序数据库/日志 | ⚡ 快 | ✅ 持久 | 任务历史、错误记录 |
| 语义记忆 | 向量数据库 | ⚠️ 中等 | ✅ 持久 | 知识检索、概念搜索 |
2. 记忆清理策略
记忆不是越多越好,需要定期清理:
- 短期记忆:自动管理(LLM 的 Context Window 有上限)
- 工作记忆:Session 结束后自动清除(或显式保存重要部分)
- 长期记忆:保留核心信息,删除过期数据(如 6 个月前的临时配置)
- 情景记忆:归档旧事件(如 1 年前的日志压缩存储)
- 语义记忆:定期重新向量化(如模型升级时)
3. 记忆检索优化
记忆的价值在于能够被检索:
# 多层检索策略
async function retrieve_memory(query) {
// 1. 先查短期记忆(Context Window)
let result = context.messages.find(m => m.content.includes(query));
if (result) return { source: 'short_term', data: result };
// 2. 再查工作记忆(Session State)
result = session.state[query];
if (result) return { source: 'working', data: result };
// 3. 再查长期记忆(数据库)
result = await db.query('SELECT * FROM memories WHERE content LIKE ?', `%${query}%`);
if (result.length > 0) return { source: 'long_term', data: result };
// 4. 最后查语义记忆(向量搜索)
const embedding = await embed(query);
result = await vector_db.search(embedding, { top_k: 5 });
if (result.length > 0) return { source: 'semantic', data: result };
return null;
}
❓ 常见问题(FAQ)
Q1: Context Window 不够用怎么办?
Context Window 溢出的解决方案:
- 压缩:使用 Context Compression 技术(如 LLMLingua)
- 摘要:把旧的对话压缩成摘要,保留在 Context 中
- 分层:把不常用的信息移到长期记忆,需要时再加载
- 扩容:使用更大的 Context Window 模型(如 Claude 3.5 的 200K)
Q2: 记忆太多会拖慢 Agent 吗?
会,但需要权衡。 记忆越多,检索越慢。优化策略:
- 使用索引(数据库索引、向量索引)
- 分层检索(先查快的,再查慢的)
- 异步加载(不阻塞主流程)
- 缓存热点记忆(如用户偏好)
Q3: 如何让 Agent "忘记"某些事情?
记忆删除策略:
# 删除用户偏好
await memory.delete_preference(user_id, 'content_style');
# 删除特定任务历史
await memory.delete_task_history(task_id);
# 清空所有记忆(慎用!)
await memory.clear_all(user_id);
# 选择性遗忘(基于时间)
await memory.forget_older_than('2026-01-01');
Q4: 记忆可以用于多 Agent 协作吗?
当然可以! 这是记忆架构的高级用法。多个 Agent 可以共享同一个长期记忆数据库,实现"集体记忆"。
# Agent A 写入记忆
await agent_a.memory.save({
type: 'discovery',
content: '发现竞品 XXX 的新功能',
timestamp: now()
});
# Agent B 读取记忆
const discoveries = await agent_b.memory.search({
type: 'discovery',
after: '2026-06-01'
});
# Agent B 现在知道了 Agent A 的发现!
🎬 总结:记忆的哲学
世界上有两种存在:一种是活在当下的瞬间,另一种是带着记忆的延续。
Agent 的记忆架构,就是让它在瞬间和延续之间找到平衡。短期记忆让它反应迅速,长期记忆让它经验丰富,情景记忆让它不再犯同样的错误。
记住:好的记忆系统不是记住所有事情,而是记住对的事情。
- 为你的 Agent 设计记忆架构(从简单开始)
- 实现用户偏好记忆(最实用的功能)
- 记录任务历史,用于后续分析和优化
- 探索向量数据库用于语义记忆