Bus and ask
One-way messages between sessions, and the blocking question a worker raises when the decision is not its own.
In plain words#
Two desks, same office. A note is a sticky you leave on the other desk (“label format changed — please recheck”). An ask is raising your hand and waiting (“which field is canonical?”) so nobody invents an answer in silence.
You talk to your Chair in normal language. The Chair delivers the note or the raised hand. You do not need the tool names below for day-to-day use — they are here for operators who want the exact verbs.
Seats on different CLIs and different models share one bus: a seat addresses a
peer by name, not by vendor. Bodies travel in context-mode, so a message costs
one line plus an id in the reader's window. What each seat spent is in
/app/board.
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; chair is accepted and means the same), child or sibling. Siblings and children of the same Chair match across projects of the workspace. With no Chair seat on the roster, chair/parent still delivers, addressed to the role — the Chair's own msg_inbox {} reads its seat and the role. |
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.
Every message names its author: <display name> (<agent id>/<preset or CLI>) via orch <session id>. msg_inbox carries it as a rendered From field next to the raw FromSession/FromAgent — the same convention covers ask/ask_answer, lock rows and task_list, so a human reading any of them always knows which seat did what and through which CLI.
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 a hint, not a gate: a 1-based index or a case-insensitive match picks one, and anything else is recorded verbatim as the answer. A numeric answer that happens to equal an option's index maps to that option; prefix it with = (e.g. =2) to force the literal text through instead. 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. Orchemax 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 Orchemax 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
handoffmessage 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.