$ cat zh/blog/background-agent-finished

后台 Agent 结束了,不一定轮到你

前台回合、后台 worker 和自动化可能写出相似的完成记录,但它们对用户提醒的含义完全不同。

“发现完成事件就弹窗”在单会话演示里很好用,放到真实编程工作流中却会制造噪音。主线程派生的 worker、子 Agent 和自动化都可能结束,但人类并不需要接手。

Claude 记录里可能混入 sidechain

一些 Claude Code 记录会把侧链活动写进主 transcript。解析器要读取 sidechain 标记和会话关系,不能只看外层消息类型。侧链的结束可以更新后台状态,却不应自动变成前台“轮到你”。

Codex 在 session metadata 中标识来源

Codex rollout 的 session_meta 包含 originator 与派生信息。第一行可能很大,读取器必须拿到完整行后再解析;截断元数据会让分类退化,进而把子线程误当成互动线程。

先分类,再聚合

扫描阶段先给每个会话确定来源和交互资格,状态阶段再判断运行或完成,最后才决定全局提醒。把过滤放到通知层太晚,因为错误会话已经参与了全局状态计算。

测试用例就是提醒契约

  • 前台交互回合完成:允许提醒。
  • 前台明确请求权限:允许提醒并说明原因。
  • 子 Agent 完成但主线程仍运行:不提醒。
  • 自动化结束:记录结果,不冒充用户回合。
  • 来源未知或元数据截断:降级为未知,不猜测。

更完整的多会话聚合方式见同时监控多个 Claude Code 和 Codex 会话

来源未知时不要冒险提醒

真实记录可能因为版本变化、部分写入或未知 originator 无法分类。此时最稳妥的结果是保留会话、标记来源未知,并等待更多证据。把未知默认成前台,会把每次并行 fan-out 都变成打断;默认丢弃则可能漏掉真正的互动回合。

聚合层应该保留哪些信息

即使后台会话不触发提醒,也应保留它的运行状态、父会话、工作目录和最新活动时间。这样全局状态栏可以说明“一个前台会话等待你,两个后台任务仍在运行”,而不是用一个图标抹平所有并行工作。