让AI代理告别金鱼记忆:三档文件系统实现低成本、高可用的长期记忆
你有没有试过养一群“金鱼型”AI代理?
它们每天准时上线,干活利索,报告漂亮——但一到第二天,就彻底失忆:
– 昨天被坑过的 bounty 平台,今天又踩一遍;
– 上周注册过的空投钱包,这周还要你手输地址;
– 写了 20 篇技术文章,却从不记得哪类标题点击率翻倍……
这不是 AI 不行,而是它默认「没脑子」——没有持久记忆,每次启动都是全新出厂。
别急着上向量数据库、RAG 或语义搜索。
这篇讲的,是一个用纯文本文件 + 3 个文件夹 + 3 条铁律就能落地的实战方案,
连刚学完 fs.appendFile 的前端同学,1 小时就能搭起来。
🧠 人类怎么记事儿?AI 就怎么记
我们没用复杂模型,只照搬人脑记忆分层逻辑:
- 短时记忆(HEARTBEAT.md):像贴在显示器上的便利贴,只记「此刻正在干啥」,上限 50 行,任务结束自动清空;
- 中期记忆(memory/2026-04-08.md):像每日手账,每个代理当天干了啥、踩了啥坑、赚了多少钱,全按日期存成独立
.md文件; - 长期记忆(MEMORY.md):像老师傅的笔记本,只收真正有用的「经验」——比如「Galxe 项目要抢在截止前 2 小时提交」「Zora 空投必须用主网交易」,每周人工整理一次,严格控在 500 行内。
✅ 关键不是“存得多”,而是“挑得准”。
❌ 别让 AI 自己总结“教训”——它真会写出:“完成任务很重要”这种废话。
📁 文件结构:简单到不像话
/workspace/
├── MEMORY.md # 长期记忆(人工维护,≤500行)
├── HEARTBEAT.md # 短时状态(自动清理,≤50行)
├── memory/ # 中期日志(每天一个文件,30天后自动删)
│ ├── 2026-04-01.md
│ ├── 2026-04-02.md
│ └── ...
├── reports/ # 各代理输出报告(不参与记忆)
└── articles/ # 内容产出(不参与记忆)
💡 为什么不用一个大文件?四个理由够硬核:
- 你说“查查上周二 bounty-hunter 干了啥”,
grep -r "bounty-hunter.*2026-04-02" memory/一秒出结果; - 想删旧数据?
find memory/ -mtime +30 -delete一行命令搞定; - 六个代理同时写日志?各自
append同一天的文件,零锁冲突; - 新人接手项目?打开
MEMORY.md,5 分钟看懂团队核心规则和雷区。
🛠️ 代码怎么写?三段真·能跑的 Node.js 示例(带中文注释)
① 代理写今日日志(追加模式,安全不覆盖)
// 代理运行结束后,自动记一笔到当天日志
async function writeDailyLog(agentName, content) {
const today = new Date().toISOString().split('T')[0]; // 格式:2026-04-08
const logPath = `/workspace/memory/${today}.md`;
const timeCN = new Date().toLocaleTimeString('zh-CN', {
timeZone: 'Asia/Shanghai',
hour: '2-digit',
minute: '2-digit'
});
// 拼接成标准格式:### bounty-hunter (10:23)\n- 提交了3个任务...\n\n
const entry = `### ${agentName} (${timeCN})\n${content}\n\n`;
await fs.appendFile(logPath, entry, 'utf-8');
}
② 启动时读取记忆(优先级:长期 > 近3天日志 > 当前心跳)
// 每个代理启动第一件事:加载上下文
async function initializeAgent() {
// 1. 长期记忆(必读,500行以内,稳定可靠)
const longTerm = await fs.readFile('MEMORY.md', 'utf-8');
// 2. 近3天日志(最多读3个文件,避免爆内存)
const recentLogs = [];
for (let i = 0; i < 3; i++) {
const date = new Date(Date.now() - i * 24 * 60 * 60 * 1000);
const dateStr = date.toISOString().split('T')[0];
try {
const log = await fs.readFile(`memory/${dateStr}.md`, 'utf-8');
recentLogs.push(log);
} catch (e) {
// 文件不存在?跳过,不报错
}
}
// 3. 当前心跳(如果存在,否则留空)
let heartbeat = '';
try {
heartbeat = await fs.readFile('HEARTBEAT.md', 'utf-8');
} catch (e) {}
return {
longTermMemory: longTerm,
recentLogs: recentLogs.join('\n'), // 合并成一段供 LLM 读取
heartbeatState: heartbeat,
};
}
③ 周五下午手动更新长期记忆(这才是灵魂!)
// 每周日花 15 分钟,把本周日志里的干货抄进 MEMORY.md
async function updateLongTermMemory(lesson, category) {
const memoryPath = '/workspace/MEMORY.md';
const content = await fs.readFile(memoryPath, 'utf-8');
// 如果分类不存在,先加个标题
const header = `## ${category}`;
if (!content.includes(header)) {
await fs.appendFile(memoryPath, `\n${header}\n\n`);
}
// 追加具体经验(带短横线,保持格式统一)
await fs.appendFile(memoryPath, `- ${lesson}\n`);
}
📈 效果立竿见影:从“人工客服”变“老员工”
| 场景 | 加入记忆前 | 加入记忆后 |
|---|---|---|
| bounty-hunter | 每天重试已失败的 scam 项目 | 自动跳过黑名单平台(BounceBit) |
| airdrop-hunter | 反复问“我上次用的哪个钱包?” | 查 MEMORY.md → 直接填 Zora 主网地址 |
| hunter-content | 文章标题全靠猜 | 读到“Lessons from X Trades 标题点击率+100%”,立刻复刻 |
更实在的是——
以前每天花 30 分钟给代理“讲背景”,现在省下时间喝咖啡;
每月 Token 成本约 ¥9,换来的是 人力成本直降 ¥450+。
⚠️ 什么情况别硬套这套?(避坑指南)
- 你的代理只做一件事(比如每天备份服务器),那真不需要记忆;
- 你设计的就是“每次重启都清零”,比如风控扫描器,那就别加;
- 你没法坚持每周花 15 分钟整理
MEMORY.md——那日志只会变成垃圾山; - 你要存 API Key、私钥、身份证号?千万别放这里! 用专门的 secrets manager。
✅ 最后说一句大实话
这套系统的技术含量,可能还没你写的第一个 fetch 请求高。
真正的门槛是:
– 愿意每周亲手整理一次 MEMORY.md;
– 敢删掉 30 天前的日志(哪怕“总觉得以后有用”);
– 强制自己和代理都守规矩:HEARTBEAT.md 超 50 行?先删旧的,再写新的。
当你的 AI 开始说:“哦,这个我们上周试过,失败因为……”,
你就知道——它终于不是工具,而是队友了。
直达网址:https://github.com/openclaw/workspace
