# agent-watcher Push-delivery layer for [`agent-ping`](https://git.botbought.ai/foreman/agent-ping). The "secondary nervous system" for Claude Code agents on this network. `agent-ping` queues messages in inbox files; `agent-watcher` notices them (and other external events) and wakes the recipient agent without a human in the loop. Two layers: - **Collector** (this repo, Go) — small daemon under `systemd --user`. Always on, brain-blind. Converts external events (HTTP webhooks, drop-folder file arrivals) into ping inbox writes. Runs whether or not any agent is alive. - **MCP Watcher** (Python, in progress) — Claude Code MCP subprocess declared in each agent's `mcp.json`. Watches the agent's inbox via inotify and surfaces events into the live session via Channels. Provides reply tools (`ack`, `respond`, `mark_handled`). Filesystem is the queue. OpenBrain is not involved. ## Spec [`spec/agent-watcher.md`](spec/agent-watcher.md). Read that for architecture, decisions, scope. Channels reference docs (snapshot of Anthropic's official docs, used by Layer 2): [`docs/channels/`](docs/channels/). ## Status | Layer | Lane | Status | |---|---|---| | Spec v1 | — | Signed off by Bob 2026-05-06 | | Layer 1: Collector | Foreman / Go | **v0 working: 43 tests passing.** End-to-end exercised; binary builds. systemd unit + INSTALL.md ready. | | Layer 2: MCP Watcher | Bob / Python | In progress — sandbox CC session being set up on VPS for testing. | ## Install (Layer 1) ```sh git clone https://git.botbought.ai/foreman/agent-watcher ~/agent-watcher cd ~/agent-watcher ./install.sh ``` Then edit `~/.config/agent-watcher/collector.yaml` and `systemctl --user restart agent-watcher`. See [`INSTALL.md`](INSTALL.md) for verify steps, troubleshooting, and the `loginctl enable-linger` step required to keep the daemon running across logouts. Per CLAUDE.md rule #2, **Angus runs the install commands** — agents do not modify their own configuration. ## Quick reference (Layer 1) ``` Inputs Output ───────── ────── HTTP POST → port 18790 ┐ (routed via │ .inbox (JSONL, ping-shaped) YAML table) │ identical format to ├─→ what `ping ` writes; File drop in │ the existing UserPromptSubmit hook and the ~/Nyx/workspace/incoming/ │ future MCP Watcher consume the stream *.json ┘ without distinguishing source. ``` `/health` on the same webhook port returns `{received, emitted, errors, uptime_sec}` for journalctl correlation.