KAIROS 模式与 /dream:Claude Code 的仿生记忆系统

基于源码分析,揭秘 Claude Code 中 AI “做梦整理记忆”的完整机制。


目录

  1. KAIROS 是什么
  2. Feature Flag 体系
  3. 日期追加式日志:记忆的原始形态
  4. /dream 技能:蒸馏记忆的工人
  5. autoDream:自动触发引擎
  6. 四阶段蒸馏流程
  7. 触发门控:不是”夜间”而是”空闲足够久”
  8. KAIROS Agent 模式:永续运行的自主体
  9. 完整内存流转图
  10. 关键源码位置速查表

KAIROS 是什么

KAIROS(καιρός,古希腊语,意为”恰当的时机”)是 Claude Code 中一个完全自主、持续运行的 Agent 模式的代号。与普通的单次对话不同,KAIROS 模式下 Claude 是一个”一直在线”的智能体:

  • 通过 <tick> 心跳信号定期唤醒
  • 主动订阅 GitHub PR 事件
  • 在低活跃期整理记忆
  • 向用户推送通知

整个系统在 src/main.tsx 中有超过 80 处 feature('KAIROS') 门控,是 Claude Code 中规模最大的实验性特性之一。


Feature Flag 体系

KAIROS 不是一个单一开关,而是一组精细化的子标志

标志 功能
KAIROS 主标志,启用全套 KAIROS 特性
KAIROS_DREAM 仅启用 /dream 记忆蒸馏技能
KAIROS_BRIEF 仅启用 BriefTool(主动状态更新)
KAIROS_GITHUB_WEBHOOKS 启用 SubscribePRTool(GitHub PR 订阅)
KAIROS_CHANNELS 频道通知
KAIROS_PUSH_NOTIFICATION 设备推送通知

Dream 技能注册(src/skills/bundled/index.ts 第 35 行):

1
2
3
4
// dream 技能只要 KAIROS 或 KAIROS_DREAM 任一为真就注册
feature('KAIROS') || feature('KAIROS_DREAM')
? [require('./dream.js')]
: []

KAIROS 模式激活状态通过全局 state 追踪(src/bootstrap/state.ts 第 1085–1090 行):

1
2
export function getKairosActive(): boolean { ... }
export function setKairosActive(value: boolean): void { ... }

并在遥测元数据中标记(src/services/analytics/metadata.ts 第 493 行):

1
kairosActive?: true

日期追加式日志:记忆的原始形态

这是整个系统最具设计感的部分。在 KAIROS 模式下,Claude 不再维护结构化的 MEMORY.md,而是向按日期命名的日志文件追加原始条目。

路径构造src/memdir/paths.ts 第 246–251 行):

1
2
3
4
5
6
export function getAutoMemDailyLogPath(date: Date = new Date()): string {
const yyyy = date.getFullYear().toString()
const mm = (date.getMonth() + 1).toString().padStart(2, '0')
const dd = date.getDate().toString().padStart(2, '0')
return join(getAutoMemPath(), 'logs', yyyy, mm, `${yyyy}-${mm}-${dd}.md`)
}

实际路径

1
2
3
4
5
6
7
~/.claude/projects/<项目路径哈希>/memory/
└── logs/
└── 2026/
└── 03/
├── 2026-03-28.md ← 周五的原始日志
├── 2026-03-29.md ← 周六的原始日志
└── 2026-03-30.md ← 今天的追加条目(持续写入)

src/memdir/memdir.ts 第 323 行的注释解释了设计意图:

“Used by assistant mode (feature(‘KAIROS’)): rather than maintaining MEMORY.md as a live index, the agent appends to a date-named log file as it works. A separate nightly /dream skill distills these logs into topic files + MEMORY.md.”

为什么用追加式日志而不是直接更新结构化文件?

在高频交互的自主 Agent 场景下,频繁更新结构化文件会引发:

  1. 并发写入冲突(多个子 Agent 同时修改同一文件)
  2. 中途崩溃导致文件损坏
  3. 每次写入都要读-改-写整个文件,代价高

追加式日志是数据库领域成熟的 WAL(Write-Ahead Log)模式,Claude 借用了同样的思路。


/dream 技能:蒸馏记忆的工人

/dream 是一个注册在 src/skills/bundled/index.ts 的内置技能,底层实现在编译后的 dream.js(Anthropic 内部代码,源码中以编译产物形式存在)。

它的本质是:启动一个完全独立的 fork 子 Agent,专门执行记忆整理工作。

触发方式有两种:

  1. 用户手动:在 KAIROS 模式下输入 /dream
  2. 自动触发:由 autoDream.ts 后台引擎监控并自动调用

autoDream:自动触发引擎

核心文件:src/services/autoDream/autoDream.ts

这个模块负责在后台监控条件,并在合适时机自动触发 /dream。相关子模块:

文件 职责
autoDream.ts 主调度引擎
consolidationPrompt.ts 发送给蒸馏子 Agent 的完整提示词
consolidationLock.ts 防止多进程同时运行的锁文件管理
config.ts 启用/禁用开关,key: autoDreamEnabled

任务类型注册src/Task.ts 第 13 行):

1
2
// 'dream' 是合法的 TaskType
type TaskType = 'bash' | 'edit' | 'read' | 'write' | 'dream' | ...

UI 状态展示src/tasks/DreamTask/DreamTask.ts 第 63 行):

1
2
createTaskStateBase(id, 'dream', 'dreaming')
// 任务的 display label 直接就是 "dreaming"

文件变更追踪autoDream.ts 第 281–313 行):

1
2
3
// makeDreamProgressWatcher 监听子 Agent 的工具调用
// 凡是 FileEditTool 或 FileWriteTool 的调用,路径都被记录到 filesTouched[]
// DreamTaskState.filesTouched 记录本次 dream 运行写过哪些文件

四阶段蒸馏流程

consolidationPrompt.ts 定义了发送给 dream 子 Agent 的完整任务提示,标题明确写着:

1
2
# Dream: Memory Consolidation
You are performing a dream — a reflective pass over your memory files.

整个蒸馏过程分为四个阶段:

Phase 1:定向(Orient)

1
2
3
4
1. ls memory 目录
2. 读取 MEMORY.md(快速了解已知主题)
3. 浏览现有 topic 文件(skim,不深读)
4. 列举 logs/ 和 sessions/ 子目录

目标:建立全局视图,了解”已经知道什么”和”原始信号在哪”。

Phase 2:收集近期信号(Gather Recent Signal)

按优先级:

  1. 日期日志logs/YYYY/MM/YYYY-MM-DD.md)— 最优先,追加式原始记录
  2. 漂移的记忆(drifted memories)— 上次蒸馏后可能已过期的条目
  3. 对话 JSONLsessions/ 目录中的转录文件)— 通过 grep 窄范围提取,而非全读

Phase 3:整合(Consolidate)

1
2
3
4
- 写入或更新 topic 文件(如 user_preferences.md, project_context.md)
- 融合新信号进入已有结构
- 相对日期转为绝对日期("上周四" → "2026-03-26")
- 删除被新信息推翻的旧事实

这是真正的”蒸馏”:原始的流式日志变成结构化的主题文档。文件名由模型自己决定,系统不预设。

Phase 4:精简与索引(Prune and Index)

1
2
3
- 更新 MEMORY.md 作为稀疏索引
- 保持在 MAX_ENTRYPOINT_LINES 行以内 + ~25KB 以内
- 格式:- [Title](file.md) — one-line hook

最终 MEMORY.md 是整个记忆系统的”目录”,每行一个主题文件的指针。

整合前后对比:

1
2
3
4
5
6
7
8
9
10
整合前(原始日志 logs/2026/03/2026-03-30.md):
[14:23] 用户说不喜欢在回复末尾加总结
[15:07] 修改了 src/model/transformer.py 的 attention 机制
[16:44] 用户提到明天要赶 ICLR deadline
[17:02] 用户更喜欢 rebase 而不是 merge

整合后:
memory/user_preferences.md ← "不加总结、用 rebase"
memory/project_context.md ← "transformer.py attention 修改、ICLR deadline"
MEMORY.md ← 两行指针

触发门控:不是”夜间”而是”空闲足够久”

重要澄清:源码中没有“检测到夜间”或”检测到低活跃时段”的逻辑。memdir.ts 注释里的”nightly”只是非正式文档用语,实际触发条件是:

条件 1:时间间隔autoDream.ts 第 6–8 行)

1
hoursSince >= minHours  // 默认:距上次蒸馏超过 24 小时

条件 2:会话数量

1
transcriptCount >= minSessions  // 默认:上次蒸馏后新增 ≥ 5 个会话

条件 3:锁文件(防并发)consolidationLock.ts

1
2
// 检查 .consolidate-lock 文件
// 验证 PID + 文件修改时间,确保没有其他进程正在运行蒸馏

条件 4:用户近期无交互backgroundHousekeeping.ts 第 44–75 行)

1
2
3
4
5
6
// 如果用户在过去 60 秒内有交互,推迟执行
if (getLastInteractionTime() > Date.now() - 1000 * 60) {
// 重新调度,等待用户闲下来
setTimeout(tryAgain, RETRY_INTERVAL)
return
}

扫描节流:即使时间条件满足,会话列表重扫限制每 10 分钟最多一次:

1
const SESSION_SCAN_INTERVAL_MS = 10 * 60 * 1000

阈值来源minHoursminSessions 由 GrowthBook 动态标志 tengu_onyx_plover 控制,可以远程调整而无需发版。


KAIROS Agent 模式:永续运行的自主体

理解 dream 系统需要先理解 KAIROS 的整体模式。

KAIROS 不是用户发起的对话,而是一个持续运行的后台 Agent,靠 <tick> 心跳维持活跃:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
用户不在线

KAIROS Agent 等待 tick(通过 SleepTool 休眠)

tick 到达(定期心跳)

Agent 被唤醒:检查是否有 PR 事件、日历提醒、待处理任务

[若有工作] 执行工作
[若无工作] 继续 SleepTool 休眠

同时:
autoDream 监控器在后台运行

条件满足(24h + 5 sessions + 用户空闲)

fork 出 dream 子 Agent

dream 子 Agent 执行四阶段蒸馏

写入 topic 文件,更新 MEMORY.md

DreamTask 状态更新为 "completed",UI 显示 "last ran X ago"

KAIROS Agent 相关工具(src/tools.ts 第 26–50 行):

1
2
3
4
5
6
7
8
// 全部在 KAIROS 模式下可用
SleepTool // 让 Agent 休眠到下一个 tick
SendUserFileTool // 主动向用户发送文件
PushNotificationTool // 向设备推送通知
SubscribePRTool // 订阅 GitHub PR 事件(KAIROS_GITHUB_WEBHOOKS)
BriefTool // 主动发出状态摘要(KAIROS_BRIEF)
SuggestBackgroundPRTool // 后台 PR 建议
ScheduleCronTool // 会话内 cron 调度

SleepTool 的引导语(src/tools/SleepTool/prompt.ts 第 11 行):

1
2
You may receive <tick> prompts — these are periodic check-ins.
Look for useful work to do before sleeping.

完整内存流转图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
KAIROS Agent 工作中

▼ 每次有值得记录的信息
追加写入 logs/YYYY/MM/YYYY-MM-DD.md
(append-only,永不修改旧条目)

│ 累积多个会话 + 24小时过去
│ 用户当前空闲 + 无锁冲突

autoDream.ts 触发条件满足


fork dream 子 Agent 启动
DreamTask 状态: "dreaming"


▼ Phase 1: Orient
读取现有 memory/ 目录结构
读 MEMORY.md 稀疏索引
浏览现有 topic 文件


▼ Phase 2: Gather
读取近期 logs/YYYY/MM/*.md ← 主要信号源
检查漂移的记忆条目
grep sessions/*.jsonl ← 补充信号


▼ Phase 3: Consolidate
┌─────────────────────────────────┐
│ memory/ 目录 │
│ │
logs/2026/03/ │ user_preferences.md (更新) │
2026-03-28.md ────▶│ project_context.md (更新) │
2026-03-29.md ────▶│ coding_patterns.md (新建) │
2026-03-30.md ────▶│ ... │
│ │
│ 相对日期 → 绝对日期 │
│ 矛盾事实 → 删除旧的 │
└─────────────────────────────────┘


▼ Phase 4: Prune & Index
更新 MEMORY.md(稀疏索引,< MAX_ENTRYPOINT_LINES 行)
格式:- [Title](file.md) — one-line hook



DreamTask 状态: "completed"
filesTouched[] 记录本次修改的文件列表
UI: "last ran X ago"


▼ 下次 KAIROS Agent 工作时
读取 MEMORY.md 获取全局上下文
(不再需要读完整的 logs/,已被蒸馏)

关键源码位置速查表

功能 文件 行号
KAIROS 主标志门控(命令注册) src/commands.ts 63, 67, 70, 101
KAIROS 工具注册 src/tools.ts 26, 42, 46, 50
dream 技能注册(KAIROS|KAIROS_DREAM src/skills/bundled/index.ts 35–39
getKairosActive / setKairosActive src/bootstrap/state.ts 1085–1090
遥测元数据 kairosActive src/services/analytics/metadata.ts 493
日期日志路径构造 src/memdir/paths.ts 246–251
设计意图注释 src/memdir/memdir.ts 323, 335–348
autoDream 主调度引擎 src/services/autoDream/autoDream.ts 全文
四阶段蒸馏提示词 src/services/autoDream/consolidationPrompt.ts 全文
并发锁管理 src/services/autoDream/consolidationLock.ts 全文
启用/禁用开关 src/services/autoDream/config.ts 9
DreamTask 注册 src/tasks/DreamTask/DreamTask.ts 全文
'dream' 作为 TaskType src/Task.ts 13
“dreaming” display label src/tasks/DreamTask/DreamTask.ts 63
文件变更追踪(makeDreamProgressWatcher) src/services/autoDream/autoDream.ts 281–313
用户交互检查(推迟执行) src/backgroundHousekeeping.ts 44–75
会话扫描节流(10分钟) src/services/autoDream/autoDream.ts SESSION_SCAN_INTERVAL_MS
SleepTool 引导语(tick 机制) src/tools/SleepTool/prompt.ts 11
MemoryFileSelector UI(”last ran X ago”) src/components/MemoryFileSelector.tsx 192

总结

KAIROS 与 /dream 构成了一套完整的仿生记忆系统

  1. 记录(海马体):工作时实时向日期日志追加原始条目,保持低开销
  2. 蒸馏(慢波睡眠):空闲足够久后,fork 独立子 Agent 执行四阶段整理
  3. 索引(记忆巩固):原始流式日志压缩为结构化主题文件 + 稀疏索引

“nightly /dream”的命名并非字面意义上的定时任务,而是一个精准的仿生隐喻:当系统”足够空闲”时,自动发生的记忆巩固过程。 人类睡眠中海马体向新皮层传输记忆的机制,在这里被实现为:日期追加日志 → fork 子 Agent → 结构化 topic 文件。

这是工程设计向认知科学借鉴的一次有趣实践。