Delegated agents
The errand may leave the tower. The keys, the ledger, and the last word do not.
Spellweaver delegates through an attributed AgentJob. The coordinator tracks it; Graph
holds station state; the Run ledger binds its wait. An adapter receives a frozen request, never
the live Run, and the Pattern parks for one terminal adoption.
Today only the deterministic, effect-free reference adapter runs by default. Codex and Claude
have one-shot protocol adapters behind an unimplemented, refusing-by-default host port. Foreign
CLI execution, Coffin containment, and provider effects remain undelivered; the delivered boundary
below separates the current job mechanics from those designs.
ADR 28 owns delegation law.
Agents owns the opaque-runtime boundary;
Workers owns AgentJob labor.
Seal the labor
| Type | Exact contents |
|---|---|
DelegatedAgentRequest |
request_id (idempotency key), run_id, step_id, runtime, profile (read, candidate, or verify), prompt, and input_artifacts |
DelegatedCliRequestV2 |
Explicit CLI schema/compiler, the occurrence/prompt fields, exact mechanical intent and qualified operator task/projection/custody/verification bindings; no positive authorization field |
DelegatedAgentJobRef |
job_id, request_id, run_id, runtime, and profile; it does not copy step_id |
DelegatedAgentJob |
request, ref, status, optional result, and ordered events |
DelegatedAgentResult |
Same job_id, terminal status, optional output, artifacts, and error; failed, timed_out, and lost require an error, while succeeded forbids one |
An ArtifactRef is frozen metadata for external bytes, not bytes or custody. The full station
contract declares containment, budget, timeout, cancellation, artifact boundary, and permitted
downstream use. Today's
DelegatedAgentRequest has no budget or timeout fields, and State records no measured delegated
budget ledger. V2 adds the four existing capture/wall bounds and owner references; it does not
supply the full host/provider budget envelope or implement those owners. Its actual owner producer
remains absent and the trusted observation consumer denies by default. A positive inert fixture
proves consumer conformance only. Workers
owns the exact version/codec, validity and compatibility contract.
Fresh legacy CLI requests refuse before host launch. Historical lookup and cancellation remain readable at their original evidence scope; missing mechanics are never backfilled from current settings. The published delegated score revisions retain their legacy requests. V2 currently passes through inert callers and the existing store/coordinator, not a new published Pattern or native Creation admission path.
DelegatedAgentRequest and ArtifactRef are frozen from construction. The same
request_id and content returns the existing reference without another start; conflicting
content fails. Pattern lifecycle owns the pinned workflow context.
Park for one job
queued → admitted → preparing → running → succeeded | failed | cancelled | timed_out | lost
This is the normal path; earlier states may take only their declared terminal edges. The station
stores job_id, GraphRunner snapshots, and the worker binds that owner with
AWAITING_DELEGATE. Only its terminal job may re-admit the Run.
First terminal adoption wins. Duplicate or late result adoption is inert and appends no event; a
mismatched job id is rejected, and an older job cannot resume a newer wait. Only succeeded lets
the delegated rite project optional text; every other terminal status fails it.
Reference cancellation is idempotent; no effectful process-tree cancellation is delivered.
lost records indeterminate external truth: it is terminal for result adoption, neither polled nor
restarted, and not permission to repeat. It is also not containment proof. Explicit parent
cancellation still calls the owning runtime's cancellation operation and records
lost → cancelled only after that call returns. Cancellation during runtime start settles lost.
An unclassified exception after runtime.start is invoked also settles lost; a failure before
invocation may settle failed.
Resume admission atomically creates the fresh monotonic delivery key. Publication failure leaves that exact queued delivery for relay. Startup recognizes the pre-park crash window only when the first resumable checkpoint binds the same Run and delegated job; otherwise it contains correlated jobs before parent failure. It refreshes durable delegated waits and re-admits only the terminal job that owns each wait; missing coordination or owner identity fails required PostgreSQL startup. After the admission CAS wins, repeated callbacks are inert. Stasis and return owns re-admission.
Keep the keys outside
The serialized envelope contains no RunContext, live toolsets, provider objects, leases,
credentials, or ambient authority. A profile and pure policy express posture; they do not prove
enforcement.
Returned text and ArtifactRefs are data, not authority. A lower-trust return remains
provenance-tagged and quarantined: it grants no instruction, execution, promotion, or effect
authority, only station-declared interpretation. A reference alone neither admits nor materializes bytes.
Return quarantine owns this law.
The host marks candidate content produced through this job lineage agent_generated; a later
human approval does not relabel it. When a candidate touches a Protected
Region, promotion follows
the exact live Gate in Pattern lifecycle.
The delegated runtime never receives the authority to alter or erase the target-owner manifest.
If a delegated request, child provider call, or returned derivative may cross a remote boundary, it also follows the parent anonymization and egress contract. Delegation cannot copy authority or shed privacy lineage.
The runtime and its provider are separate consumers. A remote runtime receives its own minimum
workspace projection under a DelegatedRuntimeTarget; a child model receives a second consumer-
specific Cut when transformation policy requires one, plus a fresh PortalTarget decision for its
exact prompt/tool envelope. A local Coffin still
protects the host from its runtime even when only the child call crosses the network. The outer
AgentJob never authorizes an unknown series of child payloads.
This separation is also the delegation's economic leverage: the local anonymizer and bastion can make subsidized remote cognition usable without making the remote runtime custodian of the raw repository or its authority.
Provider-private commands and credentials stay behind the adapter boundary. Effectful foreign
labor additionally requires the Security-owned Coffin supervisor, job-scoped nono policy, and
Provider Gate; none belongs inside Pattern law. The Coffin
profile owns those boundaries.
A runtime that cannot use the exact Provider Gate endpoint, disclose its child model route, or
disable ambient network/fallback is ineligible. Transparent MITM is not an adapter.
Wrap a CLI as a bounded adapter
Creation's CLI branch uses this job boundary for a concrete engineering assignment. The wrapper is a deterministic protocol adapter under a supervisor: it translates an admitted task into one runtime invocation and translates observed termination into a result. A separate native Agent may prepare or review that task. The wrapper does not become another sefirah, coordinator, or source of permission.
An effectful adapter needs these five passages under the existing Coffin contract:
- Prepare. Pin the base, task projection, allowed paths, runtime/adapter versions, output contract, limits, and authorized downstream use. Resolve effective configuration explicitly, including hooks, plugins, MCP servers, and continuation state; arbitrary project or user configuration must not expand the task. Apply the Privacy Cut when the chosen recipient requires transformation. Required governing instructions still reach the worker in its admitted packet.
- Launch. Use an absolute executable and bounded argument vector, with task text supplied as data rather than interpolated shell code. Bind the provider session and supervised process to the job when observable. Attest workspace, environment, credentials, outbound calls, and resource boundaries before invoking an effectful runtime. Prompt instructions or CLI tool permissions alone do not establish this containment.
- Observe. Parse the versioned machine event protocol, keep diagnostics distinct, and bound both streams. Preserve ordering, partial results, and capture gaps. An unknown usage count is unknown consumption, not a zero-cost receipt. Provider tool events remain attributed claims unless the trusted host independently observed the stated operation.
- Settle. Correlate the terminal protocol record, process outcome, job identity, and retained
artifacts. Truncated output, an unresolved child, or an ambiguous start cannot become success
from the last sentence alone. Cancellation and timeout require the supervisor's full descendant
settlement evidence; apply the existing
lostand reconciliation rules when effects remain uncertain. Never start another attempt merely because the response was lost. - Return. Collect bounded candidate bytes under host custody, check allowed paths and base, and quarantine them separately from narrative and provider events. Use declared rehydration positions only; a raw patch is not a general substitution template. Independent local review and verification examine the exact resulting candidate. Adapter success neither passes those checks nor promotes the artifact.
For a first adapter, declare how each observed runtime event and exit condition maps to the
existing job statuses. Do not make every non-zero exit failed: work may already have occurred.
An adapter-specific rejection receipt can establish that nothing started; uncertainty cannot.
The current request/result types are a starting envelope, not evidence that this richer binding,
budget accounting, or artifact custody already exists.
The current protocol implementation pins Codex 0.159.2 and Claude Code 2.1.296. It builds literal
commands with prompt bytes on stdin, isolated configuration roots and an allowlisted replacement
environment, then parses bounded JSONL. Incomplete lines, malformed or duplicate terminal evidence,
oversized output, and success paired with a failing process exit remain lost. Raw provider errors
and stderr do not enter retained diagnostics. Polling receives the store-retained request; V2
independently compiles its complete expected launch specification and limits before comparing the
host result and matching receipt. Historical legacy lookup correlates only its original request
and deterministic stdin. Cancellation needs the same retained interpretation and matching
whole-job containment receipt, including before the first poll. Neither operation re-admits or
launches work, even after owner-observation expiry. Claude accepts a reviewed core event subset with one initialized session; unknown
event variants refuse until their envelopes and ordering are reviewed.
No host implementation or authentication bridge ships, and neither adapter is automatically registered. Security requires an exact audited source/policy/executable qualification with applicable advisories dispositioned; a version number, CLI help and advertised limits do not qualify a host. Containment version selection explains why the former series baseline was retired without admitting a replacement. The required outer service, network, resource, credential, Gate and artifact boundaries must all be proved before any real launch.
Compare actual integration surfaces
The following primary documentation was checked on 2026-10-12 for this design. It supplies implementation leads, not LychD acceptance receipts or a reason to adopt a provider's default permissions.
| External surface | Useful mechanism | LychD still has to establish |
|---|---|---|
| Codex non-interactive mode | codex exec --json emits JSONL events; --output-schema requests a structured final result. |
Exact event/terminal interpretation, effective configuration, artifact custody, and host verification. |
| Codex app-server | Bidirectional stdio JSONL supports explicit approval requests, thread/turn identity, and interruption. | Pin the binary's generated protocol schema and admitted methods; exclude thread/shellCommand and experimental process/*, which run outside its sandbox. |
| Claude Code programmatic mode | Print mode offers JSON, streamed events, and schema-constrained output. --allowedTools controls auto-approval; bare mode limits ambient discovery. |
Tool availability and OS containment separately; required task context; pinned behavior when schemas, streams, or background work fail. |
| Claude Agent SDK configuration | Explicit settings sources, tools, model, turn limits, and spending limits configure its runtime loop. | Python's env merges with the inherited environment; supply a clean supervisor environment rather than assuming a small dictionary removes secrets. |
| nono's D-Bus advisory | A documented local IPC escape in CLI profiles before the listed fix demonstrates why a sandbox name is insufficient. | Current patched implementation and policy, with negative tests for host IPC and descendant escape on the admitted platform. |
For the first bounded job, prefer one machine-readable invocation over terminal scraping. Use app-server when approval and continuation require a bidirectional protocol. Each runtime keeps a thin adapter; the supervisor, Provider Gate, budget accounting, and artifact admission remain shared owners. This is an implementation recommendation, not a selected or installed runtime.
Pin effective configuration
Current Settings accepts one exact delegated casting selection:
[weaver.delegation]
revision = "2"
runtime = "reference"
profile = "read"
This executable example selects the inert reference runtime through delegated_rite@2. Omission
keeps revision 1. Another runtime must already be explicitly registered; an unknown name refuses
assembly. New admissions retain the selected runtime/profile in Run intent and checkpoints.
Changing configuration or retrying an idempotency key does not redirect an existing Run.
The selector supplies no host, privacy, provider or execution authority.
There is no claude, codex_cli, fallback, or anonymization activation switch. Unknown
fields are rejected. A future effectful selection must also retain its effective configuration
with the job: runtime and protocol revision, model and Gate endpoint, isolated configuration and
session roots, available tools, hooks/MCP/plugins, allowed environment, output contract, and finite
time, token, spend, process and artifact limits. A resumed job retains that selection; changing
operator settings does not rewrite an admitted occurrence.
Disable implicit provider fallback in each harness. A configured alternate belongs to the pinned execution-road policy, with separate privacy, destination and budget admission. A timeout after submission requires reconciliation before an alternate can start. Even a same-model retry is another physical disclosure: Claude's documented gateway protocol can retry with changed request fields, so a retry label cannot establish identical bytes. Test every child request at the Gate.
Supported account integration is a separate compatibility decision. OpenAI documents an app-server plan-usage integration; its existence does not admit a LychD route or authorize copying an operator's login store. Bind any future supported account flow to its actual application, entitlement and credential custodian. Portal Roads retains the current direct-server-API starting point.
Prepare the adapter before remote labor
Complete the capability in independently reviewable slices:
| Slice | Evidence needed before advancing |
|---|---|
| Protocol and result normalization | Recorded synthetic streams exercise success, explicit rejection, malformed/truncated output, duplicate terminal events, mismatched identity, and oversized diagnostics. No model or foreign executable is needed. |
| One contained local runtime | Observe denied out-of-scope reads/writes, unavailable host sockets and credentials, bounded output, complete cancellation, and reconciliation after an ambiguous launch. CLI flags alone are insufficient. |
| Admitted provider crossing | Verify the exact destination and payload, applicable Cut and utility evidence, and every child call's gate; block an undeclared retry or fallback. |
| Creation candidate return | An exact patch or artifact survives quarantine, any permitted rehydration, and independent checks against the real base. A useful proposal can still fail acceptance. |
Adversarial checks include a process that prints success before failing, a valid result whose artifact belongs to another job or base, a background child that outlives its parent, and a patch that targets a path outside the admitted workspace. Pair them with successful controls so refusal cannot masquerade as a working adapter. The bounded protocol slice has offline tests; contained execution, provider crossing and candidate custody still need their own acceptance evidence.
Name the delivered truth
Delegated execution is Partial in the State of
Work. The only runnable adapter is
reference: process-local, deterministic, and performing no model, filesystem, subprocess, or
network work.
Codex CLI (codex) and Claude Code (claude) have unregistered protocol adapters whose default
host refuses execution. OpenCode Go (opencode-go) remains a declared-only example. No effectful
Coffin supervisor or CLI/provider process, credential isolation, or durable artifact custody is
delivered. Database shapes and a PostgreSQL store exist without a real provider or two-process
PostgreSQL recovery receipt; exact pre-park recovery is proved only with focused in-memory tests.
The tracked delegated-coding playbook records repository procedure and design input. It supplies neither runtime law nor delivery evidence.
Execution roads owns when this job form is preferable to a native Portal call or sovereign A2A task.