Skip to main content

Broadcasts

A broadcast sends one message to every agent chat an explicit selector resolves to. Bossanova wakes each target chat and delivers the message as a prompt. Use it when a coordinator needs to tell a known audience something now.

A broadcast is not a GitHub PR callback. A callback waits for one pull request to reach a state and notifies one chat; a broadcast tells an audience something immediately.

The local audience is fixed when you send

Bossanova resolves a local selector once, at send time, then stores the resulting deliveries. A local chat created after the send is never added retroactively. This keeps a broad message from silently expanding as new sessions start.

This guarantee applies only to the current daemon. With --cross-daemon, each receiving daemon resolves the selector when it receives the routed broadcast, so a chat created after the origin send can be a remote target.

An empty result is valid: no routable chat happened to match. An empty selector is different: it is an error, never a request to notify everyone.

Select an audience deliberately

A selector can name six dimensions: chat, session, repo, agent, account, and daemon. Selectors carry identifiers, not credentials, so the selector is safe to log; the message body is not.

  • Commas join terms in one clause. Different dimensions are ANDed: repo:repo_123,agent:claude selects Claude chats for one repository.
  • Repeating one dimension with commas is OR within that dimension: agent:claude,agent:codex selects either agent.
  • A plus sign ORs complete clauses: repo:repo_123,agent:claude+account:acct_456 selects either clause.

Start with the narrowest selector you can. Every matched chat is woken, so a broad selector has a real cost. The sending chat is excluded by default to avoid self-wake loops; use --include-origin only when it should receive the message too. One daemon refuses, rather than truncates, an audience over its target cap.

Keep the body secret

The body is delivered and stored verbatim, but no list or inspect surface echoes it back. Treat it like a prompt containing operational context: do not put it in logs or status updates. The receiver must also treat a broadcast as a signal, not proof. If it says a PR merged or a deployment completed, verify that external state before acting.

Send a broadcast

boss broadcast send requires both a selector and a message:

# Tell every Claude chat in one repository.
boss broadcast send --to repo:repo_123,agent:claude \
--message "The migration is complete; rebase before your next change."

# Read a sensitive body from standard input instead of shell history.
printf '%s' 'Investigate the failed integration check.' | \
boss broadcast send --to session:session_123 --message -

# Include the sending chat when this is intentionally a self-notification.
boss broadcast send --to chat:agent_123 --include-origin \
--message "Continue after the scheduled window."

Use --from to record the originating chat and --expires-in to bound retry time. Delivery retries for 24 hours by default; the maximum is 30 days. boss broadcast list (ls) can filter by --chat, --origin, or --state; boss broadcast remove (rm) permanently removes a broadcast and its deliveries.

Reach other daemons only when needed

Broadcasts start local to the current daemon. --cross-daemon asks Boss Cloud to fan out to other live daemons, each of which resolves the selector against its own chats:

boss broadcast send --cross-daemon --to repo:repo_123,agent:codex \
--message "A release branch is ready for review."

Cross-daemon delivery is off by default and best effort. An offline daemon has no store-and-forward queue, and fan-out to more than 32 other daemons is refused rather than truncated. Do not try to target another daemon with a daemon:<id> selector term: chat rows have no daemon id in that dimension, so such a term resolves to zero chats on every daemon.

Subscribe to a session outcome

A subscription is a standing rule that sends one broadcast when a session settles. Its --on value is completed, errored, or settled (either outcome):

# Tell a coordinator whether a child session reached any terminal outcome.
boss broadcast subscribe --session session_123 --on settled \
--to chat:agent_456 --message "Child session settled; inspect its PR."

Unlike an ordinary broadcast, a subscription resolves its audience at fire time, not when registered. It resolves and delivers only on its owning daemon: cross-daemon fan-out is available only to an explicit broadcast send with --cross-daemon. It is one-shot: after it fires, is canceled, or expires, it no longer stands. --expires-in bounds how long the rule stands (24 hours by default, 30 days maximum), not the retry window of its fired broadcast. boss broadcast subscriptions lists rules; unsubscribe retires one rather than erasing it, so a cancelled subscription still appears in an unfiltered list and can be selected by its historical state.

MCP tools

Agents can use the same capability through MCP:

ToolPurpose
send_broadcastSend a message to a selector now.
list_broadcastsList broadcasts without exposing bodies.
delete_broadcastRemove a broadcast and its deliveries.
register_broadcast_subscriptionRegister a one-shot outcome rule.
list_broadcast_subscriptionsList standing or terminal rules.
delete_broadcast_subscriptionCancel a subscription.

Pass explicit IDs from the relevant list or context tool. For a broader agent tool overview, see the MCP guide.