Harness adapters
pstack skills describe delegation abstractly: "spawn a subagent on model X", "launch N in parallel in one message", "readonly", "AskQuestion". Each is an intent, not a tool name. Satisfy the intent with whatever your session actually provides — your live tool inventory and your CLI's own help are the authority, not this file. Never invent a tool, and say in your reply which mechanism you used.
The primitives
Spawn a subagent. In order of preference:
- Your harness's native subagent or delegation tool, whatever it is called.
- No such tool → invoke your own CLI non-interactively as a subprocess (its help names the command and flags), one invocation per arm, run concurrently in background shells, each arm's report collected from stdout or a file path named in its brief.
- No subprocesses either → run the arms sequentially inline, one at a time, each writing its report to a file before the next starts, then synthesize. Keep the configured arm count.
Each writer gets its own git worktree, whichever mechanism spawns it.
Set an arm's model. Pass the model through whatever the spawn mechanism accepts — a tool parameter, a CLI flag. Only pass a value this session has confirmed the mechanism accepts; anything unconfirmed or rejected means
: omit the model and let the arm run on the session model.
Set an arm's effort. Every role resolves to a model and a reasoning effort (see
The models config below). Pass the effort through the spawn mechanism when it has a field or flag for it. When it has none, or the harness rejects the value, the effort alone becomes
: keep the model, keep the arm, and say in the reply that the effort was inherited. An effort problem never drops a model or an arm.
Parallelism. Real where the mechanism allows it (independent tool calls in one message, concurrent subprocesses); otherwise sequential with the same arm count.
Read-only. Use an enforcing option if the spawn mechanism has one; otherwise state it plainly in the brief ("read-only: do not edit or write files").
Structured questions (). Your harness's structured-question tool if it has one; otherwise ask in plain chat.
Open a todolist. Harnesses name this tool inconsistently, so resolve it by looking, never by recall. Claude Code calls it
, Codex calls it
, Hermes ships it as the
toolset. Search your inventory by the exact names above and by shape, a tool that tracks a plan or a task list, not by the literal word "todo" alone;
is the name that gets missed. Some harnesses defer tool schemas, so a tool absent from the visible inventory may still be loadable through a tool-search facility. Query that facility both ways before you conclude there is none, because a name lookup finds what a shape query misses and the reverse. Only a look that came up empty licenses the fallback: a scratch
in your worktree or working directory when you can write files, otherwise a checklist in your reply updated as items land. Missing the tool never cancels the practice: the full plan stated up front, one item in progress at a time, skips marked with a reason, nothing silently dropped. Name the mechanism you used in your reply.
Loops and wake-ups. Your harness's loop or scheduling facility; otherwise a re-invoking wrapper (script, cron, CI).
Transcripts. Every harness keeps this workspace's session record somewhere — log files under its data directory, or a database with an export command. Locate yours before reading, and stay inside the current workspace's sessions; other projects' transcripts are private.
Hints for known harnesses
Observed circa 2026-09. Treat as starting points, not contracts — verify against your live session before relying on any of them, and prefer what you find over what is written here.
| harness | spawn | todolist | effort | transcripts |
|---|
| Claude Code | tool (custom agents from spawn by name); takes short aliases | . Absent from some builds and permission modes, and it is not always in the deferred-tool list either, so an empty look here is real and the fallback applies | no per-call field; only the frontmatter key of a custom agent file. A subagent inherits the session effort (, ), so the effort is here | JSONL under ~/.claude/projects/<slug>/
, = workspace path with → |
| Codex | (the multi-agent feature, stable in 0.152) takes a model and a reasoning effort per spawn; custom roles live in or with and ; is the subprocess route | . No "todo" in the name, so a keyword scan misses it | the reasoning-effort field on ; -c model_reasoning_effort=<value>
on . A model set without an effort gets that model's default effort (medium on the GPT-5.6 family), not the parent's, so always pass one | JSONL under by date |
| Hermes | a delegation toolset when enabled; for one-shot subprocess runs | the toolset, listed as "Task Planning" and enabled by default. Confirm with , then read the tool's live schema for the call shape | on ; config and per-model agent.reasoning_overrides
. Whether the delegation toolset takes an effort field is unverified: check its schema in session | SQLite store; subcommands list and export |
Universal rules
- Panels degrade by model, never by count. A four-model panel in a one-model harness is still four arms (parallel or sequential), each with a genuinely different brief; the configured list length sets the count.
- Named sibling skills are files. When a pstack skill says "the architect skill" or "read the leaf skill", it names a sibling directory under the same installed skills root. Most pstack skills are gated against model invocation, so they appear in no tool inventory and their descriptions are not in context — that never means missing. Read the named skill's SKILL.md (and any files it references) directly and follow it; record that you applied it by file read. Never edit a skill's gating to make it invocable.
- Tool names in skill text describe intent, never a required tool. , , , , a todolist, and Cursor-era parameters like , , and name capabilities: realize each with whatever your session provides (a search tool, a shell command, a read-only brief, worktree isolation, background execution). A missing tool never cancels the step — find the equivalent, and never report a step blocked on a tool name.
- Config: roles resolve to a model and an effort per The models config below. A value the current harness cannot use is for that field only.
- Honesty: never report parallel arms that actually ran sequentially; name the mechanism used.
- No improvised models: every spawn resolves through a named role. A spawn whose skill names no role resolves through the line, then . Never pick a model that neither the config nor the skill's inline default names, and say which role the model came from.
The models config
~/.agents/pstack-models.md
(user) and
(workspace) map each role to a model and a reasoning effort.
writes and lints the file; its shipped default is
examples/pstack-models.md
next to that skill.
Grammar. , or
to bind several roles at once. Panel roles (
,
,
,
,
) take a comma list, one arm per entry. An entry is
or
. Efforts are
,
,
,
,
,
;
is Codex's Pro mode and is valid only on
.
and
, with or without
, run the arm on the parent chat model. A
,
, or
header starts a section whose lines apply to that harness only; lines above any header apply everywhere. Two roles are special.
is the show-me-your-work reviewer; when it resolves to the model that did the work, show-me-your-work steps down one tier so the review stays cross-model.
is the entry for any spawn whose skill names no role; it ships as
.
Precedence. Resolve the model and the effort of a role separately, taking the first level that has a value:
- workspace file, this harness's section
- workspace file, flat lines
- user file, this harness's section
- user file, flat lines
- the skill's inline default for the model; the effort policy below for the effort
- the line, searched through levels 1 to 4, for a spawn whose skill names no role or whose role has no inline default
- : the value is or , the harness has no way to set that field, or the harness rejected the value
A section never leaks into another harness. A workspace flat line beats a user harness line, so the old rule "workspace wins per role" still holds.
Codex alias translation. On Codex, a Claude alias that reaches step 7 translates instead of inheriting:
| alias | Codex entry | why |
|---|
| | Sol at max is the Fable-parity tier |
| | Sol at high or xhigh matches Opus |
| | Terra is the balanced, mini-like tier, Sonnet's role |
| | Luna is the high-throughput, nano-like tier; the floor keeps it at high |
The translated effort belongs to the alias and stands unless the entry wrote its own
. Hermes has no translation table yet; an alias there is
, as before.
Effort policy. When no
is written: floor
for every role.
for hardest tasks, judgment and prose, bug-fix, perf-issue, hillclimb, how explainer, how critics, why synthesizer, reflect judgment, divergent and synthesizer, arena cross-judge pool, architect runners, and trail reviewer. Nothing in this policy produces
or
; those come only from an explicit
or
on a line, from the Codex translation of
, or from an explicit escalation in the task. Effort never changes an arm count or a model choice.