Chio/Docs
LOGIN · JOIN

Process identity and authority

Give every worker a durable name and only the authority its part of the job requires.

Concept chio@5f63e6e

On this page

A long job outlives the workers that run it. The host names each process once, binds it to its parent and a narrowed grant, and keeps all three fixed while workers crash, restart, and change language.

The running example is a four-process tree working on the pricing project: root delegates to triage and fixer, and fixer delegates to tester to rerun the flaky test in issue #416. The report project follows the same rules with two children.

Each child holds a narrowed share of its parent's grant

A child descends from its exact parent through a verified narrowing of scope, validity, and budget share. Root allocates 3,000 basis points to triage and 3,000 to fixer, and fixer's tester receives 1,000 within fixer's ceiling.

Process treeChoose an action.
grantsholds3,000 bps3,000 bps1,000 bpsaaaκroot grantp₀rootBtree ceiling100 callsp₁triageread_filep₂fixerread_file, write_file, run_commandp₃testerrun_commandgrantsholds3,000 bps3,000 bps1,000 bpsaaaκroot grantp₀rootB100 callsp₁triageread_filep₂fixerread_file, write_file, run_commandp₃testerrun_command

One root grant bounds the whole tree

Every process holds part of one root grant. The tree shares a ceiling of 100 calls, held as B, and each child receives a share in basis points with a subset of its parent’s tools. Shares are authority allocations; any process can reach the shared ceiling. Process identity.

The four-process authority tree with its declared shares and tools. Cancel and revoke act on fixer; workers are drawn as a. Guard checks and the order of in-flight calls are left out.

Shares are authority allocations; the tree's 100 calls stay one shared ceiling. A busy triage can reach that ceiling, which then blocks a new tester key as well. Replaying an existing key needs no new tree slot, and the kernel still applies current validity and guard checks to it.

In the report project, root delegates 5,000 basis points each to producer and consumer under one ten-call ceiling, and its complete host.json declares both roles. A host with report-reading and publishing tools can run the deeper tree drawn here.

The host declaration fixes the tree before any worker runs

The tree, its limits, and each child's tools are declared once in the host configuration. In the pricing project, triagereads, fixer reads, writes, and runs commands, andfixer hands tester the one tool it needs to rerun a flaky test.

Deeper delegation · tree configuration excerptjson
{
  "schema": "chio.process.host.v1",
  "limits": {
    "max_processes": 4,
    "max_depth": 2,
    "max_calls": 100
  },
  "children": [
    {
      "id": "triage",
      "parent": "root",
      "budget_share_bps": 3000,
      "tools": [
        {
          "server_id": "workspace",
          "tool_name": "read_file"
        }
      ]
    },
    {
      "id": "fixer",
      "parent": "root",
      "budget_share_bps": 3000,
      "tools": [
        {
          "server_id": "workspace",
          "tool_name": "read_file"
        },
        {
          "server_id": "workspace",
          "tool_name": "write_file"
        },
        {
          "server_id": "shell",
          "tool_name": "run_command"
        }
      ]
    },
    {
      "id": "tester",
      "parent": "fixer",
      "budget_share_bps": 1000,
      "tools": [
        {
          "server_id": "shell",
          "tool_name": "run_command"
        }
      ]
    }
  ]
}

Parents precede children in the declaration. A parent's capability must permit delegation, and each child selects specific tools from its parent's scope. A child stays within its parent's share, and siblings together stay within the parent. The journal reserves shares when children attach, including for an intermediate parent that never calls a tool itself.

A restart replaces the attempt and keeps the process

Eight identities meet in a running process. Only the process ID names the actor; the others bind it to a host, select its authority, or describe one attempt. A worker restart creates no new process and leaves the tree's budget where it stood.

IdentityOwner and lifetimeExample use
Runtime IDInitialized host lineage; kept across compatible relocationBinds independently verified process responses to this host
Process IDImmutable actor within the runtimeThe consumer process survives worker restarts
Parent and root IDsFrozen lineageDetermine ancestors, subtree cancellation, and shared quotas
Capability IDSigned authority attached to the processHost-attached; selects the narrowed grant
Worker credentialPrivate bearer connection; rotates and expiresAuthenticates one attempt without changing the process
OS PID and attemptOne executable lifetime and its recorded launchSelects logs and resource accounting
Operation keyApplication-selected logical intentreceive-order resolves its original call
Model turn and tool-call IDApplication or framework planning identitySurvives recovery when a saved model decision resumes

Keep process identity in host-owned state, out of model prompts and guest-supplied request fields. The worker protocol derives it from a private credential, and Security identity covers the surrounding caller boundary. A Rust binary and a TypeScript worker receive authority through the same process connection, and a compiled worker holds the same guest standing as any other.

Read more in Write workers in Rust or TypeScript.

Four limits count four different things

A tree can hit any of four limits, and recovery treats each by its own rule.

  1. Process count and depth. Counts tree identities. IDs are never recycled, and canceled children still count.
  2. Tree call ceiling. Counts new logical operation keys, including denied and uncertain calls. Repeating an existing key consumes no slot.
  3. Capability budget share. The signed allocation from parent to child. Cancellation does not refund a child's share automatically.
  4. Kernel budgets. Governed invocation, monetary, and other admission limits. They stay kernel-owned and apply on replay.

A leaf resumes only after its signed chain is restored from the root

Before the runtime invokes a leaf, it restores verified ancestors from the root toward that leaf. The kernel checks the original signed chain and its scope transitions, so no parent makes a dummy tool call first. Process registration cannot add a trust root or become a second issuer.

This matters when tester restarts after fixer has exited successfully: the signed chain is durable host state, independent of a live parent socket. Preserve that chain through backup and relocation, and keep its signing material outside worker mounts.

Read more in Swarm authority, which covers the signed delegation graph this host binds to working processes.

Cancel and revoke stop new work without rewriting history

Both commands act on a running tree, from the selected process down through its descendants.

report/bash
# End the worker connections; the process and its records stay
chio process revoke --state .chio --process producer

# Close the process and its subtree permanently
chio process cancel --state .chio --process producer
  1. Revoke. Removes the worker credentials of the selected process and its descendants. Identities, checkpoints, and history remain, and an operator can issue an authorized fresh connection to the same identity.
  2. Cancel. Permanently stops new admissions, checkpoints, and blob access for the selected subtree. Retained history stays readable offline.
  3. Credential expiry. Ends one connection, no later than the capability's validity. A new connection requires still-valid authority.
  4. Capability expiry. Ends the signed permission. Restarting workers or issuing credentials cannot extend it.

A call admitted before cancellation may still perform its effect; the runtime withholds its output when it observes the cancellation before return. Neither control undoes an external effect, extends a capability lifetime, or reclaims a child allocation.

To end the signed permission itself before it expires, revoke the capability while the host is stopped. The kernel records the revocation in the host's authority store and prints the revoked capability ID; every capability the producer delegated beneath it fails its next check.

report/ · host stoppedbash
chio process revoke-capability --state .chio --process producer
Output
{
  "process": "producer",
  "capability_id": "cap-01d4…8e21",
  "revoked": true
}

Every boundary refuses on disposable host state

Test each boundary in its own fresh state directory. The starter's two signed refusals are the smallest authority test; the cases below cover the rest.

  1. Give triage a write_file route its parent lacks. Attachment refuses the wider scope: initialization fails and no serving host is established.
  2. Allocate root's children 6,000 and 5,000 basis points. Sibling allocations exceed the parent. Keep the failed initialization for diagnosis and choose fresh state.
  3. Give tester more than fixer's allocation. The leaf exceeds its parent, and no child identity with broader authority is created.
  4. Call receive_jobs on the producer's connection. The kernel signs a refusal, and the original receipt carries no released output.
  5. Add a sibling selector to inspect. The worker request is invalid: the protocol has no process selector.
  6. Spend all max_calls on unique keys. The next new key is refused. Denied and uncertain calls count too, and original keys still resolve to their original calls.
  7. Cancel fixer. fixer and tester stop new admission. triage is outside that subtree, and effects admitted before the cancel are still reconciled.

For the initialization cases, change the host configuration before init; changing an already bound host is not an authority update mechanism. For call exhaustion, issue distinct disposable mailbox operations until the ceiling is reached, then repeat the first exact operation and inspect both its result and current validity. Never exhaust a production tree to test its limit.

Next: connect a worker to its process