一键导入
dispatch
Execute a plan with parallel agents. You become the dispatcher: spawn impl/review agents, coordinate work, and track progress with a live UI fragment.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Execute a plan with parallel agents. You become the dispatcher: spawn impl/review agents, coordinate work, and track progress with a live UI fragment.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | dispatch |
| description | Execute a plan with parallel agents. You become the dispatcher: spawn impl/review agents, coordinate work, and track progress with a live UI fragment. |
You (the primary agent) become the dispatcher. Use elisp evaluation to call agent-shell-dispatch functions for spawning agents, sending messages, and checking status. The dispatch renderer runs as agent-shell-dispatch-render-mode — a minor mode that shows " Dispatch" in the mode line and can be toggled by the user.
Throughout this skill you need to evaluate elisp in the running Emacs instance. Use whichever method is available, in order of preference:
emacs_eval_elisp tool (exact name depends on MCP server configuration)describe that evaluates elispemacsclient --eval '(elisp-form)' via BashCode blocks below show the elisp to evaluate. Wrap them with whichever method you have.
There is no hard cap on agent count — parallelism is bounded by coordination overhead and the filesystem isolation story (see "Parallelism and isolation" below), not by an arbitrary number.
mcp__emacs__emacs_eval_elisp tool to evaluate elisp").per-task, batch, or noneFirst, register your buffer as the dispatcher so permission requests render here:
(setq agent-shell-dispatch--primary-buffer
(agent-shell-dispatch-current-agent-buffer-name))
Then spawn agents. They run in the background (no popup, no prompts, acceptEdits mode). Non-edit permissions (bash, etc.) render as button dialogs in YOUR buffer — the user handles them directly. You do NOT handle permissions.
Use short names (e.g. "Impl-1", "Rev-1") — these appear in the agent activity column in the header, so brevity matters.
(agent-shell-dispatch-spawn-agent
default-directory
"Impl-1"
"You are Impl-1. Wait for your task assignment.")
agent-shell-dispatch-spawn-agent returns the FULL buffer name of the spawned agent (e.g. "[agent:Impl-1] Agent @ project"). Capture and use this string — do not rely on (agent-shell-dispatch-agent-buffer "Impl-1") to resolve it later. The short-name resolver has been unreliable in practice (returns nil). If you respawn an agent with the same short name after killing a prior instance, Emacs adds a <N> disambiguation suffix (e.g. <2>); always use the exact string returned by spawn-agent.
Repeat for each agent. If you need filesystem isolation (parallel impl agents writing to the same repo), see "Parallelism and isolation" below — spawn each agent in its own git worktree directory.
CRITICAL ORDER: start the task graph FIRST, then send tasks and report statuses. If you call agent-shell-dispatch-report before agent-shell-dispatch-start, the report is wiped when start re-initializes state and the graph will render as "not started" indefinitely.
This enables agent-shell-dispatch-render-mode in the dispatcher buffer and initializes the statuses hash. Pass a list of task plists using the exact agent buffer names returned by spawn-agent:
(agent-shell-dispatch-start-current
'((:id "impl-1" :name "Task 1 description" :agent "[agent:Impl-1] Agent @ project")
(:id "impl-2" :name "Task 2 description" :agent "[agent:Impl-2] Agent @ project")))
Read SUBAGENT_TEMPLATE.md (in the same directory as this skill) and customize it per task — replace TASK_NAME, TASK_ID, TASK_DESCRIPTION, CRITERIA, and DISPATCHER_PRIMARY_BUFFER_NAME with the actual values.
IMPORTANT: agent-shell-dispatch--primary-buffer is buffer-local to the dispatcher. Subagents evaluating elisp see it as nil, which makes their message-send calls fail with "stringp nil". You MUST substitute the literal string value of (agent-shell-dispatch-current-agent-buffer-name) (your dispatcher buffer name) into the template everywhere the subagent needs to reference the dispatcher. SUBAGENT_TEMPLATE.md uses "DISPATCHER_PRIMARY_BUFFER_NAME" as the placeholder — replace it with e.g. "Codex Agent @ project".
(agent-shell-dispatch-send-to-agent
"[agent:Impl-1] Agent @ project" ; full buffer name from spawn-agent
"CUSTOMIZED-TEMPLATE-CONTENT"
"dispatcher")
After sending all tasks, report them as working:
(agent-shell-dispatch-report "TASK-ID" "working" "brief current phase")
The header graph updates at ~100ms with spinners and status colors. Geometry is cached; only status colors redraw per frame. You do NOT need to poll or check statuses.
Tell the user:
Dispatch running. The progress fragment updates automatically. Tell me when:
- All tasks show complete (✓) and you want me to gather results
- An agent needs guidance and you want me to intervene
- You want to stop (
stop)
Do NOT poll statuses yourself. The elisp timer handles progress updates. Wait for the user to tell you what to do next.
You own all task graph updates. Subagents do NOT call agent-shell-dispatch-report — they communicate via messages only. You will receive queued prompts for:
[Task Progress: agent (task: ID)] — subagent announcing start / phase transition. Optional informational signal. The phase label updates in the header automatically.[Task Complete: agent (task: ID)] — subagent finished. If reviews are required (see review policy from Step 1), do NOT mark the task done yet — spawn or send a reviewer first. Only mark done after the review passes:
(agent-shell-dispatch-report "TASK-ID" "done")
[Task Error: agent (task: ID)] — subagent hit an error. Investigate, then:
(agent-shell-dispatch-report "TASK-ID" "error" "reason")
MCP transport errors ("stringp nil", JSON-RPC envelope errors) can cause a subagent's agent-shell-dispatch-msg-send call to fail. SUBAGENT_TEMPLATE.md tells subagents to emit a ===DISPATCH-FALLBACK=== block at the end of their work in that case. If an agent's status shows ready (idle) but you never got a Task Complete prompt, harvest its output via agent-shell-dispatch-view-agent and look for the fallback block. Use it to mark the task done manually.
When the review policy requires reviews:
[Task Complete], send a reviewer to check the implementer's workagent-shell-dispatch-send-to-agent. The implementer fixes and sends a new [Task Complete]. Re-review.Fix-loop shortcut: For efficiency, instruct the reviewer to send change requests directly to the implementer using agent-shell-dispatch-send-to-agent, and have the implementer message the reviewer back when fixed. The dispatcher only gets notified of the final pass/fail outcome — no need to relay every round-trip. When setting up a fix-loop, tell BOTH sides:
(agent-shell-dispatch-send-to-agent (agent-shell-dispatch-agent-buffer \"Impl-1\") MESSAGE). Wait for their reply before re-reviewing."(agent-shell-dispatch-send-to-agent (agent-shell-dispatch-agent-buffer \"Rev-1\") MESSAGE). Include what you changed."Multi-stage reviews: If a task requires multiple review stages (e.g. correctness → style → integration), define all stages upfront in the reviewer's assignment. Each stage reports its outcome. If all stages pass in one go, a single [Task Complete] suffices.
If a reviewer flags an issue in shared code (used by multiple tasks), do NOT bundle the fix with the triggering task's review. Instead:
Permission requests from background agents render as button dialogs in your buffer with all available options. Edit permissions with diffs include a View (v) button that opens an ediff session. The user handles permissions directly — you do NOT accept or reject on their behalf.
(progn
(agent-shell-dispatch-stop)
(agent-shell-dispatch-kill-agents))
View that agent's output and send it guidance:
(agent-shell-dispatch-view-agent (agent-shell-dispatch-agent-buffer "Impl-1") 200)
All dispatch functions must be evaluated in YOUR buffer (the dispatcher). Dispatch state is buffer-local — calling these from a subagent buffer is a no-op.
When the user tells you all tasks are complete:
(agent-shell-dispatch-stop)
(agent-shell-dispatch-view-all-agents 3000)
Report: completed tasks, commits, issues, next steps.
Clean up agents:
(agent-shell-dispatch-kill-agents)
Note: killed agents may leave their buffers behind (especially if you respawned agents within the same session — old instances persist as <N>-suffixed buffers). Clean them up explicitly if they clutter the buffer list:
(dolist (b (buffer-list))
(when (string-match-p "^\\[agent:" (buffer-name b))
(kill-buffer b)))
git worktree remove --force /tmp/up-log-<name> # per worktree
git branch -D fix/<name> # if the branch is no longer needed
When multiple impl agents touch the same repository in parallel, they will race on the working tree. Use git worktrees — one per agent — to give each agent its own filesystem.
git worktree add /tmp/project-impl-1 -b fix/area-1 base-branch
git worktree add /tmp/project-impl-2 -b fix/area-2 base-branch
Then spawn each agent with the corresponding directory:
(agent-shell-dispatch-spawn-agent "/tmp/project-impl-1" "Impl-1" "You are Impl-1. Wait for task assignment.")
(agent-shell-dispatch-spawn-agent "/tmp/project-impl-2" "Impl-2" "You are Impl-2. Wait for task assignment.")
Each agent commits to its own branch. When all agents complete, merge the branches back into the base branch (or let the user do so). Merge conflicts between sibling branches are expected for adjacent code; resolve in the dispatcher before final integration.
Worktree isolation is REQUIRED when:
cargo test / npm test / etc. concurrently (build artifacts collide)It's optional when:
When in doubt, use worktrees.
| Action | Function |
|---|---|
| Spawn agent | (agent-shell-dispatch-spawn-agent DIR NAME MSG) |
| Resolve agent name | (agent-shell-dispatch-agent-buffer NAME) → buffer name |
| Send message | (agent-shell-dispatch-send-to-agent BUF MSG FROM) |
| List agents | (agent-shell-dispatch-list-agents) |
| View output | (agent-shell-dispatch-view-agent BUF LINES) |
| View all | (agent-shell-dispatch-view-all-agents NUM-CHARS) |
| Start task graph | (agent-shell-dispatch-start BUF TASKS) — enables agent-shell-dispatch-render-mode |
| Report status | (agent-shell-dispatch-report TASK-ID STATUS DETAIL) |
| Send msg to dispatcher | (agent-shell-dispatch-msg-send MSG TARGET) |
| Stop task graph | (agent-shell-dispatch-stop) — disables agent-shell-dispatch-render-mode |
| Interrupt one | (agent-shell-dispatch-interrupt-agent BUF) |
| Stop ALL | (agent-shell-dispatch-kill-agents) — also stops task graph |
spawn-agent everywhere (don't rely on agent-shell-dispatch-agent-buffer name resolution — it has been unreliable).agent-shell-dispatch--primary-buffer (it's buffer-local to you). Substitute the literal dispatcher buffer name into their templates.agent-shell-dispatch-start) BEFORE reporting statuses (agent-shell-dispatch-report). Reports made before start are wiped.agent-shell-dispatch-send-to-agent. If the question is ambiguous or you
lack context to answer confidently, ask the USER for clarification before
responding to the subagent — don't guess.ready (idle) without a Task Complete prompt, check its buffer for a ===DISPATCH-FALLBACK=== block — MCP transport errors can silently drop message sends.M-x agent-shell-dispatch-render-mode if something goes wrong.