bro

Events β€” notify, mailbox, bus

The events facade β€” a session mailbox by default, a local event broker behind it.

bro comms notify writes through one events facade β€” mailbox by default, or the local broker when "connectors": { "events": "bus" } selects it. The notify connector's postTool probe drains drops into session context, so a watcher, fixer, or convoy worker reaches a live session mid-turn instead of the recipient burning tokens in a wait loop.

The mailbox itself is plain files β€” no broker, no config, no daemon β€” and bro review watch --notify writes there directly (a raw dropMailbox tmp+rename), bypassing the facade: connectors.events routes bro comms notify writes only, never watch drops.

The mailbox β€” bro comms notify

One atomic drop (tmp+rename) per event into <git-common-dir>/bro/notify/ inside a repo β€” shared across linked worktrees via the common git dir β€” or the XDG state dir ($XDG_STATE_HOME, default ~/.local/state) outside one.

CommandWhat it does
bro comms notify <text>Drop one event β€” delivered to every session's next postTool probe
bro comms notify -- <text>Verbatim text β€” needed when it contains option-looking words like --help
bro comms notify --to <agentId|sessionId|orchestrator> <text>Addressed drop for exactly one consumer β€” orchestrator names the session owning agents; absent means broadcast
--kind note|info|ask|result|blockA label, never a grant β€” a block or ask carries no approval or scope with it
--in-reply-to <ref>The drop, bead, or step this answers
--key <k>Coalesce β€” a pending same-key drop from this source is superseded by the newer one

Delivery is pull-based: a drop never wakes a sleeping session β€” it lands in context on the next tool call. Broadcast drops stay for every session until the drop TTL reaps them; addressed drops expire on read (single-consumer). Each drop should be self-contained β€” the drain renders it verbatim.

The broker β€” bro comms bus

A local event broker in @broject/core β€” topics, filters, seq cursors. status deliberately exits 0 when the broker is down: nobody started one is a normal state, not a fault.

CommandWhat it does
bro comms bus serve [--json]Run the broker (SIGINT/SIGTERM to stop)
bro comms bus publish --topic T --kind K [--key K] [--source S] [--to ADDR] [--cause C] [--ref R] [--payload JSON] [--json]Publish one event and exit β€” connect, write, close. --to addresses one recipient (orchestrator works here too); absent means broadcast
bro comms bus subscribe [--topic T]… [--kind K]… [--to ADDR] [--since N] [--json]Stream matching events until interrupted; --since N replays from a seq cursor β€” a cursor outside the window reports a gap
bro comms bus status [--json]Liveness and counters

GitHub webhooks β€” github:*

bro fleet serve ingests GitHub webhook deliveries and publishes them as bus topics: POST /api/v1/webhooks/github maps each verified delivery to github:<event> (github:pull_request, github:check_run, …) with the payload action as kind and pr-<n>/sha-<head> as key. The X-Hub-Signature-256 HMAC is the auth β€” no session token β€” and the route is armed only while BRO_GITHUB_WEBHOOK_SECRET is set; unset it answers 503, a bad signature 401. When the secret IS set, bro fleet serve also starts the repo's broker in-process β€” the two commands below are the whole local-dev receiver:

gh extension install cli/gh-webhook   # once
BRO_GITHUB_WEBHOOK_SECRET=dev bro fleet serve --port 8791
gh webhook forward --repo=org/repo \
  --events=pull_request,pull_request_review,check_run,check_suite,issue_comment \
  --url=http://127.0.0.1:8791/api/v1/webhooks/github --secret=dev

Hosted mode is the same route behind a tunnel or reverse proxy pointed at a repo webhook or GitHub App β€” the signature check survives the public Host a tunnel forwards with.

bro review act wait subscribes to github:* and polls early when a matching event lands β€” a check completing wakes the wait instead of sitting out the interval. Broker down means plain timer polling: the webhook path is an accelerator over the default, never a requirement.

Policy

  • Write, don't wait. A finished worker, a watcher that saw a transition, a fixer that needs attention β€” drop the event and get on with it; never poll the parent.
  • Once per session, not once total. The mailbox is broadcast with a per-session .seen cursor β€” a drop reaches every live session exactly once.
  • bro review watch --notify drops the initial snapshot and gate transitions into the mailbox β€” see Fleet & supervision.

On this page