运行时机制:记忆、自动化与沙箱生命周期
运行时机制:记忆、自动化与沙箱生命周期
本文解读 Grok Bot 的「长期运行基础设施」:记忆(memory)、定时/事件驱动的自动化(Routines)、以及沙箱(box)的生命周期管理。
面向对象:想理解「它怎么记住你、怎么在你不在时自己干活、怎么自我更新恢复」的读者。文中路径均为仓库内相对路径。
1. 记忆(Memory)系统
source/host/runner/sand-memory.ts + source/host/runner/turn-memory.ts。
1.1 三级记忆
system-prompt-assembly.ts 的 getMemorySection() 拼装三类记忆:
| 级别 | 来源 | 召回限制 |
|---|---|---|
| Agent memory | memoryStore().recall(30) | profile + recent(30 条) |
| User memory | userMemory().recall({ profileLimit: 50, recentLimit: 15 }) | 用户级档案 + 近期 |
| Project memory | projectMemory().recall({...}, cap 3) | 项目级,注入上限 3 个 block |
1.2 记忆的建模
- 两种记录:
profile(「关于用户是谁」的持久事实,每 turn 都带)与log(带日期的历史事件)。 - rank 与衰减:
memoryRecallRank = log2(importance) + createdAt / (半衰期 30 天)—— 重要度(episode 1.5 / note 0.5 / 普通 1)× 时间衰减。 - 内容规范化:
normalizeMemoryContent(折叠空白、截断 500 字符)、memoryDedupeKey(去重)。 - 提取标记:
<<SAND_MEMORY_EXTRACTION>>/<<SAND_MEMORY_EPISODE>>、[episode]/[note]前缀、NONE哨兵 —— 模型输出结构化记忆提取,代码解析入库。 - episode 间隔:
DEFAULT_EPISODE_INTERVAL = 6(可SAND_MEMORY_EPISODE_INTERVAL覆盖)。
1.3 记忆 freeze 快照
isMemoryFreezeEnabled + resolveFrozenMemoryPrompt:记忆 prompt 按 compaction epoch 冻结成快照(FrozenMemorySnapshot { render, compactionEpoch }),避免每次 turn 重算记忆渲染;epoch 前进时才重渲染。
1.4 对模型的呈现
renderMemorySystemPrompt:
“Memory: durable facts you have learned about the user and their world. These persist across every conversation with this agent, even after the chat is cleared.”
并告知记忆存于 profile + log/,用 update_state (target "memory") 的 write / forget 修改。
2. 自动化(Routines)
source/host/automations/automation.ts + automation-trigger.ts + automation-store.ts。
2.1 什么是 routine
一个 routine = 保存的 prompt + 触发器(cron 定时 或 事件监听)。触发后以隐藏消息唤醒 agent(cue 为 AUTOMATION_WAKE_CUE),执行保存的 prompt,再用 SendMessage 交付结果。
2.2 触发器类型
- cron:5 段 cron,支持
@hourly/@daily/...、@every 30s|5m|2h|1d、CRON_TZ=前缀。 - 事件监听:
slack/github/microsoftTeams/linear/sentry/pagerduty/group(多监听器组合)。 - 事件走用户的 Cursor 账户连接(不贴 token)。
2.3 极其详尽的调度指引
renderAutomationsSystemPrompt 是 prompt 里最长的 section 之一,值得注意的点:
- 「主动创建 routine」:遇到「every morning / remind me / check daily / ping me when / watch this」这类重复需求,默认建 routine 而不是单次执行;
- 默认 weekday + 清醒时段:模糊的「daily」要翻译成
15 8 * * 1-5而非@daily(避免周末/凌晨打扰),只有明确说「including weekends」或确实时间敏感才放开; - 「只说几点不给分钟」:用消息时间戳的分钟数(问于 1:32 →
32 2 * * *); - 自过期:有限 watch(“keep an eye on X”)默认带 deadline 并自删;
- prompt 写意图而非固化工具配方(connector schema 会变,每次用
GetMcpTools现查); - 重复 auth 失败要 pause 而非每次触发都盲发。
2.4 存储与运行历史
- 每个 routine 一个子文件夹(
automation.json+runs历史,上限AUTOMATION_MAX_RUN_HISTORY = 20); - 上限
AUTOMATION_MAX_PER_AGENT = 50; - 用
update_state (target "routine")的create/update/pause/resume/delete管理。
3. 沙箱(box)生命周期
source/host/extensions/forever-box/ + source/host/extensions/box-lifecycle/。
3.1 ForeverBoxService
forever-box-service.ts 管理 box 的长期运行:
- Update vs Reset:
update(preserveData: true,保数据重建 pod)vsreset(preserveData: false,恢复到快照、可能丢数据)——即 prompt 里的「Update Grok Bot’s Computer」vs「Reset Grok Bot’s Computer」。 - 自动更新:
maybeAutoUpdate/watchForImageUpdate/autoUpdateNow,检测到新镜像且不忙时自动重建(保数据)。 - 镜像轮询:
startImagePolling(间隔 24h)+seedImageUpdateAvailable(启动时种一次)。 - 重建前 flush:
requestRecreate先flushPendingUploads(等 10s)。 - 迁移态:
setMigrating会隐藏 vncUrl、清空 pull 进度。
3.2 磁盘压力守卫
disk-pressure.ts + disk-pressure-guard.ts:
- 监控
/workspace、sand_data、/tmp三个卷; soft/hard两级压力;createDiskPressureReminderEpisodes:按 agent 持久化「磁盘压力提醒 episode」,每个 agent 提醒一次(claim/commit/forget),重启后仍能恢复(ledger 文件)。
3.3 参考文档
box-reference-docs.ts 在 box 启动时写入两份模型可见的参考文档:
debugging-the-box:box-doctor 自检、/.dockerenv判断 Docker-vs-anyrun、桌面日志、恢复路径;app-ui:App 真实 UI 路径(Settings 五 tab、删除 agent、Update/Reset 按钮位置)——对应 system prompt 里「引导用户前先 Read 它,别编 UI 路径」。
4. 一句话总结
- 记忆:agent/user/project 三级,profile(持久事实)+ log(历史),rank=重要度×时间衰减,按 compaction epoch 冻结快照注入 prompt。
- 自动化:routine = prompt + cron/事件触发器,默认 weekday+清醒时段,自过期,auth 失败要 pause。
- 沙箱生命周期:保数据 Update vs 丢数据 Reset,自动镜像轮询更新,磁盘压力分级提醒。
相关文档: