Claude Code 源码分析第 46 课 · 第 07
第 46 课

KAIROS 常驻模式

Claude Code 如何从请求-响应 CLI 转变为在会话之间活动、安排自己的工作并主动与您联系的自治代理。

01 什么是 KAIROS?

到目前为止,您在本课程中学习的每个功能(启动顺序、工具调用、内存、压缩)都以基本的方式运行 reactive 模型:您输入,克劳德响应,会话结束。 KAIROS 是 Anthropic 违反该合同的系统的内部代号。

在 KAIROS 下,Claude Code 成为永远在线的守护进程。 它启动一次,在重新启动时保持持久会话,安排自己的签入,在您不看时向您发送消息,并在您睡觉时巩固自己的内存。 它与其说是一个 CLI 工具,不如说是一个后台员工。

Source
名称 KAIROS 在整个代码库中显示为 Bun 构建时功能标志: feature('KAIROS')。 它是一个 Anthropic 内部标志 - 完全通过死代码消除从外部构建中门控出来。 所有 KAIROS 代码路径都由正三元组保护,因此捆绑器可以将它们不断折叠为 false 并对模块进行tree-shake。

特征标志系统

KAIROS 不是一个单一的开关。 代码库揭示了 family 相关标志,每个标志独立传送始终在线体验的特定部分:

Flag它解锁什么Scope
KAIROS 全辅助模式:辅助指挥,会话连续性(--session-id, --continue), SendUserFileTool, PushNotificationTool, assistant 设置键、每日日志内存模型、 workerType: 'claude_code_assistant' 在桥上 ant-only
KAIROS_BRIEF Ships BriefTool (SendUserMessage) 独立于完整的 KAIROS。 让聊天视图 / --brief 体验到达外部用户。 external
KAIROS_PUSH_NOTIFICATION Ships PushNotificationTool 独立于完整的 KAIROS。 external
KAIROS_GITHUB_WEBHOOKS Ships SubscribePRTool — GitPR 事件的 Hub Webhook 订阅。 ant-only
KAIROS_CHANNELS MCP 通道通知 — 让 MCP 服务器将入站消息推送到对话中。 这 channelsEnabled 设置键和 allowedChannelPlugins policy. external
PROACTIVE 更早、更轻的主动模式。 许多 KAIROS 路径都有人把守 feature('PROACTIVE') || feature('KAIROS') — KAIROS 是一个严格的超集。 包括 SleepTool 以及系统提示的主动部分。 ant-only
AGENT_TRIGGERS Cron调度系统(CronCreate, CronDelete, CronList, .claude/scheduled_tasks.json)。 可独立运输——零进口 src/assistant/. gb-gated
架构笔记
这些标志的设计使得每种功能都可以独立地传送和终止切换。 评论中 ScheduleCronTool/prompt.ts 说明了这一点: “AGENT_TRIGGERS 可以从 KAIROS 独立发布 - cron 模块图对 src/assistant/ 的导入为零,并且没有功能('KAIROS')调用。”
02 状态枢轴: kairosActive

KAIROS 模式中的所有内容都以全局状态存储中的单个布尔值为中心。 在 bootstrap/state.ts:

// bootstrap/state.ts (line 1085)
export function getKairosActive(): boolean {
  return STATE.kairosActive  // default: false
}

export function setKairosActive(value: boolean): void {
  STATE.kairosActive = value
}

这个布尔值是运行时“我们现在处于助理模式吗?” 旗帜。 它是从 main.tsx 在启动期间,在运行任何工具可用性检查之前。 它的影响无处不在:

Memory

每日日志模式

When kairosActive, loadMemoryPrompt() 从标准 MEMORY.md 阅读器切换到 buildAssistantDailyLogPrompt() — 仅附加每日日志而不是共享索引文件。

BriefTool

选择绕过

isBriefEnabled() 返回 true 为 kairosActive 会话无需明确的用户选择加入。 系统提示硬编码“you MUST use SendUserMessage”。

快速模式

SDK 限制解除

快速模式 (Opus 4.6) 在非交互式 SDK 会话中被阻止,除非 getKairosActive() 是真的。 助理守护进程模式不受第三方偏好检查。

AutoDream

梦想被关闭

后台内存整合代理(isGateOpen()) 显式返回 false when kairosActive — 助手模式使用自己的磁盘技能梦想管道。

Bridge

工人类型变化

When isAssistantMode() (读作 kairosActive),桥将会话注册为 workerType: 'claude_code_assistant' — 在 Web UI 会话选择器中作为不同类型可见。

Scheduler

Auto-Enable

cron 调度程序 assistantMode 标志绕过正常 isLoading 门和 setScheduledTasksEnabled() 握手 — 任务 scheduled_tasks.json 启动时立即开始射击。

03 Tick Loop:代理如何保持活力

主动/KAIROS模式的核心是一种心跳机制,称为 tick。 当自主运行时,模型会定期接收 <tengu_tick> XML 消息。 将其视为轻轻的轻推:“你醒了,现在怎么办?”

从系统提示中 constants/prompts.ts (getProactiveSection()):

// The exact text the model receives in its system prompt when proactive is active:

"You are running autonomously. You will receive <tengu_tick> prompts that keep you
alive between turns — just treat them as 'you're awake, what now?' The time in each
<tengu_tick> is the user's current local time."

"Multiple ticks may be batched into a single message. This is normal — just process
the latest one. Never echo or repeat tick content in your response."

"**If you have nothing useful to do on a tick, you MUST call Sleep.** Never respond
with only a status message like 'still waiting' — that wastes a turn and burns tokens."

SleepTool:具有成本意识的空闲

仅当以下情况时才会加载睡眠工具: feature('PROACTIVE') || feature('KAIROS')。 它的全部工作是让模型让出 CPU,而不会在每空闲秒消耗一次 API 调用:

// tools/SleepTool/prompt.ts
export const SLEEP_TOOL_PROMPT = `Wait for a specified duration.
The user can interrupt the sleep at any time.

Use this when you have nothing to do, or when you're waiting for something.

You may receive <tengu_tick> prompts — look for useful work before sleeping.

Each wake-up costs an API call, but the prompt cache expires after 5 minutes
of inactivity — balance accordingly.`

提示中包含三个关键设计点:

  • 型号 chooses 它的睡眠持续时间——等待慢速进程时更长,迭代时更短
  • 睡觉显然比打电话便宜 Bash(sleep ...) — 没有举行 shell 进程
  • 5 分钟提示缓存过期是一个硬成本底线 - 唤醒频率超过此值会浪费缓存创建令牌

睡眠中断:优先级队列

当用户在睡眠中发送消息时, QueuePriority 系统中 types/textInputTypes.ts 处理唤醒:

// types/textInputTypes.ts
type QueuePriority = 'now' | 'next' | 'later'

// 'now'  — interrupt current tool call immediately (Esc + send)
// 'next' — wait for current tool to finish, then inject between tool result and next API call
//          Wakes an in-progress SleepTool call.
// 'later'— end-of-turn drain. Also wakes SleepTool.
关键见解
睡眠进度(sleep_progress) 列于 EPHEMERAL_PROGRESS_TYPES 与 bash/powershell/MCP 进度一起 — 它从存储的记录中删除,就像 shell spinner 输出一样。 滴答循环会产生大量噪音,如果保留的话会污染上下文。

终端聚焦意识

主动的系统提示为模型提供了用户终端是否聚焦的明确指导。 这改变了它应该的自主程度:

"**Unfocused**: The user is away. Lean heavily into autonomous action —
make decisions, explore, commit, push. Only pause for genuinely
irreversible or high-risk actions.

**Focused**: The user is watching. Be more collaborative — surface choices,
ask before committing to large changes."
04 KAIROS 工具套件

KAIROS 引入了标准 Claude Code 中不存在的一组专用工具。 每个都有条件加载 tools.ts 基于其功能标志:

// tools.ts — conditional loading (simplified)
const SleepTool           = feature('PROACTIVE') || feature('KAIROS')
                             ? require('./tools/SleepTool/SleepTool.js').SleepTool : null

const SendUserFileTool    = feature('KAIROS')
                             ? require('./tools/SendUserFileTool/SendUserFileTool.js').SendUserFileTool : null

const PushNotificationTool = feature('KAIROS') || feature('KAIROS_PUSH_NOTIFICATION')
                             ? require('./tools/PushNotificationTool/PushNotificationTool.js').PushNotificationTool : null

const SubscribePRTool     = feature('KAIROS_GITHUB_WEBHOOKS')
                             ? require('./tools/SubscribePRTool/SubscribePRTool.js').SubscribePRTool : null

// Cron tools (AGENT_TRIGGERS — independently shippable):
const cronTools = feature('AGENT_TRIGGERS')
  ? [ CronCreateTool, CronDeleteTool, CronListTool ] : []
Sleep
积极主动 || 凯罗斯

在一段时间内让出执行而不保留 shell 进程。 该模型的主要怠速机制。 尊重 minSleepDurationMs and maxSleepDurationMs 节流设置。 可以与其他工具同时调用。

发送用户消息(简短)
凯罗斯 || KAIROS_BRIEF

辅助模式下模型的主输出通道。 支持 status: 'proactive' (未经请求的更新)与 status: 'normal' (回复)。 接受文件附件。 由权利+选择加入逻辑控制 isBriefEnabled().

SendUserFile
仅限凯罗斯

将文件作为附件发送给用户。 区别于 SendUserMessage的附件参数 — 用于文件传输的独立工具。 与 BriefTool 附件逻辑一起存在 tools/SendUserFileTool/.

PushNotification
凯罗斯 || KAIROS_PUSH_NOTIFICATION

向用户的设备发送系统级推送通知。 当 Claude 完成长时间运行的任务并且用户离开时使用。 这 ConfigTool 暴露了一个 pushNotificationsEnabled 在该标志后面设置门控。

SubscribePR
KAIROS_GITHUB_WEBHOOKS

订阅 GitHub PR webhook 事件。 让助手在 PR 审核完成或 CI 完成时自动唤醒,无需轮询。 同时显示为工具和斜杠命令(/subscribe-pr).

CronCreate / CronDelete / CronList
AGENT_TRIGGERS

在 cron 表达式上安排提示。 一次性(“下午 2 点提醒我”)或重复(“每个工作日上午 9 点”)。 持久任务坚持下去 .claude/scheduled_tasks.json 并生存重启。 在可配置的最长期限(默认值:天)后自动过期。

BriefTool 深入探讨:权利与激活

BriefTool 具有代码库中最复杂的启用逻辑。 它故意区分了两个问题:

isBriefEntitled()

  • 是用户 allowed 使用简报?
  • 检查:KAIROS 活动或环境变量 CLAUDE_CODE_BRIEF 或 GrowthBook 标志 tengu_kairos_brief
  • GrowthBook 每 5 分钟刷新一次
  • Governs: --brief 旗帜, defaultView: 'chat', --tools listing

isBriefEnabled()

  • 很简短 active 在本次会议上?
  • Requires: kairosActive OR userMsgOptIn 和权利
  • 致电自 Tool.isEnabled() — 懒惰,初始化后
  • 控制:模型是否看到工具、系统提示部分、todo-nag 抑制

拆分原因:没有它,将用户注册 tengu_kairos_brief 会默默地激活所有会话的 Brief。 选择加入 (userMsgOptIn) 必须由用户操作显式设置: --brief, defaultView: 'chat', /brief 斜杠命令,或 CLAUDE_CODE_BRIEF 环境是。

// tools/BriefTool/BriefTool.ts (simplified)
export function isBriefEnabled(): boolean {
  // Top-level feature() guard is load-bearing for dead-code elimination.
  // Bun constant-folds to `false` in external builds.
  return feature('KAIROS') || feature('KAIROS_BRIEF')
    ? (getKairosActive() || getUserMsgOptIn()) && isBriefEntitled()
    : false
}
大连商品交易所 (DCE) 陷阱
BriefTool 中的评论明确警告:“撰写 isBriefEntitled() alone(有自己的守卫)在语义上是等价的,但无法跨越边界进行常量折叠。” feature() 每个调用站点的守卫让 Bun 从外部构建中摇动整个 BriefTool 对象。
05 计划任务: scheduled_tasks.json

cron系统是Claude安排自己未来工作的机制。 它完全生活在 utils/cronTasks.ts, utils/cronScheduler.ts,以及三个 Cron 工具。

CronTask 形状

// utils/cronTasks.ts
type CronTask = {
  id:          string
  cron:        string       // 5-field cron in local timezone
  prompt:      string       // prompt to enqueue when task fires
  createdAt:   number       // epoch ms — anchor for missed-task detection
  lastFiredAt?: number      // set after each recurring fire
  recurring?:  boolean      // true = reschedule after firing
  permanent?:  boolean      // exempt from recurringMaxAgeMs expiry
  durable?:    boolean      // runtime-only: false = session-only, undefined = disk-backed
  agentId?:    string       // routes fire to a teammate's queue instead of main REPL
}

两个耐用等级

仅会话(持久: false)

  • 从未写入磁盘
  • 克劳德退出后消失
  • 对于:“5 分钟后提醒我”、“一小时后回来查看”
  • 大多数用户请求的默认值

耐用(耐用:真实)

  • 坚持 .claude/scheduled_tasks.json
  • 重新启动后仍然存在 - 调度程序在下次启动时启动
  • 错过的一次性任务浮出水面以供追赶
  • 重复任务在以下时间后自动过期 recurringMaxAgeMs

抖动系统

CronCreate 提示包含有关车队规模负载分配的工程智慧:

// From CronCreateTool prompt (ScheduleCronTool/prompt.ts)
"Every user who asks for '9am' gets `0 9`, and every user who asks for 'hourly' gets
`0 *` — which means requests from across the planet land on the API at the same instant.

When the user's request is approximate, pick a minute that is NOT 0 or 30:
  'every morning around 9' → '57 8 * * *' or '3 9 * * *' (not '0 9 * * *')
  'hourly' → '7 * * * *' (not '0 * * * *')"

除了模型的偏移选择之外,调度程序本身还添加了确定性抖动:重复任务最多延迟其周期的 10%(最多 15 分钟),而一次性任务在 :00 或 :30 提前最多 90 秒触发。

永久任务:助手模式内置

The permanent: true 该字段专门用于助理模式的内置任务——每日追赶、早上登记、梦想巩固。 这些是写给 scheduled_tasks.json 在安装时 src/assistant/install.ts 并不受年龄限制。 这 writeIfMissing() 模式意味着重新安装永远不会覆盖用户自定义设置。

06 AutoDream:后台内存整合

AutoDream是KAIROS的后台维护人员。 当积累了足够的时间和会话时,它会自动触发,产生一个分叉的子代理来巩固内存,而不会中断主会话。

门链(最便宜的优先)

flowchart TD A[Post-sampling hook fires] --> B{isGateOpen?} B -->|kairosActive| X[Skip — KAIROS uses disk-skill dream] B -->|isRemoteMode| Y[Skip] B -->|!autoMemEnabled| Z[Skip] B -->|!autoDreamEnabled| AA[Skip] B -->|pass| C{Time gate\nhoursSince >= minHours?} C -->|no| Skip1[Return] C -->|yes| D{Scan throttle\nlastScanMs >= 10min?} D -->|no| Skip2[Return] D -->|yes| E[Scan sessions since lastConsolidatedAt] E --> F{Session count >= minSessions?} F -->|no| Skip3[Return] F -->|yes| G[tryAcquireConsolidationLock] G -->|null — locked| Skip4[Return] G -->|priorMtime| H[registerDreamTask UI] H --> I[runForkedAgent — dream prompt] I --> J[completeDreamTask\nappendSystemMessage]

GrowthBook 标志的默认阈值 tengu_onyx_plover: 24小时 自上次合并以来, 5 节课 最低限度。 两者都可以在不部署的情况下进行实时调整。

整合提示:4 个阶段

梦想代理人收到来自的结构化提示 services/autoDream/consolidationPrompt.ts:

第一阶段

Orient

ls 内存目录,读取 MEMORY.md 索引,浏览现有主题文件以避免重复。 如果 logs/ or sessions/ 子目录存在(助手模式布局),查看最近的条目。

第二阶段

Gather

首先是每日日志,然后是漂移的记忆,然后是狭窄的记录 grep。 Never 详尽地阅读文字记录——只搜索那些已经被怀疑重要的事情。

第三阶段

Consolidate

将新信号合并到现有主题文件中,将相对日期转换为绝对日期,从源头删除矛盾的事实。

第四阶段

修剪和索引

更新MEMORY.md:保留在 MAX_ENTRYPOINT_LINES 行和~25KB。 每项:一行,一行钩。 切勿将内存内容直接写入索引。

梦想跑步的工具限制

自动梦想子代理会收到附加到其提示中的强化工具约束注释:

"Bash is restricted to read-only commands (ls, find, grep, cat, stat, wc, head, tail).
Anything that writes, redirects to a file, or modifies state will be denied.
Plan your exploration with this in mind — no need to probe."

这是通过附加的 extra 仅在自动梦想运行中使用参数 — 手动 /dream 技能在具有正常权限的主循环中运行。

DreamTask:UI 可见性

分叉的梦想代理出现在页脚药丸和 Shift+Down 后台任务对话框中 tasks/DreamTask/DreamTask.ts。 它跟踪:

  • phase: 'starting' | 'updating' — 翻转到 'updating' 当第一个编辑/写入工具调用到达时
  • filesTouched — 部分列表(错过 Bash 介导的写入,仅捕获模式匹配的工具调用)
  • turns — 最后 30 个助手回合,tool_use 方块折叠成一个计数
锁的力学
Dream 使用文件实时锁定 consolidationLock.ts. tryAcquireConsolidationLock() returns null 如果另一个过程正在中期合并。 如果运行失败或用户从任务对话框中终止它, rollbackConsolidationLock(priorMtime) 倒回锁定文件,以便下一个会话可以重试。 扫描限制(10 分钟)充当重试之间的退避。
07 助理模式内存:每日日志与 MEMORY.md

标准 Claude Code 内存使用单个 MEMORY.md 模型读取和写入的索引文件。 KAIROS 助手模式使用完全不同的模型:仅附加的每日日志。

标准模式

  • Single MEMORY.md file
  • Model直接读写
  • 通过 TEAMMEM 同步在团队之间共享
  • AutoDream 定期对其进行整合
  • 会话量大时扩展性较差

KAIROS 助手模式

  • 每日日志文件: logs/YYYY/MM/YYYY-MM-DD.md
  • 仅在工作期间追加 — 不覆盖
  • Dream Skill 每晚将日志提取到主题文件中
  • MEMORY.md 成为综合索引
  • 与 TEAMMEM 同步不兼容(明确关闭)

每日日志路径的计算方式为 getAutoMemDailyLogPath() in memdir/paths.ts:

// memdir/paths.ts
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`)
  // → ~/.claude/memory/logs/2026/03/2026-03-31.md
}
08 会话连续性: --session-id Flag

KAIROS 的定义功能之一是持久会话身份。 KAIROS 会话可以在重新启动时恢复:

# Restart and continue the same conversation
claude remote-control --session-id=<id>
claude remote-control --continue   # alias: -c

这些标志被解析为 bridge/bridgeMain.ts 并且明显落后于 feature('KAIROS') 警卫。 来自评论:

// bridge/bridgeMain.ts
// feature('KAIROS') gate: --session-id is ant-only; without the gate,
// external builds would expose an argument that does nothing.
if (feature('KAIROS') && arg === '--session-id' && ...) { ... }
if (feature('KAIROS') && arg.startsWith('--session-id=')) { ... }
if (feature('KAIROS') && (arg === '--continue' || arg === '-c')) { ... }

会话是通过 perpetual 桥配置中的标志。 当会话是永久的时,无环境的桥接路径(通常提供更好的性能)回退到基于环境的路径以保持交叉重启会话的连续性:

// initReplBridge.ts
// perpetual (assistant-mode session continuity via bridge-pointer.json) is
// env-coupled and not yet implemented in env-less — fall back to env-based
// when set so KAIROS users don't silently lose cross-restart continuity.
if (isEnvLessBridgeEnabled() && !perpetual) { ... }
09 设置:用户如何配置助手模式

KAIROS 将多个设置键添加到 Claude Code 设置架构中(utils/settings/types.ts):

KeyTypePurposeGate
assistant boolean 以助手模式启动克劳德(自定义系统提示、简要视图、定时签到技巧) KAIROS
assistantName string claude.ai 会话列表中的显示名称 KAIROS
defaultView '聊天' | '成绩单' 聊天视图 = 仅 SendUserMessage 检查点。 成绩单 = 完整的工具输出。 'chat' 激活简短选择加入。 凯罗斯 || KAIROS_BRIEF
minSleepDurationMs number 睡眠工具必须进行的最短睡眠时间。 限制托管环境中的主动滴答频率。 积极主动 || 凯罗斯
maxSleepDurationMs 数字(-1 = 不确定) 最大睡眠时间。 -1 = 仅等待用户输入。 限制远程环境中的空闲时间。 积极主动 || 凯罗斯
autoDreamEnabled boolean 覆盖 GrowthBook 默认的后台内存整合。 用户设置胜过 GB 标志。 始终存在
channelsEnabled boolean 选择加入 MCP 频道通知(从 MCP 服务器推送)。 默认关闭。 始终存在
allowedChannelPlugins array 组织级别的渠道插件白名单。 设置后替换 Anthropic 分类帐。 始终存在
10 主动模式下系统提示

当主动性活跃时, getSystemPrompt() 采用与普通结构化部分方法完全不同的路径:

// constants/prompts.ts — proactive path
if ((feature('PROACTIVE') || feature('KAIROS')) && proactiveModule?.isProactiveActive()) {
  logForDebugging('[SystemPrompt] path=simple-proactive')
  return [
    `\nYou are an autonomous agent. Use the available tools to do useful work.\n\n${CYBER_RISK_INSTRUCTION}`,
    getSystemRemindersSection(),
    await loadMemoryPrompt(),
    envInfo,
    getLanguageSection(settings.language),
    isMcpInstructionsDeltaEnabled() ? null : getMcpInstructionsSection(mcpClients),
    getScratchpadInstructions(),
    getFunctionResultClearingSection(model),
    SUMMARIZE_TOOL_RESULTS_SECTION,
    getProactiveSection(),   // ← tick loop + Sleep + focus instructions
  ].filter(s => s !== null)
}

标准路径使用带有缓存和节标识符的动态节注册表。 主动路径返回一个平面数组——更简单、更快,并且针对持续运行的代理的缓存缺失严重的性质进行了优化。

简要部分重复数据删除
getBriefSection() 包括一个守卫:当主动主动处于活动状态时, getProactiveSection() 已经附加 BRIEF_PROACTIVE_SECTION 内联(在终端焦点段落的末尾)。 如果没有守卫,系统提示中就会出现两次简要说明。
11 GrowthBook Kill-Switch 架构

KAIROS 的运行时行为广泛地由 GrowthBook 功能标志控制,使 Anthropic 能够在不部署的情况下调整或终止子系统。 该模式在整个代码库中是一致的:

// Pattern: cached refresh with explicit interval
const KAIROS_BRIEF_REFRESH_MS = 5 * 60 * 1000  // 5 minutes
const KAIROS_CRON_REFRESH_MS  = 5 * 60 * 1000  // 5 minutes

// Brief entitlement — checks GB flag, refreshes every 5 min
getFeatureValue_CACHED_WITH_REFRESH('tengu_kairos_brief', false, KAIROS_BRIEF_REFRESH_MS)

// Cron kill switch — fleet-wide disable
getFeatureValue_CACHED_WITH_REFRESH('tengu_kairos_cron', true, KAIROS_CRON_REFRESH_MS)

// Durable cron kill switch (narrower — leaves session-only cron untouched)
getFeatureValue_CACHED_WITH_REFRESH('tengu_kairos_cron_durable', true, KAIROS_CRON_REFRESH_MS)

// AutoDream thresholds + enabled gate
getFeatureValue_CACHED_MAY_BE_STALE('tengu_onyx_plover', null)

// Cron jitter config — ops can push during an incident to reduce load
getFeatureValue_CACHED_WITH_REFRESH('tengu_kairos_cron_config', null, ...)

评论中 cronJitterConfig.ts 解释了事件的故事: “在事件发生期间,操作员可以推动 tengu_kairos_cron_config 例如 高抖动乘数可将负载分散到整个机群中。” 5 分钟刷新间隔经过专门调整,以便 GB 更改在一个缓存窗口内生效,速度足以满足事件响应,但又不会太快而增加持续的网络压力。

12 架构图:完整的 KAIROS 系统
graph TD subgraph "Build Time" F1["feature('KAIROS')"] F2["feature('KAIROS_BRIEF')"] F3["feature('AGENT_TRIGGERS')"] F4["feature('KAIROS_GITHUB_WEBHOOKS')"] F5["feature('PROACTIVE') || KAIROS"] end subgraph "Runtime State" KA[kairosActive: boolean] UMO[userMsgOptIn: boolean] end subgraph "Output Tools" BT[BriefTool / SendUserMessage] SFT[SendUserFileTool] PNT[PushNotificationTool] end subgraph "Lifecycle Tools" ST[SleepTool] SPRT[SubscribePRTool] CC[CronCreate] CD[CronDelete] CL[CronList] end subgraph "Background Services" ADR[AutoDream\nforked sub-agent] CS[CronScheduler\n1s poll loop] end subgraph "Memory" DL["Daily Logs\nlogs/YYYY/MM/DD.md"] MEM[MEMORY.md index] CP[ConsolidationPrompt\n4-phase dream] end F1 --> KA F1 --> BT F1 --> SFT F1 --> PNT F2 --> BT F3 --> CC & CD & CL F4 --> SPRT F5 --> ST KA --> DL KA --> BT KA --> ADR CS --> |fires prompt| ST CC --> CS ADR --> CP CP --> DL CP --> MEM
13 主要设计原则

研究 KAIROS 源代码揭示了 Anthropic 一致应用的几个架构原则:

原则 1:DCE 的正三元数

每个功能门控块都使用正三元数而不是负早期回报:

// CORRECT — DCE works
return feature('KAIROS') ? doKairosThings() : false

// WRONG — DCE fails (negative guard defeats constant-folding)
if (!feature('KAIROS')) return false
return doKairosThings()

原则 2:独立可运输性

每个子功能都经过精心设计,可以独立发布和终止切换。 cron 模块图的导入为零 src/assistant/。 BriefTool有自己的 KAIROS_BRIEF 旗帜。 这意味着完全助手模式中的错误不会阻止 cron 调度程序的运行。

原则 3:最便宜的登机口优先

所有 KAIROS 子系统都按照最便宜的评估顺序检查门。 自动梦想检查 kairosActive (一次布尔读取)在检查时间之前、在读取文件系统的会话计数之前、在获取锁之前。 这很重要,因为这些检查在每个代理轮次上运行。

原则 4:操作员终止开关

每个 GrowthBook 门控子系统都有一个获胜的本地环境变量覆盖: CLAUDE_CODE_DISABLE_CRON 杀死 cron 调度程序, CLAUDE_CODE_BRIEF 启用 Brief 进行开发/测试。 这使得个别工程师可以绕过车队大门,而无需接触 GrowthBook。

原则 5:系统提示中的成本预算

该模型明确告知 API 调用成本和提示缓存机制。 “每次唤醒都会花费一次 API 调用,但提示缓存会在 5 分钟不活动后过期 - 相应地平衡。” 这是异常透明的系统提示工程——将模型视为具有成本意识的参与者,而不是向其隐藏基础设施详细信息。

要点

  • KAIROS 是一系列构建时标志,而不是单个开关。 核心标志是ant-only; 子功能如 KAIROS_BRIEF, KAIROS_CHANNELS, 和 AGENT_TRIGGERS 独立运送给外部用户。
  • kairosActive in bootstrap/state.ts 是运行时枢纽,可同时更改内存模式、BriefTool 选择行为、快速模式可用性和桥接工作器类型。
  • 滴答循环使用 <tengu_tick> XML 心跳 + SleepTool 作为一种成本感知的闲置机制。 该模型在系统提示中明确告知缓存过期和 API 调用成本。
  • 简述工具分离 entitlement (允许使用?)来自 activation (选择加入?)以防止注册用户默认情况下出现静默简报。
  • AutoDream fires as a forked sub-agent after 24 hours and 5 sessions, using a file-mtime lock with rollback on failure. 它收到手册中不存在的强化只读工具约束 /dream runs.
  • cron 系统有两层:仅会话层(内存中)和持久层(持久化) .claude/scheduled_tasks.json)。 两者都可以通过 GrowthBook 独立进行终止切换,无需部署。
  • 正三元数对于消除死代码是必需的 — Bun 常量折叠 feature('KAIROS') to false 仅当守卫是三元数,而不是负的提前返回时,才在外部构建中。

检查你的理解情况

Q1. 为什么会 isBriefEnabled() 有自己的顶级 feature('KAIROS') || feature('KAIROS_BRIEF') 守卫,即使它打电话 isBriefEntitled() 哪个有自己的警卫?
Q2. When kairosActive 这是真的,AutoDream 会发生什么?
Q3. 创建一个 cron 任务 recurring: true, permanent: false。 之后会发生什么 recurringMaxAgeMs 已经过去了?
Q4. 为什么主动系统提示会告诉模型有关 5 分钟提示缓存到期窗口的信息?