Delegated seat contracts
Delegated seats outside the manager's filesystem
The portable lifecycle bootstrap
design and SPEC §13.17 define how a managed agent that enrollManagedAgent already enrolled starts
in a child that cannot see the manager's filesystem. The ordinary spawn path writes the token and
sentinel under the manager's workspace root and hands the runtime a launch whose bearer command and
material file are paths on that filesystem, so such a child needs this path instead.
Runtime handoff
The delegation boundary is one optional runtime method. A runtime that implements
Runtime.spawnDelegated(launch, handoff) receives two values and no paths: a DelegatedSeatLaunch
(connector name, persona text, managerInstanceId, model and the other launch choices) and a ManagedLifecycleHandoff
(space, owner, actor, the host-chosen lifecycleUid, broker and IdP pins, the pinned exchange base,
the sentinel, the channel lists, and the raw actor token). The manager enrolls once, as it does
today, and builds the handoff from what it holds. It never sends the token to the host, never copies
a file from its workspace or secret store, and never builds a local launch for that seat. No signer,
issuer or callout record, loopback capability, provisioner or manager credential, control token, or
manager path crosses. A spawn choice that only the manager's host can honour is refused before
enrollment: --resume, a manifest agent's continuity: exact, --cwd, and any shared MCP server,
whether from --share-tools or the config default (--share-tools none passes).
A delegated manager also refuses a caller-supplied persona config override in resolve-agent,
spawn and direct Manager.startAgent calls. The shared persona resolver refuses before checking
or reading that path, with failed-precondition on the wire and one fixed execution-mode message.
Pass a named catalog persona instead. This does not change locally executing managers. A resolved
manifest can still use its own validated, host-materialized persona resource. The wire schemas
accept no internal resolved field that could bypass the config refusal.
Child bootstrap
The runtime creates one provider resource under managedRuntimeKey(target), writes the handoff into
it as one 0600 file and the persona beside it, and runs the stock bootstrap there:
cotal spawn --config <persona-file> --space <space> --name <actor> --expect-owner <owner> --expect-lifecycle-uid <uid>
with COTAL_MANAGED_HANDOFF_FILE naming the file and COTAL_MANAGER_INSTANCE naming the launching
manager. delegatedSeatCommand builds that argv and env.
cotal spawn reads the file into memory, deletes it and drops the variable before it parses flags,
prints help or loads extensions, so every outcome, a refusal of its own flags included, leaves no
file. It refuses before any broker connection or exchange request when COTAL_MANAGER_INSTANCE is absent (COTAL_MANAGED_HANDOFF_FILE requires COTAL_MANAGER_INSTANCE; DelegatedSeatLaunch.managerInstanceId is required and a newer CLI child under an older manager or runtime refuses every delegated launch, so managers and the CLI must be upgraded together) or malformed, or when the
space, owner, actor, or lifecycle UID differ from the expected values, and then runs the
enrollment-redeem consumer: it registers the mesh in its own home, writes the token to its own 0600
file, and exchanges it through agent-bearer --exchange-url unchanged. It never enrolls, redeems, or
mints a token or UID.
Provider closure guarantees
Readiness is still mesh presence. A create whose answer is lost leaves the handle running, so the
launch settles uncertain and stays held; the manager never retries it. A provider read that finds no
resource under the key is not an exit, because the create may still land. Every close by
managedRuntimeKey is fenced: it completes only once the create was answered or the provider refuses
any later create under the key. A provider that names its own resources may run the create as a
durable operation keyed by managedRuntimeKey and close through the identifier its authenticated
create response returned, kept where the host can read it without the manager. Only that response
binds an identifier to the key; one derived from the key or found by name or listing is never closed
or adopted, and while the response is unknown the launch stays held. Every stop, the reap of a child
whose parent exited and Manager.stop({ withAgents: true }) included, runs prepareAgentRetirement
for the UID-exact target, then stop() on the handle spawnDelegated returned, then the terminal
barrier. preparePreservation refuses a cut that holds a delegated seat, and a Manager.stop() after
a refused cut retires the seat through the same steps. After the manager is gone
the host runs the same steps, makes the same fenced close by managedRuntimeKey, and finishes at
MANAGED_RETIRE_PATH. Supply spawnDelegated only from a runtime whose host can make that fenced
close without the manager. The enrollment redeem
(COTAL_ENROLLMENT_FILE) stays for lifecycles whose token the host generated itself; a host cannot
mint one for a manager-enrolled lifecycle because it holds only the digest.
Delegated recovery contracts
Core exports RemoteDelegatedRecoveryRequest, RemoteDelegatedRecoveryResult,
RemoteDelegatedRecoveryLaunchRequest, their closed parsers, and
parseDelegatedRecoveryDescriptor. Runtime.rebindDelegated describes an optional same-child
rebind. These are contracts for SPEC §13.18, not an enabled recovery path. The current Manager
does not call the new method or reconstruct delegated rows. Its public adoptRuntimeHandle
returns a native handle without inserting a managed row.
A supporting host retains the descriptor in the original user-intent consuming CAS, binds each claim to the original instance and current registration, and supplies complete fenced scans. The manager needs its original persistent secret store and a runtime that can verify the same child execution after process loss. It must retain held aliases before reconciling accepted goals. Missing storage or unverified child identity keeps recovery held; neither permits another launch. The request parsers validate data, not fresh host authority or durable transactions. Existing hosts continue to refuse the opt-in launch extension rather than silently ignore it.
Related contracts
Refused launch choices
Host-dependent launch choices are refused before enrollment. See the detailed contract.
Retirement order
Delegated stop and retirement follow the provider closure guarantees. See the detailed contract.