--- name: orchestrate description: >- The main-actor pattern for bot teammates. Use when YOU are a bot wired to a chat (Telegram, etc.) and a request needs real coding/build work. You stay the ONLY voice in chat and never block — you delegate the heavy work to persistent tmux sub-agents (mav-agent), poll their done-marker, and report results back. Trigger when: a chat request implies a long-running build/code task, when you feel tempted to do heavy work inline and risk freezing the conversation, or when the user asks to "spawn an agent", "run this in the background", or "delegate" something. --- # Orchestrate — one voice talks, hands stay clean You are the **main actor**: the single process that owns the chat. Your job is to read messages, decide, reply, and **delegate** anything heavy. You must never block the conversation on a long build. Coding/builds happen in **sub-agents** that live in their own tmux windows and persist across turns — even if your own session gets compacted or restarted. ## The rule - **You** = the only thing that touches the chat. Fast turns, never blocks. - **Sub-agents** = do the actual coding/building in tmux. They outlive your turn. - Never run a long task inline. Spawn it, then poll the marker, then report. ## Tools Two thin wrappers around a persistent tmux session named `mav`: - `mav-agent` — spawn/observe named claude or codex sub-agents (one tmux window each). - `mav-tmux` — run a one-off shell command in the shared session and capture output. ### mav-agent ``` mav-agent run spawn a claude sub-agent (model: opus) mav-agent run --codex spawn a codex sub-agent mav-agent status running | done (exit N) | none mav-agent wait [timeout_s] block until done (marker-based), prints tail mav-agent result print the agent's full final stdout mav-agent read live snapshot of the agent's pane mav-agent list all agent windows + their status mav-agent kill kill an agent window ``` ### The clean handoff (why this is reliable) Every `run` wraps the agent so that when the CLI exits it writes: - `/tmp/mav-agent/.out` — full stdout/stderr stream - `/tmp/mav-agent/.done` — exit code (written ONLY when finished) `status` / `wait` poll the `.done` marker — **no prompt-sniffing, no guessing**. Marker present ⇒ work is finished. Absent + window alive ⇒ still running. This is the gotcha that breaks naive setups: without a real done-signal the main actor either reports too early or hangs forever. The marker fixes both. ## Playbook (the loop you run every time) 1. **Acknowledge fast.** Reply in chat that you're on it. Don't make the user wait on a silent turn. 2. **Spawn.** `mav-agent run ""`. The sub-agent does NOT share your memory — put everything it needs in the task. 3. **Don't block your turn.** For short work, `mav-agent wait 60`. For long work, end your turn; on the next wake check `mav-agent status `. 4. **On done:** `mav-agent result `, summarize, reply in chat. Check the exit code — non-zero means it failed; read `result` and decide a fix or retry. 5. **Clean up** finished windows with `mav-agent kill ` so `list` stays readable. ## Conventions - **Name agents by job**, not sequence: `auth-fix`, `icon-gen`, `db-migrate`. - **Self-contained tasks.** Sub-agents start cold — no chat history, no your-memory. Spell out the repo path, the goal, and the done-condition in the task string. - **One job per agent.** Parallel jobs ⇒ parallel names; they run concurrently. - **Claude vs codex:** claude (`opus`) for reasoning/multi-file work; `--codex` for fast scoped edits. Both honor the same status/wait/result handoff. - **Long-lived processes** (servers, watchers, `npm run dev`) go in `mav-tmux run`, not an agent — they're meant to keep running, not finish. ## Anti-patterns - ❌ Doing the build inline in your own turn — freezes the chat, dies on compaction. - ❌ Polling `read` and eyeballing for a shell prompt — flaky. Use `status`/`wait`. - ❌ Terse tasks like `"fix the bug"` — the agent has none of your context. Be explicit. - ❌ Leaving dozens of dead windows around — `kill` them after you read the result. ## Quick example ```bash # chat: "regenerate the app icons in /Users/m1/proj at 3 sizes" mav-agent run icon-gen "In /Users/m1/proj, regenerate app icons at 1x/2x/3x \ from assets/icon.svg into assets/icons/. Use the existing gen script if present. \ Print the output paths when done." mav-agent status icon-gen # -> running # ... end turn, or wait ... mav-agent wait icon-gen 120 # -> [done] exit 0 + tail mav-agent result icon-gen # -> full log to summarize back to chat mav-agent kill icon-gen ``` That's the whole pattern: one voice in chat, real work in persistent agents, a file marker for the handoff. Any bot wired to a chat can adopt it by following this loop.