第11章 · KAIROS:自主助手模式全解
第11章 · KAIROS:自主助手模式全解
11.1 KAIROS在代码库中的分布
KAIROS是Claude Code中最引人注目的隐藏系统之一。通过对泄露源码的全面检索,我们发现feature('KAIROS')在57个文件中出现了158次,遍布代码库的各个核心模块。这一分布密度表明KAIROS不是一个实验性附加功能,而是深度嵌入Claude Code架构的核心系统。
KAIROS的设计哲学体现在其名称本身——在希腊语中,Kairos(καιρός)意为"恰当的时机"或"关键时刻",与Chronos(线性时间)形成对比。这暗示了KAIROS系统的核心理念:AI不是被动等待用户指令,而是在"恰当的时机"主动采取行动。
11.2 六个KAIROS子标志矩阵
KAIROS采用分层特性标志设计,一个主标志加五个子标志,构成了精细的功能控制矩阵:
| 标志名 | 控制功能 | 门控逻辑 | 关键文件 |
|---|---|---|---|
KAIROS | 主开关:自主Agent模式 | 编译时消除 | tools.ts, prompts.ts, main.tsx |
KAIROS_BRIEF | Brief工具:状态感知消息 | KAIROS || KAIROS_BRIEF | tools/BriefTool/ |
KAIROS_CHANNELS | 外部渠道集成(Slack/Discord/SMS) | KAIROS || KAIROS_CHANNELS | services/mcp/channelNotification.ts |
KAIROS_PUSH_NOTIFICATION | 系统推送通知 | KAIROS || KAIROS_PUSH_NOTIFICATION | tools/PushNotificationTool/ |
KAIROS_GITHUB_WEBHOOKS | GitHub PR订阅与Webhook | 独立标志 | tools/SubscribePRTool/ |
KAIROS_DREAM | 自主记忆巩固(Dream模式) | 独立标志 | tasks/DreamTask/, services/autoDream/ |
值得注意的是门控逻辑的设计:大多数子标志采用OR门控(KAIROS || KAIROS_XXX),这意味着这些功能既可以作为完整KAIROS模式的一部分启用,也可以作为独立功能独立激活。这种设计为Anthropic提供了极大的灰度发布灵活性——他们可以先向部分用户推送Brief工具或推送通知功能,而不必启用完整的自主Agent模式。
11.3 assistant/模块:会话历史管理
assistant/sessionHistory.ts实现了KAIROS的会话历史管理,为长期运行的自主Agent提供了会话恢复能力:
export type HistoryPage = {
events: SDKMessage[] // 按时间顺序排列的事件
firstId: string | null // 最早事件ID,用于向前翻页
hasMore: boolean // 是否还有更早的事件
}该模块通过OAuth令牌和组织UUID进行认证,支持基于游标的分页查询,每页加载100个事件(HISTORY_PAGE_SIZE = 100)。核心API包括:
createHistoryAuthCtx(sessionId)— 创建认证上下文fetchLatestEvents(ctx, limit)— 获取最新事件fetchOlderEvents(ctx, beforeId, limit)— 获取更早事件
这套分页API的设计表明KAIROS的会话可能持续数小时甚至数天,需要高效的历史回溯机制。
11.4 系统提示:自主Agent的完整指令
当KAIROS或PROACTIVE模式激活且isProactiveActive()返回true时,系统提示中会注入一段关键文本(constants/prompts.ts,472-879行):
You are an autonomous agent. Use the available tools to do useful work.这行简洁的开场白之后,跟随着详细的自主工作指南(864-879行):
# Autonomous work
You are running autonomously. You will receive `<tick>` prompts that keep
you alive between turns — just treat them as "you're awake, what now?"
The time in each `<tick>` is the user's current local time. Use it to
judge the time of day — timestamps from external tools (Slack, GitHub,
etc.) may be in a different timezone.
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.提示中还包含了关于资源管理的精妙指导:
## Pacing
Use the Sleep tool to control how long you wait between actions. Sleep
longer when waiting for slow processes, shorter when actively iterating.
Each wake-up costs an API call, but the prompt cache expires after 5
minutes of inactivity — balance accordingly.
**If you have nothing useful to do on a tick, you MUST call Sleep.**
Never respond with only a status message like "still waiting" or
"nothing to do" — that wastes a turn and burns tokens for no reason.这段提示揭示了KAIROS的运营成本模型:每次wake-up消耗一次API调用,但prompt cache在5分钟不活动后过期。KAIROS需要在"保持活跃"和"节省成本"之间找到平衡点。
首次唤醒时的行为也有明确规定:
## First wake-up
On your very first tick in a new session, greet the user briefly and
ask what they'd like to work on. Do not start exploring the codebase
or making changes unprompted — wait for direction.这表明即使是自主Agent,Anthropic也设计了"征求许可"的初始行为模式,避免Agent在用户不知情的情况下修改代码库。
11.5 <tick>心跳机制
<tick>是KAIROS最核心的运行时机制,实现于cli/print.ts(1835-1856行):
const tickContent = `<${TICK_TAG}>${new Date().toLocaleTimeString()}</${TICK_TAG}>`
enqueue({
mode: 'prompt' as const,
value: tickContent,
uuid: randomUUID(),
priority: 'later',
isMeta: true,
})tick的关键特征:
- 触发条件:当
isProactiveActive()为true且未暂停时,通过setTimeout(..., 0)循环触发 - 内容格式:
<tick>HH:MM:SS AM/PM</tick>,包含用户当前本地时间 - 优先级:设为
'later',允许与其他消息批量处理 - 元数据标记:
isMeta: true表明这是系统元数据而非用户输入
tick标签在constants/xml.ts中定义为常量TICK_TAG = 'tick'。UI层面,components/messages/UserTextMessage.tsx会提取tick标签以进行特殊渲染,而utils/sessionStorage.ts通过识别tick来判断自主模式的prompt。
从架构角度看,tick机制本质上是一个"轮询式唤醒"系统。与传统的事件驱动架构不同,KAIROS采用了"周期性检查"的模式——这可能看起来效率较低,但考虑到LLM的无状态特性(每次调用都需要完整上下文),tick机制是一种务实的设计选择。
11.6 Proactive模式:运行时激活路径
KAIROS的激活状态通过bootstrap/state.ts中的全局状态管理:
export function getKairosActive(): boolean {
return STATE.kairosActive
}
export function setKairosActive(value: boolean): void {
STATE.kairosActive = value
}这个状态被广泛用于代码库中的条件判断:
- 禁用AutoDream(KAIROS使用自己的磁盘技能Dream替代):
services/autoDream/autoDream.ts:96 - 控制自主Agent模式的激活
- 门控各种依赖KAIROS的行为
isProactiveActive()函数是tick机制和自主提示的最终守门人。它不仅检查KAIROS标志,还检查运行时的Proactive状态,允许在非KAIROS构建中通过Proactive路径激活类似行为。
11.7 KAIROS专属工具链
三个工具仅在KAIROS相关标志启用时才被编译和加载(tools.ts,42-52行):
SendUserFileTool(KAIROS独占):
const SendUserFileTool = feature('KAIROS')
? require('./tools/SendUserFileTool/SendUserFileTool.js').SendUserFileTool
: null允许自主Agent向用户发送文件,例如生成的报告、分析结果或代码产物。这对于长时间运行的自主任务至关重要——Agent可能在用户离线时完成了工作,需要主动推送结果。
PushNotificationTool(KAIROS或独立启用):
const PushNotificationTool =
feature('KAIROS') || feature('KAIROS_PUSH_NOTIFICATION')
? require('./tools/PushNotificationTool/PushNotificationTool.js')
.PushNotificationTool
: null系统推送通知能力,让Agent能够在重要事件发生时通知用户——例如长时间构建完成、监控到的异常、或需要人类决策的关键节点。
SubscribePRTool(GitHub Webhooks独立标志):
const SubscribePRTool = feature('KAIROS_GITHUB_WEBHOOKS')
? require('./tools/SubscribePRTool/SubscribePRTool.js').SubscribePRTool
: nullPR订阅工具使Agent能够监控GitHub Pull Request的状态变化,实现自动化的代码审查流程。这指向了KAIROS作为"值班开发者"的产品愿景。
11.8 SleepTool:自主Agent的节奏控制器
SleepTool(tools/SleepTool/prompt.ts)是KAIROS运行节奏的核心控制器:
export const SLEEP_TOOL_PROMPT = `Wait for a specified duration.
The user can interrupt the sleep at any time.
Use this when the user tells you to sleep or rest, when you have
nothing to do, or when you're waiting for something.
You may receive <tick> prompts — these are periodic check-ins.
Look for useful work to do before sleeping.
You can call this concurrently with other tools — it won't interfere
with them.
Prefer this over Bash(sleep ...) — it doesn't hold a shell process.
Each wake-up costs an API call, but the prompt cache expires after
5 minutes of inactivity — balance accordingly.`关键设计特点:
- 非阻塞:不占用Shell进程,与
Bash(sleep ...)形成对比 - 可中断:用户可以随时中断Sleep
- 可并发:不干扰其他并发工具调用
- Cache感知:明确提醒prompt cache在5分钟后过期,帮助Agent在成本和响应性之间做出平衡
11.9 BriefTool:状态感知的智能通信
BriefTool(tools/BriefTool/BriefTool.ts)为KAIROS提供了区分主动通知和被动响应的能力:
const inputSchema = z.strictObject({
message: z.string()
.describe('The message for the user. Supports markdown formatting.'),
attachments: z.array(z.string()).optional()
.describe('Optional file paths to attach.'),
status: z.enum(['normal', 'proactive'])
.describe("Use 'proactive' when surfacing something user hasn't asked for..."),
})status: 'proactive'标记让UI层能够以不同方式呈现Agent主动发起的消息(如使用不同的颜色或通知级别),这对于用户体验至关重要——用户需要快速区分"我问的问题的答案"和"Agent觉得我应该知道的事情"。
11.10 Channel Notification:外部消息集成
services/mcp/channelNotification.ts实现了KAIROS与外部通信渠道(Discord、Slack、SMS等)的集成:
export const ChannelMessageNotificationSchema = z.object({
method: z.literal('notifications/claude/channel'),
params: z.object({
content: z.string(),
meta: z.record(z.string(), z.string()).optional(),
}),
})消息流程:
- MCP服务器发送channel notification
- 消息被包裹在
<channel>标签中并入队 - SleepTool通过
hasCommandsInQueue()检测到新消息,在1秒内唤醒Agent - Agent看到消息来源,决定是通过渠道工具回复、发送SendUserMessage,还是两者兼顾
准入条件相当严格:
- 需要
KAIROS或KAIROS_CHANNELS特性标志 - 需要GrowthBook
tengu_harbor运行时标志 - 必须使用claude.ai OAuth认证(API key用户被阻止)
- Teams/Enterprise用户需要管理员明确启用
channelsEnabled: true
这一设计表明Anthropic对Channel功能保持高度谨慎——一个能接收外部消息并自动响应的AI Agent,其安全性和滥用风险需要仔细控制。
11.11 KAIROS与Bridge的集成
KAIROS的自主Agent天然需要长时间运行,这使其与Bridge系统(第15章详述)形成了紧密的协作关系。通过Bridge,KAIROS Agent可以:
- 在远程服务器上持续运行,不依赖用户的终端会话
- 通过WebSocket与用户的桌面客户端保持连接
- 在用户断线后继续工作,重连后同步状态
- 通过PushNotification和SendUserFile主动推送结果
claude assistant [sessionId]子命令提供了连接到正在运行的KAIROS会话的入口,允许用户随时接入查看Agent的工作状态。