Bus and ask

One-way messages between sessions, and the blocking question a worker raises when the decision is not its own.

What it is#

Two ways for sessions to talk, and they are not interchangeable.

The bus is one-way. msg_send needs a body, an identity (from_session / from_agent) and a target. Pick the target that matches what you know:

Target argument Reaches
to_session and/or to_agent That exact seat
to_worker A worker id — stable across reap and respawn, unlike a session id
to_role parent (the Chair), child or sibling, within the same project
to_project A registered project id: that project's running Chair

Bodies are telegraphic; kind is typically note, handoff or alert. The rest of the bus is msg_inbox, msg_ack, msg_stale (alerts nobody picked up), msg_peers and msg_roster. Humans have the same verbs under orch msg.

An ask blocks. When a decision is not yours to make and you cannot go on without it, you raise one instead of guessing:

ask { question, options?, context?, timeout_sec?, to_session?, to_project? }

It holds until someone answers or the timeout expires — timeout_sec defaults to 600. When options[] is given, those strings are the only accepted answers, case-insensitive; anything else is refused rather than recorded. The first answer wins and a second gets a clear refusal.

Raising an ask also drops an alert in the Chair's inbox naming the id and goes through the configured notify fan-out. The Chair may notice it in msg_inbox, but it answers with ask_answer — or a human does, from a terminal:

orch ask list
orch ask answer <id> --answer "…"

An answer to a cross-project "how did you solve X" can carry a symbol_ref{project, path, line, symbol} — instead of a pasted body. orch validates it against the index before accepting: the symbol must resolve under that project and be shared scope. The asker then fetches the text with code_snippet.

Why it exists#

Because "the agent went quiet" and "the agent decided for itself" are both failures, and a one-way message cannot tell them apart. An ask makes the waiting explicit and, more importantly, makes the timeout explicit: silence is not a state orch will leave you in.

worker ---- ask -----> Chair            worker blocks
worker <-- answer ---- Chair            first answer wins
worker <-- timeout ---  (nobody)        row marked "timeout", error names the question

A timed-out ask is recorded, not swallowed: the row's status becomes timeout, the tool returns an error naming the question, and a Chair answering late is told it arrived too late. The worker then decides for itself — and says so in verify_report.

How it relates to the rest#

  • Only the Chair may spawn. A worker that needs more hands messages the Chair with to_role=parent; it does not fan out. See Chair and workers.
  • Agents coordinate only through this bus. Vendor sockets and side chats are out of bounds — a parallel bus is invisible to the board, the roster and the reaper.
  • A handoff message carrying the one-line verdict is part of how a closed session reports back, alongside the board and the session page.

Nothing to run here#

The verbs exist under orch msg and orch ask for a human at a terminal, but the normal path is an agent calling the MCP tool. You will mostly meet the bus as an orch ask list when a worker is waiting on you.