关于 EZO Watcher
EZO Watcher 是面向单个项目的可自托管监控与事件响应系统,适用于编码 Agent 和团队。它会验证监控检查能否识别故障,并提供事件墙、告警及修复后复查流程。
主要功能
- 01配置 HTTP、心跳和主机检查
- 02通过模拟故障验证检查
- 03查看和管理事件
- 04通过通知渠道发送告警
- 05提供事件修复所需上下文
适用场景
- 01发现依赖故障和定时任务漏跑
- 02查看事件及其证据
- 03引导 Agent 验证修复结果
MCP 相关
EZO Watcher 向 MCP 客户端提供事件与监控操作。客户端可通过本地 stdio 桥接程序或无状态 Streamable HTTP 端点读取事件状态并管理事件。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
16收录的工具列表 · 更新于 1 周前
此工具无需参数。
详细介绍
EZO Watcher
面向项目的开源 AI SRE:监控编码 Agent 的安装、验证和修复过程。
Agent 化 LiveOps 监控:可自托管、原生支持 MCP、无需账户,并且每项检查都必须先验证能变红才算数。
在线演示 · 快速入门 · 工作原理 · 修复循环 · Agent 能看到什么 · MCP · 托管 · 文档
npm i -g ezo-watcher
watcher init
无需全局安装:npx -y ezo-watcher init
健康检查路由返回 {"ok": true},只能证明进程正在运行。如果数据库宕机、队列卡住,或昨晚的 cron 任务从未运行,它仍会显示为绿色。
EZO Watcher 是面向单个项目的告警墙和寻呼系统,旨在由已经负责项目代码的 Agent 完成设置。Agent 会读取代码仓库,选出确实能变红的遥测点,为每个点添加其来源文件和行号,并进行验证:watcher doctor --live --prove 会将每个来源自身的读数推过阈值;如果检查状态没有翻转,安装就会失败。只有 {"ok": true, "live": true} 才算完成。
之后发生故障时,同一个 Agent 会读取事件、提交修复,并通过重新检查来关闭事件。何时恢复正常由数据源决定,而不是 Agent。
提示
打开在线演示:包含示例数据的完整监控墙。可确认、静默、停放和重新检查事件;所做更改会保留在浏览器中。
工作原理
flowchart LR
subgraph project["Your project"]
code["Code, cron, configs"]
app["Running app"]
end
agent(["Coding agent"])
cfg[".watcher/config.json<br/>checks as code"]
server["Watcher server<br/>one Node process + SQLite"]
wall["Alert wall"]
phone["Phone<br/>ntfy · push · SMS · email"]
agent -- "watcher scan" --> code
agent -- "watcher add --found-at" --> cfg
cfg --> server
server -- "probes · heartbeats<br/>webhooks · host" --> app
server --> wall
server --> phone
server -- "MCP · CLI · hooks" --> agent
agent -- "fix, then recheck --wait" --> app
- 扫描。
watcher scan会列出代码仓库已暴露的内容:就绪路由、cron 条目、计划工作流、Sentry、Grafana、Netdata 和已发布端口。 - 添加。 Agent 将每个信号转换为一个数据源。每个数据源都包含依赖项宕机时会发生变化的断言,以及
--found-at file:line,使事件能直接指向相关代码。 - 验证。
watcher doctor --live --prove会修改每个读数(返回错误的 JSON、错过心跳、磁盘使用量超出限制),并且只有检查变红才会通过。 - 运行。 一个进程负责提供监控墙、向你的手机发送寻呼通知并提供 MCP 服务。
- 修复。 事件会向 Agent 提供修复说明。Agent 提交修复后,只有数据源读数恢复正常,
recheck --wait才会关闭事件。
将以下内容交给你的 Agent
Set up EZO Watcher for this project. Install the CLI with
`CI=1 npm_config_yes=true npm i -g ezo-watcher`, then run
`watcher init` and `watcher skills install --target all`, and follow the
ezo-watcher skill end to end (read `.claude/skills/ezo-watcher/SKILL.md` or
`.agents/skills/ezo-watcher/SKILL.md` if the skill is not listed in this session yet).
Follow its ranking: a dependency-gated readiness route first (never a route that
just returns {"ok": true}), a heartbeat for every scheduled job, then any Sentry,
Grafana or Netdata already in the project. Add one alert channel and prove it
with `watcher test-alert`.
Do not stop until `watcher doctor --live --prove --json` prints
{"ok": true, "live": true}. If this project has no server and no scheduled job,
add `watcher add host --id host` — the machine itself, read locally with nothing
installed (load, memory, free space, optionally a pid file) — and prove it. Only
if there is no server, no scheduled job and no host to watch either, run
`watcher doctor --no-runtime-surface --json` and tell me instead; a configured
source always wins over `--no-runtime-surface`. Ask me only
for the credential a chosen source or channel needs, and tell me what you watched
and what you skipped.
Claude Code 用户:运行 watcher skills install 后,运行 /reload-skills,以便在当前会话中加载新技能。
或手动操作
# Node 24+.
npm i -g ezo-watcher
watcher --version
cd my-project
watcher init
watcher scan --json
watcher add http-probe --id app --url http://127.0.0.1:3000/readyz \
--expect-json '{"db.ok":true}' --found-at src/server.ts:42 \
--read "readiness reads the database"
watcher add channel ntfy --id ntfy --server https://ntfy.sh --topic-env WATCHER_NTFY_TOPIC
# or, with no credential at all: watcher add channel file --id local
watcher run --detach
watcher doctor --live --prove --json # {"ok": true, "live": true}
watcher test-alert
无需全局安装:npx -y ezo-watcher <verb> 可用相同方式运行任意动词(npx -y ezo-watcher init)。打开 http://127.0.0.1:7717 查看监控面板。watcher init 会写入 .watcher/config.json(提交此文件)、.watcher/.env 和 .watcher/data/(已加入 gitignore),并从 7717 开始选择一个空闲端口。
它会配置什么
| 项目已有内容 | EZO Watcher 会添加 |
|---|---|
| 带有就绪状态路由的服务 | 一个 http-probe,用于断言依赖项宕机时会变化的 JSON 字段,而不只是检查状态码 |
| 定时作业、cron、计时器、工作流或工作进程循环 | 为每个作业配置一个 heartbeat:漏掉一次运行就会触发事件,而不是悄无声息 |
| 数据库、缓存或已发布的端口 | 一个 tcp-probe(如果套接字使用 TLS,还会检查 TLS 到期时间) |
| Sentry、Grafana、Netdata | 使用它们各自的数据源:读取已有内容,而不是重复配置 |
| 入站发送方(Stripe、GitHub、采集器) | 一个带有陈旧时间窗口的 webhook 数据源,因此发送方停止工作时会触发通知 |
| 域名 | 通过 RDAP 检查 domain-expiry,与现有 http-probe 检查的证书到期时间并列 |
| 未安装任何软件的机器 | 一个 host 数据源:本地读取每核负载、可用内存、每个挂载点的可用空间,以及可选的一个 pid 文件 |
| 必须能接到电话提醒的手机 | 一个通知渠道:ntfy、Web 推送、SMS、电子邮件或 webhook,并通过 watcher test-alert 验证。没有凭据?file 渠道会将每条通知记录为 JSONL,且无需凭据 |
修复循环
Watcher 运行后,只需一行提示词:
Check the Watcher for open incidents and fix them; verify each fix with a recheck.
sequenceDiagram
autonumber
participant S as Source
participant W as Watcher
participant P as Phone
participant A as Agent
S->>W: readiness answers {"db": {"ok": false}}
W->>P: page: Checkout api is down
A->>W: watcher status --brief (session start)
A->>W: get_fix_context
W-->>A: failed assertion, last good and bad reading, found-at server.mjs:35
A->>A: fix the code, redeploy
A->>W: verify_fix / recheck --wait
W->>S: re-run the check now
S-->>W: {"db": {"ok": true}}
W-->>A: resolved, confirmed by the source
Agent 会在会话开始时运行 watcher status --brief 获取单行状态,然后运行 get_fix_context(或 watcher incident <key> --fix-context)获取事件专属简报:数据源和目标配置、失败的断言、最近一次正常和异常观测,以及重新运行检查的命令。修复并重新部署后,只有当数据源本身报告恢复正常时,verify_fix(或 watcher recheck <key> --wait)才会关闭事件并记录归因。完整循环为 watcher skills fix。
在每次会话开始时向 Agent 提供简报
watcher hooks install --target claude # SessionStart: watcher status --brief
它会将 SessionStart 钩子写入项目的 .claude/settings.json,这样打开会话时就能通过一行内容获知监控面板的状态,无需提问。--target codex 会改为将相同指令写入 AGENTS.md(watcher hooks uninstall 可将其移除)。
Agent 本身停止工作时触发告警
添加一个 heartbeat(其 ping token 会自动生成到 .watcher/.env),并添加一个在每轮结束后 ping 它的 Stop 钩子:
watcher add heartbeat --id agent-session --every 30m --grace 15m \
--token-env WATCHER_AGENT_SESSION_TOKEN
{
"hooks": {
"Stop": [
{ "hooks": [
{ "type": "command",
"command": "sh -c 'set -a; . .watcher/.env 2>/dev/null; curl -fsS -X POST -H \"Authorization: Bearer $WATCHER_AGENT_SESSION_TOKEN\" http://127.0.0.1:7717/ingest/heartbeat/agent-session >/dev/null 2>&1 || true'" }
] }
]
}
}
宽限期内的任何一轮都会让 heartbeat 保持绿色;当 Agent 停止工作超过该时长时,HeartbeatDown 会触发告警。|| true 可防止已停止的 Watcher 阻塞 Agent 的当前轮次。(Claude Code hooks 参考文档,查阅日期:2026-11-04。)
Agent 可通过 MCP(/mcp)或 CLI 连接 Watcher,并读取纯文本。演示展示了实时效果:确认或暂挂某个事件,下方每条答复都会随之变化。每个事件详情页中的 Agent 所见都展示相同的内容。

每次会话开始时,watcher hooks install 都会运行 watcher status --brief:每个未解决事件占一行,状态墙无告警时则不显示内容。
$ watcher status --brief
warning Billing jobs HeartbeatDown 50m Billing jobs|HeartbeatDown
page Checkout API ProbeDown 21m Checkout API|ProbeDown
warning Worker hosts HostDiskFree 2h Worker hosts|HostDiskFree
run `watcher incident <key> --fix-context` or the MCP tool get_fix_context
首次调用 MCP 时,watch_state 会在一条答复中展示状态墙(节选):
{
"text": "3 firing; 2 unattended, 1 acknowledged, 0 silenced; 1 page, 2 warning, 0 info; 1 parked (not live: an open verdict that is not due yet). Every source is answering.",
"counts": { "firing": 3, "unattended": 2, "acknowledged": 1, "silenced": 0, "parked": 1, "page": 1, "warning": 2, "info": 0 }
}
接着调用 get_fix_context {"key":"Checkout API|ProbeDown"}(或 watcher incident 'Checkout API|ProbeDown' --fix-context --json),即可获取修复所需的全部信息,无需询问他人(此处为节选;实际摘要约 200 行):
{
"key": "Checkout API|ProbeDown",
"summary": "checkout-api is down: HTTP 503 in 3023ms, expected 200",
"state": { "firing": true, "attention": "none", "ackedBy": null, "silencedUntil": null, "parkedState": null, "parkedUntil": null },
// sources[0].target: the config that failed
"target": { "id": "checkout-api", "url": "https://api.acme.example/checkout/readyz", "expectJson": { "ok": true, "db.ok": true }, "slowMs": 800 },
"asserts": [{ "asserts": ["status 200", "body.ok = true", "body.db.ok = true"], "failed": ["status 200"],
"failureDetail": "HTTP 503 in 3023ms, expected 200 (25 failed polls in a row)" }],
"observations": {
"lastGood": { "at": "2026-11-05T15:06:00.000Z", "status": 200, "body": "{\"ok\":true,\"db\":{\"ok\":true,\"poolInUse\":8}}" },
"lastBad": { "at": "2026-11-05T15:30:00.000Z", "status": 503, "detail": "HTTP 503 in 3023ms, expected 200" }
},
"reproduce": {
"command": "curl -sS -m 10 'https://api.acme.example/checkout/readyz' | jq '.ok'", "expect": "true",
"watcher": "watcher recheck 'Checkout API|ProbeDown' --wait --json"
},
"next": [{ "action": "fix" }, { "action": "restart-or-deploy" }, { "action": "verify" }] // each with its detail
}

状态墙
![]() | ![]() |
| 每个事件都会打开详情页:故障内容、证据、历史记录及已发送的所有通知。 | 手机上也能看到相同的状态墙,可安装为支持 Web 推送的 PWA。 |
触发中的事件卡片占据主要空间;运行正常的服务则收缩为密集网格。页面故障显示为红色,警告显示为琥珀色,已确认的事件会显示处理人,暂挂的事件则使用专属颜色,并会自动到期。整体设计遵循 ISA-101 高性能 HMI 实践:默认使用灰色,仅对需要关注的内容使用颜色(docs/design.md)。
MCP
有两种形式,优先使用 stdio:
watcher mcp-config --client claude # also: cursor, codex; --show-secret prints the token
stdio 形式会注册正在运行的 CLI 本身(node <the install's bin/watcher.mjs> mcp --dir <project>):客户端会在项目中启动一个小型桥接程序,由它从 .watcher/.env 读取 WATCHER_MCP_TOKEN,注册信息中不包含密钥。适用于与 Watcher 位于同一台机器上的 Agent。
HTTP 形式使用运行中服务自身的端点 <baseUrl>/mcp(无状态的 Streamable HTTP),并通过 Authorization: Bearer $WATCHER_MCP_TOKEN 进行保护。可在 Tunnel 后使用,让同一个 Agent 能从 Tunnel 可访问的任何位置工作;如果启用了 Access,请为 /mcp 设置 Cloudflare Access 绕过规则(该端点仍使用自身的 Bearer 令牌;参见 watcher skills cloudflare)。
| 读取 | 写入(每项均以 agent: <who> 标记) |
|---|---|
watch_state · list_incidents · get_incident · get_fix_context · incident_history · list_sources | acknowledge · unacknowledge · silence · park · unpark · comment · recheck · verify_fix · resolve · confirm_resolution |
所有输入详见 docs/mcp.md。
与众不同之处
- 以断言为准,而非以状态为准。 200 只能证明套接字接受了连接。只有每项检查都带有一个在发生变更时会翻转的谓词(
--prove),安装才算通过;这样,数据库故障、队列停滞或作业失效都能真正触发告警。 - 先关注静默故障。 在对 4 个手动标注的代码仓库进行原型扫描时,文件扫描找到了大部分 HTTP 接口,但只发现了约五分之一的静默故障:在安装脚本中生成的计划任务、运行时创建的 launchd/systemd 单元、拉取队列工作器、产品自身配置中声明的陈旧时间、状态目录的可写性、作为代码常量保存的依赖 URL。该技能内置了这份检查清单,其中每项都会变成心跳或带有过期时间窗口的 Webhook。
- 本地运行,无需账户。 一个 Node 进程、
node:sqlite、保存在 git 中的配置,以及权限为 0600 的 env 文件。无需注册任何服务;它可在笔记本电脑、服务器上运行,也可通过 Cloudflare Tunnel 对外提供服务。 - 原生支持 Agent。 文档随 CLI 一同提供(
watcher skills <topic>),安装流程专为 Agent 编写,运行中的 Watcher 通过 MCP 提供服务,因此 Agent 可以读取状态墙、确认告警、发表评论、暂时静默、搁置并重新检查。
托管
flowchart LR
local["Local process"] --> svc["launchd / systemd<br/>service"] --> vps["Docker or a VPS"] --> tunnel["Cloudflare Tunnel<br/>$0, no port forwarding"] --> containers["Cloudflare Containers<br/>beta"]
优先选择最便宜的方案。Cloudflare Tunnel 是“用我的 Cloudflare 密钥托管”的默认选项:使用你已有区域中的主机名,无需端口转发。watcher cloudflare tunnel --hostname watch.example.com 会配置隧道、DNS 和运行令牌;watcher cloudflare quick 则会为演示提供一个临时的公网 URL。Cloudflare Containers 持续运行时约需 9.57 美元/月,且无法探测你的局域网;Workers 边缘端口尚未构建。详情请查看:watcher skills hosting 和 watcher skills cloudflare。
绑定到 loopback 以外的地址时,必须设置 WATCHER_ADMIN_TOKEN;否则服务器会拒绝启动。
文档
skills/ezo-watcher/SKILL.md | 安装流程。CLI 也会输出此内容:watcher skills 会列出主题(install、discover、sources、channels、hosting、cloudflare、netdata、operate、fix、telemetry) |
skills/ezo-watcher/references/ | 这些主题输出的详细内容 |
docs/mcp.md | 将 Agent 连接到正在运行的状态墙 |
docs/doctor-codes.md | 每个 watcher doctor 代码及其修复方法 |
docs/embed.md | 在其他页面中嵌入状态墙或单个卡片 |
docs/telemetry.md | 匿名遥测会发送哪些数据,以及如何关闭 |
docs/design.md | 产品与视觉设计决策及其来源 |
AGENTS.md | 如何参与此代码仓库的开发 |
llms.txt | Agent 阅读此代码仓库时使用的索引 |
遥测
CLI 和服务器会发送匿名使用数据(动词和标志名称、退出代码、doctor 检查代码、内部错误类型),以便我们发现故障并优先修复。绝不会发送路径、主机、URL、配置或 env 值。用户只需查看一次通知,之后遥测便会默认开启;可通过 watcher telemetry disable 或 DO_NOT_TRACK=1 将其关闭,设置 WATCHER_TELEMETRY_DEBUG=1 则会准确打印将要发送的内容。发送内容及其去向详见:docs/telemetry.md。
状态
公开预览版,已发布到 npm,包名为 ezo-watcher。支持为他人的项目托管状态墙;不支持多租户托管。
开发
npm ci
npm run build
npm run typecheck
npm test
Node 24+、ESM、TypeScript。代码布局、测试规则和泄漏门禁请参阅 AGENTS.md,产品决策请参阅 docs/design.md。
许可证
MIT © EZO Labs Inc.
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。

