Bus y ask
Mensajes de una vía entre sesiones, y la pregunta bloqueante que levanta un worker cuando la decisión no es suya.
En palabras simples#
Dos escritorios, misma oficina. Una nota es un post-it en el otro escritorio (“cambió el formato de la etiqueta — vuelve a revisar”). Un ask es levantar la mano y esperar (“¿cuál campo es el canónico?”) para que nadie invente la respuesta en silencio.
Le hablas a tu Chair en lenguaje normal. El Chair entrega la nota o la mano alzada. Para el día a día no necesitas los nombres de herramientas de abajo — están para quien opera y quiere los verbos exactos.
Los asientos corren en CLIs y modelos distintos y comparten un solo bus: un
asiento le escribe a otro por nombre, no por proveedor. Los cuerpos viajan en
modo contexto, así que un mensaje cuesta una línea y un id en la ventana de
quien lo lee. Lo que gastó cada asiento está en /app/board.
Qué es#
Dos formas de que las sesiones se hablen, y no son intercambiables.
El bus es de una vía. msg_send necesita un cuerpo, una identidad (from_session / from_agent) y un destino. Elige el destino según lo que sepas:
| Argumento de destino | Alcanza a |
|---|---|
to_session y/o to_agent |
Ese asiento exacto |
to_worker |
Un id de worker: estable entre recogidas y relanzamientos, a diferencia del id de sesión |
to_role |
parent (el Chair; chair se acepta y significa lo mismo), child o sibling. Los siblings y children de un mismo Chair se encuentran entre proyectos del workspace. Si no hay asiento de Chair en el roster, chair/parent igual entrega, dirigido al rol — el msg_inbox {} del Chair lee su asiento y el rol. |
to_project |
Un id de proyecto registrado: el Chair en curso de ese proyecto |
Los cuerpos son telegráficos; kind suele ser note, handoff o alert. El resto del bus son msg_inbox, msg_ack, msg_stale (alertas que nadie levantó), msg_peers y msg_roster. Los humanos tienen los mismos verbos bajo orch msg.
Todo mensaje nombra a su autor: <nombre visible> (<id de agente>/<preset o CLI>) via orch <id de sesión>. msg_inbox lo lleva como un campo From ya renderizado junto al FromSession/FromAgent crudo — la misma convención cubre ask/ask_answer, las filas de lock y task_list, así que quien lea cualquiera de ellos sabe siempre qué asiento hizo qué y por cuál CLI.
Un ask bloquea. Cuando la decisión no es tuya y no puedes seguir sin ella, levantas uno en vez de adivinar:
ask { question, options?, context?, timeout_sec?, to_session?, to_project? }
Se sostiene hasta que alguien responda o venza el tiempo — timeout_sec es 600 por defecto. Cuando se dan options[], esas cadenas son una pista, no un filtro: un índice base 1 o una coincidencia sin distinguir mayúsculas elige una, y cualquier otro texto se registra tal cual como respuesta. Una respuesta numérica que coincide con el índice de una opción se mapea a esa opción; antepón = (por ejemplo =2) para forzar el texto literal. La primera respuesta gana y una segunda recibe un rechazo claro.
Levantar un ask también deja un alert en la bandeja del Chair nombrando el id y pasa por el fan-out de notificaciones configurado. El Chair puede notarlo en msg_inbox, pero responde con ask_answer — o lo hace un humano, desde una terminal:
orch ask list
orch ask answer <id> --answer "…"
La respuesta a un "¿cómo resolviste X?" entre proyectos puede llevar un symbol_ref — {project, path, line, symbol} — en lugar de un cuerpo pegado. Orchemax lo valida contra el índice antes de aceptarlo: el símbolo tiene que resolver bajo ese proyecto y ser de alcance shared. Quien preguntó obtiene el texto con code_snippet.
Por qué existe#
Porque "el agente se quedó callado" y "el agente decidió por su cuenta" son ambos fallas, y un mensaje de una vía no las distingue. Un ask vuelve explícita la espera y, más importante, vuelve explícito el timeout: el silencio no es un estado en el que Orchemax te vaya a dejar.
worker ---- ask -----> Chair el worker bloquea
worker <- respuesta -- Chair la primera respuesta gana
worker <-- timeout --- (nadie) fila marcada "timeout", el error nombra la pregunta
Un ask vencido queda registrado, no tragado: el estado de la fila pasa a timeout, la herramienta devuelve un error que nombra la pregunta, y a un Chair que responde tarde se le avisa que llegó tarde. El worker decide entonces por su cuenta — y lo dice en verify_report.
Cómo se relaciona con el resto#
- Solo el Chair puede lanzar. Un worker que necesita más manos le escribe al Chair con
to_role=parent; no hace fan-out. Ver Chair y workers. - Los agentes se coordinan únicamente por este bus. Sockets de proveedor y chats paralelos quedan fuera: un bus paralelo es invisible para el board, el roster y el recolector.
- Un mensaje
handoffcon el veredicto de una línea es parte de cómo reporta una sesión cerrada, junto con el board y la página de sesión.
Aquí no hay nada que ejecutar#
Los verbos existen bajo orch msg y orch ask para un humano en una terminal, pero el camino normal es un agente llamando a la herramienta MCP. Lo más probable es que te encuentres con el bus como un orch ask list cuando un worker te está esperando.