One bot owns the chat and delegates coding to persistent tmux sub-agents, using a .done file marker for a reliable handoff (status/wait/result). Includes README + install.sh for one-command setup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
107 lines
5.0 KiB
Markdown
107 lines
5.0 KiB
Markdown
---
|
|
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 <name> <task> spawn a claude sub-agent (model: opus)
|
|
mav-agent run <name> --codex <task> spawn a codex sub-agent
|
|
mav-agent status <name> running | done (exit N) | none
|
|
mav-agent wait <name> [timeout_s] block until done (marker-based), prints tail
|
|
mav-agent result <name> print the agent's full final stdout
|
|
mav-agent read <name> live snapshot of the agent's pane
|
|
mav-agent list all agent windows + their status
|
|
mav-agent kill <name> 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/<name>.out` — full stdout/stderr stream
|
|
- `/tmp/mav-agent/<name>.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 <name> "<self-contained task with full context>"`.
|
|
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 <name> 60`. For long
|
|
work, end your turn; on the next wake check `mav-agent status <name>`.
|
|
4. **On done:** `mav-agent result <name>`, 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 <name>` 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.
|