Polyhydra Skills  /  Agent Workflow

delegate

Route work off the expensive tier -- a Codex CLI worker, a Haiku/Sonnet subagent, or local Ollama -- instead of running it inline. Use for read-only investigation that would flood the transcript (grep sweeps, log trawls, triage) and to dispatch already-specified implementation, on "hand this off", "give it to codex", "use a worker". Code changes still need a GitHub issue first -- route through polyhydra-issue-router, this is not a way to implement without one.

Agent Workflow

Drop this in — save the block below as ~/.claude/skills/delegate/SKILL.md, or run:

mkdir -p ~/.claude/skills/delegate
cat > ~/.claude/skills/delegate/SKILL.md <<'EOF'
# (paste the full source block below into this file)
EOF

Full source

SKILL.md — copy everything inside
# Delegate — get work off the expensive tier

The in-session trigger for the
[model-tier delivery loop](../../docs/workflows/model-tier-delivery-loop.md).
That doc defines the tiers; this skill is what makes them get *used* during an
ordinary session instead of only inside a codeburn run.

Role→tool bindings are canonical in
[`config/agent-roles.yaml`](../../config/agent-roles.yaml)
(`python tools/agent_roles.py <role>`).

**Related, not duplicate:** `skills/polyhydra-issue-router` covers the
*issue-first* path — start from a GitHub issue, classify it, split cheap prep
from Codex implementation, produce a handoff. This skill covers the
*session-first* path: work is already in front of you and the question is
which tier should carry it.

**Session-first is a routing decision, not a way around the issue.**
[`AGENTS.md`](../../AGENTS.md) requires a GitHub issue for any new slice,
backlog item, or follow-up, and that rule outranks this skill. So:

- **Read-only investigation** — recon, grep sweeps, log trawls, "how does X
  work", reviewing a diff — route freely from a live conversation. No issue
  needed; nothing is being changed.
- **Anything code-changing** — create or identify the issue first, then route
  the implementation through `polyhydra-issue-router`. Come back here only to
  dispatch work that already has one, and give the worker its own issue-linked
  worktree lease.

Reaching for this skill *because* no issue exists is the misuse it has to
refuse. Convenience is exactly the pressure the issue-first rule exists to
resist.

## The one discriminator

**Match the tier to ambiguity, not to task size.**

A big job with a crisp definition of done is cheap work. A three-line change
where "correct" is still being negotiated is expensive work. Size is a trap —
routing by it is how a 40-file mechanical rename eats frontier tokens while a
subtle auth decision gets handed to a worker.

## The lanes

| Lane | Dispatch | Takes | Does not take |
| --- | --- | --- | --- |
| **Codex worker** (Muscle) | `skills/delegate/scripts/delegate-codex.sh` | Well-specified implementation: write the code, run the tests, iterate. A contractor working a ticket. | Anything where the spec is still being argued. |
| **Haiku subagent** (cheap Claude) | `Agent(subagent_type:"Explore"\|"general-purpose", model:"haiku")` | High-volume, low-ambiguity reading: grep sweeps, log trawls, "which files touch X", first-pass triage. | Judgment calls, security review, final verdicts. |
| **Sonnet subagent** (mid Claude) | `Agent(..., model:"sonnet")` | Bounded reasoning that produces a *written conclusion* — a focused investigation, a triage write-up, a recommendation. | Writing code. Implementation is Terra's lane per `AGENTS.md`; send refactors to the Codex worker. |
| **Local Ollama** (Support) | [Ollama code agents](../../docs/features/ollama-code-agents/architecture.md) | Bulk text crunch on the homelab GPUs; condensing verbose output before it reaches the frontier tier. | Anything private or unsanitized — the [Local AI Fabric contracts](../../docs/features/local-ai-capability-fabric/contracts.md) fail closed. |
| **Stay on the frontier tier** (Brain) | — | Defining what "done" means, judging whether it was met, security and architecture, reviewing a worker's diff. | Volume. |

The two Claude lanes are the tiers the delivery loop originally lacked: it
jumped straight from Codex to local Ollama, leaving nothing between the
frontier model and the homelab GPUs.

## Offer, don't silently absorb

When work in front of you fits a lane above, **put it to the operator as a
picker before starting** — this is exactly a "which direction" moment under
the [collaboration contract](../../docs/experience/collaboration-contract.md).
One tap, no typing:

- *Hand to a Codex worker (background)* — say what it will do and that it returns a log path
- *Cheap Haiku subagent* — for search/summarize fan-out
- *Keep it on the frontier tier* — when the expensive attention is the point

Lead with the recommended lane, label it `(Recommended)`, and say what each
option **causes** (cost, latency, who reviews the result), not what it is.

Two exceptions where you act instead of asking:

- Noisy investigation you were going to run anyway (grep sweeps, log trawls) —
  spawn the cheap subagent and keep only the findings. Asking wastes a tap.
- The operator already chose a lane earlier in the session. Don't re-ask.

## Dispatching a Codex worker

Implementation work, which needs its own tree and an issue:

```bash
skills/delegate/scripts/delegate-codex.sh -C /path/to/repo \
  -W <branch> --issue-url https://github.com/<owner>/<repo>/issues/<n> \
  "Implement <spec>. Run <test command> until green. Small reviewable diff."
```

Recon, which needs neither:

```bash
skills/delegate/scripts/delegate-codex.sh -C /path/to/repo -s read-only \
  "Summarise how <subsystem> handles <case>. Cite file:line. No changes."
```

Do not copy the first form without `-W`: a writable dispatch straight at a
repository is refused, by design. The worker gets a tree of its own or it does
not run.

Backgrounds by default and returns a log path immediately. Flags: `-s read-only`
(recon), `--no-net`, `-m MODEL`, `-w` (foreground/stream), `-f prompt.md`,
`-n NAME` (log label), `--check` (auth preflight), `-W BRANCH` with
`--issue-url` (create and lease the worker's own worktree),
`--allow-shared-tree` (deliberate override, see below). Logs, the last
message, and a copy of the prompt land in `~/.claude/logs/delegate/`, under a
per-invocation stem so concurrent workers cannot overwrite each other.

Two defaults are enforced by the script rather than left to the operator's
ambient Codex config, because inheriting them silently defeats the point:

- **`gpt-5.6-terra` on `service_tier="default"`.** Ordinary delegated work is
  Terra on the default tier per [`AGENTS.md`](../../AGENTS.md); inheriting a
  config set to Sol or a premium tier would put mechanical work on the
  expensive lane this skill exists to avoid. `-m` still overrides.
- **Writable dispatch into any pre-existing git worktree is refused** — primary
  or linked, yours or another session's. The dispatcher cannot tell whether a
  tree it did not create is idle or actively owned, and racing a live session
  is how uncommitted work gets destroyed. Documenting this in prose is not
  enough; the default path has to enforce it.

  The safe path is first-class, so it is also the easy one:

  ```bash
  delegate-codex.sh -C <repo> -W <branch> --issue-url <issue> "<prompt>"
  ```

  That creates `<repo>/.worktrees/<branch>` from `--base` (default
  `origin/main`), registers the worktree lease, and dispatches the worker
  there. `--issue-url` is required because code-changing delegation is
  issue-backed; it must be an exact GitHub *issue* URL, since the lease
  registry rejects pull-request URLs.

  Escape hatches: `-s read-only` for recon against any tree, or
  `--allow-shared-tree` when you know a tree is idle.

  Detection compares the worktree's git dir against the common git dir rather
  than looking for `/worktrees/` in the path — a primary checkout that merely
  *lives* under a directory of that name (`~/worktrees/<repo>`) would otherwise
  slip past. A standalone scratch clone **is** a primary checkout as far as git
  is concerned. And when git cannot be inspected at all (dubious ownership),
  writable dispatch fails closed rather than assuming there is no repository.

Verified against `codex-cli` 0.145.0, where `codex exec` is non-interactive by
default (there is no `--ask-for-approval` flag on the subcommand) and needs
`--skip-git-repo-check` outside a repo. The script handles both.

**Write the prompt like a ticket, not a chat message.** The worker cannot ask a
follow-up question. It needs the goal, the acceptance criteria, the exact
command that proves it, and the boundary of what it may touch. A vague prompt
is how a worker burns twenty minutes producing the wrong diff.

**Do not sit and watch it.** Dispatch, do something else, check the log later.
If nothing else is in flight, say so and hand back — don't poll in a loop.

## Rules that survive delegation

- **An issue comes first for anything code-changing**, with the worker on its
  own issue-linked worktree lease. Delegation changes who does the work, not
  whether it is tracked. The script enforces this: `--issue-url` is required
  for *every* writable dispatch against a repository, including
  `--allow-shared-tree`, and the issue must belong to the repository being
  changed — a Dev Forge umbrella issue is a portfolio gate, not repo-local
  implementation authority. Read-only recon needs no issue, and neither does a
  non-repository scratch directory, where there is no branch or PR to trace to.
- **The dispatcher still owns the verdict.** A worker's diff is a submission,
  not a result. Read it against the spec before it counts as done. That is the
  Brain step in the loop and it does not delegate.
- **Never delegate the confirmation of a protected action.** Merges, deploys,
  destructive or hard-to-reverse operations, secret and access changes stay
  with the human regardless of who wrote the code.
- **Default service tier, smallest model that can safely finish.** Never
  premium/priority/fast for volume work, per
  [`prompts/muti-agent-work.md`](../../prompts/muti-agent-work.md).
- **Workers get their own worktree or a scratch clone**, never a live primary
  checkout — an unattended `codex` session has destroyed uncommitted work in a
  primary checkout before (`docs/parked-ideas.md`, 2026-08-03 and 2026-08-05).
- **Scratch goes in the job tmp dir**, never `/tmp`.