运行时机制:记忆、自动化与沙箱生命周期

运行时机制:记忆、自动化与沙箱生命周期

本文解读 Grok Bot 的「长期运行基础设施」:记忆(memory)、定时/事件驱动的自动化(Routines)、以及沙箱(box)的生命周期管理。

面向对象:想理解「它怎么记住你、怎么在你不在时自己干活、怎么自我更新恢复」的读者。文中路径均为仓库内相对路径。

1. 记忆(Memory)系统

source/host/runner/sand-memory.ts + source/host/runner/turn-memory.ts

1.1 三级记忆

system-prompt-assembly.tsgetMemorySection() 拼装三类记忆:

级别来源召回限制
Agent memorymemoryStore().recall(30)profile + recent(30 条)
User memoryuserMemory().recall({ profileLimit: 50, recentLimit: 15 })用户级档案 + 近期
Project memoryprojectMemory().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|1dCRON_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 ResetupdatepreserveData: true,保数据重建 pod)vs resetpreserveData: false,恢复到快照、可能丢数据)——即 prompt 里的「Update Grok Bot’s Computer」vs「Reset Grok Bot’s Computer」。
  • 自动更新maybeAutoUpdate / watchForImageUpdate / autoUpdateNow,检测到新镜像且不忙时自动重建(保数据)。
  • 镜像轮询startImagePolling(间隔 24h)+ seedImageUpdateAvailable(启动时种一次)。
  • 重建前 flushrequestRecreateflushPendingUploads(等 10s)。
  • 迁移态setMigrating 会隐藏 vncUrl、清空 pull 进度。

3.2 磁盘压力守卫

disk-pressure.ts + disk-pressure-guard.ts

  • 监控 /workspacesand_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,自动镜像轮询更新,磁盘压力分级提醒。

相关文档: