Skip to main content
当多个会话处理同一问题时——例如管理者将任务委派给子会话、人类直接进入工作会话,或两个智能体通过 sessions_send 协作——每个会话都会形成对其他会话的假设。一旦其他参与者介入,这些假设就会过时。会话状态感知机制会检测这种介入,向受影响的会话通知一次,并为其提供一种低成本的方法,以便在采取行动前掌握最新情况。 三个部分协同工作:
  1. 持久信号日志记录每个会话中选定的状态变更。
  2. 观察者维护每个目标的游标,并接收一条合并后的状态过期通知。
  3. 协调通过带有 changesSincesession_status 拉取精确增量。

信号日志

当受观察的会话发生实质性变更时,OpenClaw 会将一个带类型的事件追加到共享状态数据库(session_state_events)中。事件包含元数据和单行摘要,但绝不包含消息内容。 每个事件都会标明其参与者(humanagentsystem)。被取消和超时的子任务运行会记录为失败,并在事件载荷中保留精确结果(cancelledtimeouterror)。 会话的状态版本就是其日志中的最高序列号,并记录在一个持久的每会话头记录中,因此即使日志被修剪也不会丢失。会话记录过变更时,sessions_list 行会包含 stateVersionsession_status 始终会报告它。 仅记录日志的类型用于协调历史,而非通知:常规的子任务运行完成消息仍由子智能体通知负责传递,信号日志绝不会重复发送。

观察者

观察者是对目标持有游标(session_watch_cursors)的会话。游标有两个来源:
  • 隐式(生成边)。 当会话生成子智能体或 ACP 子会话时,父会话的游标会自动初始化为子会话生成时的版本。父会话无需手动订阅。
  • 显式(sessions_send watch: true)。 任何协调者都可以观察非自身生成的目标:在 sessions_send 中传入 watch: true,发送成功分派后,发送方会注册为实际接收消息的会话的观察者。注册从目标当前的状态版本开始——之前的历史绝不会产生通知。设置该参数后,工具结果会报告 watched: true|false
观察者身份必须是包含智能体限定信息的会话键。在 session.scope="global" 下,共享的 global 键在不同智能体之间存在歧义,因此此类会话会获得持久日志和 changesSince,但不会收到主动通知。 观察关系会自动清理:游标行会随信号日志的保留期限过期,在观察者会话重置时被移除,并在任一会话被删除时一并删除。v1 中没有取消观察命令。 从会话目录接管的受观察会话会按固定周期检查上游人类的直接活动。检测到的活动会与其他人类直接轮次一样进入同一信号日志和观察者流程。 如果已接管会话的上游来源被外部删除,连续三次检查发现缺失(约三个监控周期)后,会为其观察者生成一个 upstream_missing 信号,并移除上游链接。再次继续运行该目录会话会创建一个新链接。

通知:一次,而非多次

当可触发通知的事件写入,而观察者的游标落后时,观察者会在下一个轮次收到一条系统通知:
主会话观察者还会通过 Heartbeat 唤醒立即得到唤醒;嵌套子智能体观察者则会在下一个轮次收到通知。 该协议刻意采用防骚扰设计:
  • 每个观察者/目标组合最多保留一条待处理通知。 通知处于待处理状态时,其文本在字节层面保持不变,系统事件队列会据此进行去重,因此同一目标即使快速发生二十次变更,观察者的提示词中仍只会出现一行通知。
  • 冻结水位。 通知排入队列时,游标会冻结其通知位置。之后的实质性事件只会推进实质水位,不会再次发出通知。
  • 在取出时确认,仅在工作交错时重新开启。 当观察者的轮次消费该通知时,游标会向前推进。如果从通知入队到被取出之间又发生了更多实质性事件,则只会针对剩余事件重新开启一条新通知。
  • 自我抑制。 观察者绝不会收到由其自身引发事件的通知。
  • 重启恢复。 待处理通知位于内存队列中;Gateway 网关重启后,启动扫描会根据持久游标重新生成这些通知。

协调

通知会明确告诉观察者应执行的操作。带有 changesSince: <version>session_status 会返回该版本之后的带类型事件(最多 200 个),且不会推进任何游标:
historyGap: true 表示请求的版本早于保留的历史——此时应刷新整个会话状态(sessions_historysession_status),而不是将响应视为精确增量。该缺口信号是精确的:它来自每个会话的已修剪水位,而非根据序列号运算推断得出。

存储和限制

历史记录存储在共享状态数据库中,最多保留 30 天和 50,000 行;修剪后,每个会话的头记录仍保持单调递增。记录采用尽力而为模式——追加失败会写入日志,但绝不会导致原始轮次失败——因此 stateVersion 是信号日志头,而不是事务性变更数据捕获版本。 当前限制:
  • 通知传递假定只有一个 Gateway 网关进程拥有共享状态数据库。多个 Gateway 网关会共享持久日志和 changesSince,但 v1 不会跨进程推送通知。
  • 压缩事件涵盖嵌入式运行时的压缩所有者;仅由原生 harness 执行的压缩尚未被完整记录。
  • 取消结果的载荷详情目前由 ACP 子任务运行生成;原生子智能体取消会显示为一般失败。
  • 上游自回显检测会比较规范化后的用户文本。如果外部提示词与会话最近 10 条 OpenClaw 侧用户消息之一相同,则会被视为自回显。
  • 单条本地 Claude JSONL 记录如果大于每周期 1 MiB 的扫描上限,就会在 v1 中阻塞该会话的游标;绝不会跳过未分类的字节。
  • 已配对节点的 Claude 检查会在每个周期对最新 50 个转录项进行分类。更大的突发数据可能超出 v1 的扫描窗口。
  • 已配对节点的 Claude 历史读取不会提供明确的线程不存在结果,因此远程 Claude 删除在 v1 中不会被分类为 upstream_missing
  • 尚未被接管的目录会话在 v1 中仍不属于感知层。
  • 在此功能推出前接管的会话不包含上游链接;从目录中继续运行一次这些会话,即可开始上游监控。
  • 上游链接假定每个已接管的会话键只映射到一个所属智能体(接管操作使用默认存储智能体)。v1 不会监控多个智能体接管同一外部线程的情况。

相关内容