监视会话 0.9.10 新增
智能体可以监视其他会话,而不必一遍遍地去查看它们。它先订阅,然后继续自己的工作或等待;被监视的会话中发生某些事情时,OAR 会唤醒它:有提问在等待回答、某一轮失败、某个会话给出回复、某个后台任务结束。唤醒的方式是 OAR 在监视者的对话中写入一条简短消息。
典型的请求:
- 照看一批会话。 “监视那三个审查会话。其中一个提问或失败时唤醒我,等它们全部完成后汇总它们的回复。”
- 等待一项耗时任务。 “在一个会话中启动完整的测试运行并监视它。它的后台任务完成时告诉我,如果失败了也要说。”
- 留意另一台机器。 “监视
build-上的夜间部署会话,有错误就告诉我。”box
这些会话可以在此中继上(需启用智能体会话),也可以在已配对的中继上。除 Claude Cloud 和 OpenAI Image 外,每个提供商都可以监视;这两者的会话无法订阅(见按提供商)。工具本身,即 relay_ 的 subscribe,列在参考的监视会话中;本页说明你会看到什么、可以控制什么。
什么会唤醒监视者 #
订阅会指明要监视的会话,或者某台中继的所有会话(包括之后创建的会话)。它可以要求在以下情况得到通知:
| 事件 | 通俗地说 |
|---|---|
| Question(提问) | 被监视的会话在等待回答或审批。消息中带有问题及其选项。0.9.16 新增 对于不阻塞的提问,订阅稍后还会得知你的回答。 |
| Error(错误) | 某一轮失败、达到了用量上限,或者会话的智能体进程意外终止。 |
| Reply(回复) | 某个会话完成了一轮。消息中带有回复的开头部分。 |
| Task started, finished, failed(任务已开始、已结束、已失败) | 被监视会话的某个后台智能体或 shell 任务开始了(仅当订阅要求时)、完成了或失败了。以非零状态退出的 shell 命令算作失败。 |
| Stalled(停滞) | 某个会话仍在工作,但已经有一段时间没有动静。 |
| All idle(全部空闲) | 被监视的会话中已没有任何东西在运行。 |
0.9.13 新增 没有指明事件的订阅,不会因为某个 shell 命令或 monitor 正常结束而被唤醒:繁忙的会话大约每分钟就会结束一个,而每次唤醒都要让监视者带着完整上下文跑一轮。已完成的子智能体和失败的任务仍会唤醒它。必须跟踪每条命令的智能体,要明确要求所有任务结束事件。此前创建、没有指明事件的订阅会自动切换到这个默认设置;指明了事件的订阅保持不变。
确切的事件名称,以及订阅可用的选项(回复和任务结果必须匹配的正则表达式、触发一次后结束、判定为 stalled 之前的静默时间),见参考。
监视者自己的对话永远不会被监视,因此它自己的轮次不会唤醒它。
订阅只负责通知
它不批准任何事,也不回答任何事。被监视会话中的提问会一直保持待回答状态,直到你或被允许回答它的智能体作答,与以前完全一样。被监视会话中的审批卡片只能由你回答;事件中会说明这一点。
审批卡片 #
对话中的智能体第一次订阅某台中继的会话时,必须先询问你。该对话中会出现一张审批卡片:
This agent wants to watch “Review: server/” (3f9c…), “Review: web/” (a12b…) and be woken by their events.
Events: question_asked, error, turn_end, subagent_finished, task_failed, stalled, all_idle
| 你的选择 | 结果 |
|---|---|
| Allow(允许) | 订阅被创建。该对话之后对同一中继上会话的订阅不再需要新卡片。 |
| Deny(拒绝) | 订阅被拒绝。智能体会得到通知,并在没有该订阅的情况下继续工作。 |
特殊情况:
- 所有会话。 对
all的订阅总会写明:“ALL sessions of this relay, including ones created later”(此中继的所有会话,包括之后创建的);0.9.16 新增 当它排除了某些会话时,还会加上“except N it leaves out”(不含其排除的 N 个)。如果第一张卡片针对的不是all,之后对all的订阅会再次询问。如果是,Allow 就涵盖之后的所有订阅,包括all。 - 已配对的中继。 卡片会注明该中继。每台中继单独询问,且不会在另一台中继上询问任何事。
- 接管。 取代另一个监视者的智能体,可以接手旧监视者的全部订阅。这种情况总会询问,无论你之前允许过多少张卡片。卡片会说明有多少个订阅要转移、来自哪个会话;旧会话不再收到这些订阅的事件,订阅保留原有设置。你的 Allow 同时算作对所涉及中继上订阅的批准;如果其中有订阅监视了所有会话,也包括
all。
0.9.16 新增 卡片还会注明订阅的选项:once(仅一次)、heartbeat every N min(每 N 分钟心跳)、digest every N min(每 N 分钟汇总)以及带时区的 quiet HH:MM–HH:MM(免打扰 HH:MM–HH:MM)。
卡片在每种中继模式下都会出现:它与 ask、plan 或 agent 无关。批准归属于该对话,中继重启后依然保留。
你会看到什么 #
小标签及其列表 #
对话有订阅时,其标题栏显示 watching N sessions(正在监视 N 个会话),统计它监视的所有不同会话。如果有订阅监视全部会话,则显示 watching all sessions(正在监视所有会话);如果对话还按名称列出了会话,后面会跟上 (+N listed)(+N 个已列出)。0.9.16 新增 旁边的小提示会显示订阅的选项,digest N min(摘要 N 分钟)或 quiet HH:MM–HH:MM,最多两个。点击小标签会打开列表:每个订阅一行,列出会话(或中继)、事件,以及它是否为 once 或带有心跳,0.9.16 新增 是否设置了摘要、免打扰时段或排除了会话,排除的会话显示为 N left out(已排除 N 个)。Unsubscribe(取消订阅)会立即结束该订阅,无需询问智能体。
watched 徽标 #
被另一个对话按名称监视的会话,会在会话列表和它的标题栏中带有 watched(监视)徽标。将鼠标悬停在徽标上可以看到谁在监视;已配对中继上的智能体显示为它的会话和中继。对所有会话的订阅不会在会话列表中添加徽标,只会出现在每个会话的标题栏中。你在已配对中继上的订阅不会在你这一侧添加徽标。0.9.16 新增 被“全部会话”订阅排除的会话,不会因该订阅显示徽标。
事件行 #
在监视者的对话记录中,事件显示为一个标有 relay event(中继事件)的紧凑行,绝不会作为你的消息显示。它折叠成一行,例如:
relay event 3 events · question, reply
展开即可阅读各行内容,例如:
[relay event] session "Review: server/" (3f9c…): turn_end (done) "Found 4 places without input checks: …"
包含提问或错误的行保持展开。汇总了因每小时上限而被扣留的事件的行,以 Digest(摘要)开头;0.9.16 新增 由订阅的摘要选项汇总的行也是如此,而在免打扰时段内被扣留的事件所在的行以 After quiet hours(免打扰时段后)开头。标有 replayed(已重放)的行,包含已配对中继在连接中断期间保留的事件。
这一行背后是一条消息,消息开头有一行说明:它是自动发出的,不是你发的,也不批准任何事。智能体同样会读到这一行。
监视者正忙时 #
- 空闲。 消息会开始新的一轮。
- 一轮进行中。 在 Claude、DeepSeek 以及 GitHub Copilot 和 OpenAI 的 SDK 引擎上,消息会被引导进正在运行的这一轮。在其他提供商上,它会等待,并成为下一轮。消息仍在等待时到达的事件会并入这条消息,因此忙碌的监视者只会收到一条后续消息,而不是每个事件一条。
节奏控制 #
每次唤醒都要让监视者跑一轮,所以 OAR 会限制唤醒次数。
- 合并。 30 秒内的事件合并为一条消息送达。
- 每小时上限。 最近一小时内已唤醒 20 次后,其余事件会被扣留,每 10 分钟以摘要形式发送一次。一旦最近一小时内的唤醒少于 20 次,就恢复按 30 秒合并唤醒。
- 从不扣留。 提问、0.9.16 新增 你对非阻塞提问的回答以及错误总是立即送达,即使超过上限也一样。但它们仍计入上限。
- 停滞。 当某个会话在某一轮或后台任务仍在运行时已静默 15 分钟(或订阅选定的时间),就算作停滞。每段静默期只报告一次。正在等待回答的会话不算停滞:它的提问已经报告过了。
- 心跳。 如果智能体要求了心跳,那么在被监视的轮次或任务运行期间,它会按该间隔收到消息;一切空闲时则不会收到。心跳让监视者知道监视在正常工作。心跳不会被扣留到摘要中,也不计入上限。
同样的数值也列在参考的事件如何送达中。
减少唤醒 0.9.16 新增 #
智能体可以为每个订阅要求减少唤醒。提问和错误仍会立即送达;其他一切都要等待。
| 选项 | 作用 |
|---|---|
Digest(digest_,1 到 1440) |
该订阅的事件每 N 分钟合并为一条消息送达,下一条最早在上一条之后 N 分钟。 |
免打扰时段(quiet_,例如 {"from":"23:) |
某个时区中的每日时间窗口,可以跨越午夜,并随夏令时调整。窗口内发生的事情会在窗口结束时合并为一条消息送达,并标明是在免打扰时段内扣留的。窗口内不发送心跳。 |
排除会话(exclude,最多 50 个会话 id) |
监视全部会话的订阅会忽略这些会话,判断“已没有任何东西在运行”和发送心跳时也一样。 |
在时钟回拨、结束时间出现两次的那一夜,窗口在第一次到达结束时间时结束,在重复的那一小时内不会再次进入;在时钟拨快、跳过结束时间的那一夜,窗口在时钟跳变的那一刻结束。有一个限制:如果开始时间落在重复的那一小时内,窗口会在第一次经过时开始,而第二次经过时,开始时间之前的那几分钟算在窗口之外。
不回显。 当监视者自己向某个会话发送提示词并等待完整回复(通过 send、create_ 或之后的 wait)时,那一轮的回复不会再次唤醒它。那一轮的错误和提问仍会唤醒它,而它没有等待的提示词也会像以前一样唤醒它。
被扣留的事件在中继重启后依然保留,每小时上限也仍然叠加生效。智能体可以用 list_ 查看每个订阅扣留了多少事件、何时送达。详情见参考的减少唤醒。
订阅持续多久 #
订阅在以下情况下结束:
- 智能体或你取消订阅;
- 监视者的对话被归档或删除;
- 被监视的会话被归档或删除。列出多个会话的订阅会保留其他会话,直到最后一个会话结束时才结束;
- 它是 once 订阅且已触发(带正则表达式时,在第一次匹配时触发);
- 对于已配对的中继,配对被移除:那台中继上的订阅立即结束。
订阅和尚未送达的事件在中继重启后依然保留。
一个对话同时最多可有 20 个订阅。
已配对中继上的会话 #
监视已配对中继上的会话,所需条件与在那里进行任何 relay_ 调用相同:
- 该中继在对话中已解锁;
- 它针对此中继的 Agents may(智能体可以)级别至少允许读取(已配对的中继允许什么);
- 另一台中继接受其他中继的智能体:Accept prompts from other relays' agents(接受其他中继上智能体的提示词)。
如上所述,卡片在这里询问。配对只需单向存在。你的中继每隔几秒从另一台中继获取事件,这些行以另一台中继的名称开头:
[relay event] build-box · session "Nightly deploy" (77aa…): turn_end (done) "Deployed. The health check is green."
如果另一台中继一分钟内没有响应,连接就视为已断开。另一台中继会保留期间发生的事情:每个订阅最多 500 个事件,最长 7 天。它再次响应时,一个标有 replayed 的行会把这些事件带回来,提问和错误排在前面,位于 link_ 行和 link_ 行之间。如果发生的事件超出它能保留的数量,最后一行会说明丢弃了多少。7 天内无人获取的订阅会在那台中继上结束。0.9.16 新增 重放的事件和其他事件一样,遵守订阅的摘要和免打扰时段设置;这时最后一行会说明其中有多少条稍后送达。
0.9.16 新增 对已配对中继的订阅,其摘要和免打扰时段在这里,即监视者所在的地方生效;另一台中继会被告知哪些会话被排除。运行旧版 OAR 的已配对中继不认识 exclude:你的中继仍会丢弃这些会话的事件,但那台中继在判断“已没有任何东西在运行”、判断停滞以及生成心跳列表时,仍会把它们算在内。
运行旧版 OAR 的已配对中继会答复说它需要更新。
按提供商 #
哪些会话可以被监视与提供商无关:中继上的任何会话都可以。区别在于进行监视的那个会话。
| 监视方会话的提供商 | 能否订阅 | 一轮运行期间的事件 |
|---|---|---|
| Claude | 能 | 被引导进正在运行的这一轮 |
| DeepSeek 0.9.17 新增 | 能 | 被引导进正在运行的这一轮 |
| GitHub Copilot、OpenAI,SDK 引擎 | 能 | 被引导进正在运行的这一轮 |
| GitHub Copilot、OpenAI,扩展引擎 | 能 | 成为下一轮 |
| Cursor | 能 | 成为下一轮 |
| Grok | 能 | 成为下一轮 |
| Claude Cloud | 否:它没有 relay_ |
|
| OpenAI Image | 否:它调用 Images API,不运行智能体 |
哪些提供商才有 relay_,见智能体工具。
更新前启动的会话
会话 worker 在启动时构建自己的工具。如果你更新到 0.9.10 时某个对话的智能体已在运行,那么在重启之前它没有 subscribe:对空闲会话执行 Kill session(强制结束会话)就够了。