# Dispatch Worker

> Dispatch a background worker with role-templated prompt and auto-populated collision fences

- Skill: `omninode-ai/dispatch-worker` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add omninode-ai/dispatch-worker`
- Raw SKILL.md: https://api.skillmd.com/api/skills/omninode-ai/dispatch-worker/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: OmniNode-ai (https://skillmd.com/u/omninode-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/omninode-ai/dispatch-worker

---


# Dispatch Worker

Compile a worker dispatch spec through `node_dispatch_worker` and spawn a background agent.

**Announce at start:** "I'm using the dispatch-worker skill."

> **Autonomous execution**: No human confirmation gate. `--dry-run` is the only preview mechanism.

## Worker Behavior

> **Required for all dispatched workers — enforced by `_COMMON_PREAMBLE` in
> `omnimarket/src/omnimarket/nodes/node_dispatch_worker/handlers/handler_dispatch_worker.py`.**
> Operating rule 4's final local test command is `env -u PYTHONPATH uv run pytest tests/ -v`.

- **Ack after each deliverable.** After every discrete deliverable (design doc written, test
  run complete, PR opened, finding logged), send a one-line `SendMessage` to `{reports_to}`.
  Never batch acks across multiple deliverables.
- **Stop after primary task.** When the primary task is complete, send exactly:
  `"Primary task done — awaiting further instruction or shutdown."` then stop.
  Ambient-idle looping after task completion is forbidden.

## Quick Start

```
# Inline YAML spec
/dispatch_worker "
name: pr-202-fix
team: daylight-0411
role: fixer
scope: Fix omnimarket#202 halt_conditions CodeRabbit findings
targets: [omnimarket#202, <TICKET>]
"

# From file
/dispatch_worker ~/docs/plans/workers/pr-202-fix.yaml

# Dry run (print compiled prompt, no spawn)
/dispatch_worker --dry-run "
name: vggp-designer
team: daylight-0411
role: designer
scope: Design VGGP inference pipeline
targets: [<TICKET>]
"
```

## Valid Roles

| Role | Purpose | Default cap |
|------|---------|------------|
| `watcher` | CI watch loop, no code changes | 90 min |
| `fixer` | TDD-first fix + hostile_reviewer + PR | 90 min |
| `designer` | Design doc + hostile_reviewer + plan | 120 min |
| `auditor` | Read-only investigation + findings doc | 60 min |
| `synthesizer` | Reconcile cross-domain design docs | 90 min |
| `sweep` | Short-lived cron pulse, one metrics line | 10 min |
| `ops` | Long-lived stateful admin worker | 480 min |

## Spec Format

```yaml
name: <worker-handle>          # required: lowercase, hyphens/underscores, max 64 chars
team: <team-name>              # required
role: <role>                   # required: one of 7 values above
scope: "<goal description>"    # required
targets: [<ticket>, <pr>, ...]  # required: what this worker owns
collision_fences: []           # optional: auto-populated from TaskList if empty
reports_to: team-lead          # optional: default team-lead
wall_clock_cap_min: 90         # optional: defaults by role (range: 5–480)
model: sonnet                  # optional: default sonnet
replace: false                 # optional: kill existing in_progress worker with same name
```

## Dispatch record persistence (<TICKET>)

Immediately after the node compiles the worker prompt and before `Agent()` is
spawned, write a `ModelDispatchRecord` to
`$ONEX_STATE_DIR/dispatches/<agent-id>.yaml` so downstream hooks
(allowedTools audit, tool-call usage audit, consecutive-failure halt) can
reason about the dispatch:

```python
from datetime import datetime, timezone
from omniclaude.hooks.lib.dispatch_record_writer import write_dispatch_record
from omniclaude.hooks.model_dispatch_record import ModelDispatchRecord

write_dispatch_record(
    ModelDispatchRecord(
        agent_id=spec["name"],
        dispatched_at=datetime.now(timezone.utc),
        dispatcher="onex:dispatch_worker",
        ticket=spec["targets"][0],
        allowed_tools=spec.get("allowedTools", []),
        prompt_digest=prompt_digest,
        parent_session_id=parent_session_id,
    )
)
```

The PostToolUse `post_tool_use_subagent_tool_log.sh` hook appends a JSONL
line per subagent tool call to
`$ONEX_STATE_DIR/dispatches/<agent-id>/tool-calls.jsonl` when
`ONEX_AGENT_ID` is set in the subagent environment.

## Worker Operating Rules (worker_template_version: v2)

The Operating Rules are injected verbatim into every worker prompt by `prompt.md`
before spawning. They are auto-injected — dispatchers MUST NOT hand-restate them.

They are defined once, canonically, and referenced here rather than restated:

@_lib/dispatch-laws/helpers.md

This file previously carried a second hand-maintained copy which had drifted from the
injected block: it declared itself verbatim, undercounted the rules, dropped one
entirely, and abridged two others. Do NOT restate them here again.


## See Also

- `node_dispatch_worker` (omnimarket) — compiles the prompt template
- Design: `docs/design/dispatch-worker-skill-design.md`
- `src/omniclaude/hooks/model_dispatch_record.py` — dispatch record schema
- `src/omniclaude/hooks/lib/dispatch_record_writer.py` — writer/reader
- `src/omniclaude/hooks/model_resume_manifest.py` — resume manifest schema (<TICKET>)
- `src/omniclaude/hooks/lib/resume_manifest_writer.py` — phase-boundary manifest writer (<TICKET>)

