Herdr事件订阅:构建实时代理状态监控面板
【免费下载链接】herdrthe runtime your coding agents live on项目地址: https://gitcode.com/GitHub_Trending/her/herdr
Herdr 事件订阅(events.subscribe)是构建实时代理状态监控面板的关键能力:它把每个编码代理(Coding Agent)的状态变化——工作中、被阻塞、已完成——以事件推送的方式实时送达你的脚本或工具,让你无需反复轮询,就能一眼看清所有 Agent 的当前状态。
Herdr 是一个"编码代理的运行时":它作为后台服务常驻运行,Claude Code、Codex、Cursor 等 Agent 的终端进程都活在它里面。正因为如此,Herdr 能"看见"每个面板(pane)里 Agent 的每一次状态迁移,并把它们变成可订阅的事件流。
为什么选事件推送,而不是轮询
想象你同时跑着 5 个 Agent,想做一个面板显示"谁在工作、谁卡住了"。
| 方式 | 轮询agent.list | 订阅pane.agent_status_changed |
|---|---|---|
| 状态变化感知 | 最快要等一个轮询周期 | 事件即时推送 |
| CPU / 开销 | 每 N 秒全量请求一次 | 一条长连接,安静时零流量 |
| 错过状态瞬间 | 会(如一闪而过的 blocked) | 不会,事件带有序号 |
| 实现复杂度 | 低 | 低(一行 JSON 发起订阅) |
轮询是"你问我答",事件订阅是"有变化我就喊你"。对于监控面板这种场景,推送模式几乎是唯一正确答案。
Herdr 事件订阅的工作原理
理解它只需三个概念:
- 后台服务器:Herdr 是常驻后台服务,
ctrl+b q断开客户端后进程照常运行。事件由服务器统一产生,因此你断开重连、甚至换台机器 SSH 过来,监控面板依然有效。 - 事件中心(Event Hub):所有事件按发生顺序编号(sequence)。订阅从"被服务器接受的那一刻"开始接收,不重放更早的历史——配合
session.snapshot引导快照可以做到"零丢失",后文细说。 - 两个入口:
events.subscribe:长连接流式订阅,适合监控面板;events.wait:一次性等待,"等到某个状态出现就返回",适合脚本协调。
完整协议由 src/api/schema/events.rs 定义,订阅的过滤与去重逻辑在 src/api/subscriptions.rs。
你可以订阅哪些事件(速查表)
Herdr 的事件覆盖了整个"工作区 → 标签页 → 面板 → 代理"的层级结构:
| 类别 | 事件 | 能监控到什么 |
|---|---|---|
| 🔔 代理状态 | pane.agent_detected | 面板里识别出了哪个 Agent |
| ⚡ 代理状态 | pane.agent_status_changed | 状态迁移:working / blocked / idle / done / unknown |
| 📄 面板 | pane.created/closed/updated/focused/moved/exited | 面板生命周期与焦点 |
| 📃 标签页 | tab.created/closed/renamed/focused/moved | 视图切换 |
| 🗂 工作区 | workspace.created/updated/renamed/moved/reordered/closed/focused | 项目级容器变化 |
| 🌿 Worktree | worktree.created/opened/removed | Git 分支检出生命周期 |
| 🖨 输出 | pane.output_matched | 面板输出命中子串/正则 |
| 📜 滚动 | pane.scroll_changed | 面板滚动位置变化 |
| 🧱 布局 | layout.updated | 分屏布局快照更新 |
其中对监控面板最核心的是pane.agent_status_changed,它的载荷长这样:
{ "event": "pane.agent_status_changed", "data": { "pane_id": "w1:p1", "workspace_id": "w1", "agent_status": "blocked", "agent": "claude", "title": "Refactor auth middleware" } }agent_status只有五个语义值(见 concepts.mdx):working(正在跑)、blocked(需要你做决定)、done(完成待查看)、idle(已结束且已看过)、unknown(无法判定)。监控面板要盯的,基本就是前三个。
快速上手:三步订阅代理状态变化
第 1 步,先看看本机 Herdr 的完整协议(不写死字段,升级不踩坑):
herdr api schema --json第 2 步,向本地 socket 发一条订阅请求(每行一个 JSON,Unix 上是 Unix domain socket):
{"id":"sub_1","method":"events.subscribe","params":{"subscriptions":[{"type":"pane.agent_status_changed","pane_id":"w1:p1","agent_status":"blocked"}]}}第 3 步,第一条响应是"订阅确认(ack)",之后的每一行就是一条推送事件。
两个贴心的细节:
agent_status是过滤器:只想被"卡住"这件事吵醒,就填"blocked",其他状态变化不会推给你;- 如果订阅时该面板已经处于目标状态,会立刻收到一条初始事件,面板启动前就阻塞住的 Agent 不会漏掉。
上图就是 Herdr 自带的最小监控面板:侧边栏实时汇总每个 Agent 的状态(pi 显示 idle、claude 显示 working),状态还会逐层向上卷起——一个 Agent 卡住,它所在的面板、标签页、工作区都会标红提醒。你只需复制这套"状态 + 事件"的组合。
从零搭建不丢事件的监控面板
生产级面板的黄金套路是"先订阅,后快照":
- 开一条连接执行
events.subscribe,等 ack; - 缓冲这条连接开始推来的事件;
- 调用
session.snapshot(CLI 里就是herdr api snapshot)拿到一次完整的引导快照:所有工作区、标签页、面板、Agent 记录; - 用快照初始化面板,再按序回放缓冲的事件,继续监听。
这样从"订阅"到"快照"之间的任何状态变化都不会丢。重连或缓存可能过期时,重新做一次快照即可。协议细节见官方文档 socket-api.mdx。
如果你的面板还需要"等某个 Agent 卡住时触发提醒",不必自己写循环,Herdr 内置了服务器侧的等待:
herdr agent wait w1:p1 --until blockedagent.wait由服务器事件驱动,还会锁定具体是哪个终端进程,Agent 被替换后不会误判。状态语义与检测机制可参考 agents.mdx。
进阶:输出匹配、滚动监听与通知
监控面板做到这里已经能用了,还有几个事件让它更聪明:
pane.output_matched:订阅时给出pane_id+ 匹配规则(子串或正则),面板输出一旦出现命中行就推送该行及上下文。用它实现"测试失败立即弹提醒"非常顺手。pane.scroll_changed:推送offset_from_bottom等滚动指标,0表示停留在底部,可用来判断 Agent 是否还在实时刷屏。notification.show:面板发现异常后,通过一条请求就能让所有已连接的客户端弹出提示(可配声音),把"监控"升级为"告警"。
此外,Herdr 插件的[[events]]钩子可以监听同一套事件名(如pane.agent_status_changed、worktree.created),不用写任何 socket 客户端,用脚本就能挂自动化动作。
小结
- 事件订阅是"推送",轮询是"拉取"——监控面板永远选推送;
- 核心事件是
pane.agent_status_changed,五个状态值 + 状态过滤 + 初始事件回放,把"代理是否卡住"这件事做到零漏报; - "先订阅后快照"模式保证面板从冷启动到稳态不丢事件;
- 输出匹配、滚动监听、系统通知是面板升级告警的三件套。
Agent 们会在你睡觉时继续工作,而 Herdr 事件订阅确保你醒来时——甚至醒来之前——就知道它们做得怎么样。
【免费下载链接】herdrthe runtime your coding agents live on项目地址: https://gitcode.com/GitHub_Trending/her/herdr
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考