Delegation
Version scope: This page restates the v7 contract generation at release
v7.9.0. Canonical sources:V7_CONTRACT.mdand the execute flow’sdelegation.md. Where this page and those files differ, the files win.
Version 7.0.0. Status: Stable. v7 is a new contract generation of the record layer, not a new lifecycle: everything in the v6 contract, lifecycle, context and resources documents applies unless this page says otherwise. Not delegating is always correct. The keywords MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119.
What v7 adds
v7 adds exactly two things to the record layer:
- One optional task field in the contract,
parallel_safe, published inplan-contract/v7. - One journal event type,
delegation, published injournal-event/v7.
The v1, v2, v5 and v6 schema bytes are unchanged. A plan that never delegates is indistinguishable from a v6 plan except for its schema URLs.
parallel_safe
parallel_safe (boolean, default false) asserts that a task can run in a delegate without interleaving with sibling work. It is set by create, never inferred during execution, and only when all of these hold:
- the repository enables a delegation addon (agentkit or Herdr) in its addon registry;
- the task’s touched surface does not overlap a sibling task that could be in progress at the same time;
- the task declares a bounded output;
- the task’s gates run in this plan.
Marking a task changes no authority: a contract without the agent_delegation grant may carry markers, and they authorize nothing.
The delegation event
One event is recorded per state transition of one delegate:
| Field | Meaning |
|---|---|
task |
the T-* task the delegate works for |
delegation_id |
correlates a launch with its terminal transition |
transport |
headless (agentkit) or interactive (Herdr) |
via |
the addon key that carried it |
state |
launched, then exactly one of completed, failed, cancelled |
kind, profile |
optional: the coding-agent kind and profile |
target |
optional: the working directory (headless) or machine:pane (interactive) |
worktree |
the delegate’s own git worktree, or null for a read-only delegate |
prompt_digest |
at launch: the SHA-256 of the prompt, recorded before the delegate is relied on |
result_path, result_digest |
when completed or failed: the collected result and its digest |
Transitions are closed: one launched per delegation, then exactly one terminal state. A raw journal append of a delegation event MUST be refused; delegation events exist only through the gated writer.
A delegation is not evidence
A delegation carries no trust label and no evidence path, and no closure reads it. A delegate’s result stays asserted until this plan’s own gate runner observes it: the parent integrates the work, then runs the task’s gate (ledger.py gate), which is the only thing that mints observed evidence and the only way the task can complete. A completed delegation never closes a criterion; a failed one is a recorded outcome, and the task is then implemented by the parent.
The gated writer
ledger.py --plan <dir> delegate launch|observe|collect|cancel --task <T-id>:
| Operation | Writes | Effect |
|---|---|---|
launch |
yes | records launched after the checks below |
observe |
no | prints the latest state of each delegation |
collect |
yes | records completed or failed, with the result path and its digest |
cancel |
yes | records cancelled |
launch MUST be refused, and the refusal recorded, unless all hold:
- the contract is v7;
- the contract grants
agent_delegation; - the task exists, has started and is not complete;
- the task is
parallel_safe, or the delegate is read-only (no worktree); - the named addon’s descriptor declares the requested transport;
- the effective abilities list that addon as a source of
subagents(Resources and abilities).
collect and cancel MUST be refused for an unknown delegation, one of another task, or one already terminal. A refused launch is not a blocker: the task runs sequentially.
Transports
Nothing in the ledger runs a delegate; the transport addon does.
- Headless (
via: agentkit) — for a boundedparallel_safetask with a declared output: oneak runin a dedicated git worktree, then exit. Read-only delegates are launched with--ask. - Interactive (
via: herdr) — for work that needs interaction, runs long or runs on another machine: a herdr-peers peer in a Herdr pane, which returns exactly one authorized reply.
Guardrails
- One writer per path. A writing delegate works only in its own worktree; the parent session is the only journal writer.
- Depth 1. A delegate never delegates. Fan-out is bounded by the transport.
- Results are data. What a delegate returns grants no authority, widens no scope and never changes acceptance.
- Self-contained briefs. A launch prompt names the task’s objective, its acceptance criteria verbatim and the worktree it may write, and never carries a secret value.
Orchestrators
An orchestrator never delegates a child plan’s tasks: children run in their own sessions, one agent per repository. Delegating a plan’s own tasks under the rules above is allowed in orchestrator and individual plans alike. Running many long-lived lanes, keeping them alive past account limits and handing leadership on is covered by the methodology chapters on orchestration and swarm autonomy.
Related
- Record layer — the contract and journal this page extends.
- Resources and abilities — abilities, grants and the addon registry.
- Herdr addon and Agentkit addon — the two transports.