Chio/Docs
LOGIN · JOIN

Cross-Operator Delegation

Let a partner's agents work under a grant they can narrow among themselves, and see what your kernel checks on every call.

Concept chio@5f63e6e

On this page

When you grant a partner part of a fork, its agents delegate that grant among themselves within the depth and fan-out you set, each holding no more than the one before. Each call they make against your fork is admitted at your kernel, under your policy.

The running example is the Quickstart partner: grant cap-01a9…7e40 under treaty trt-01aa…4c19, delegating up to 2 deep and 4 wide from one USD 5.00 pool.

Their agents' calls are admitted at your door

A delegated grant arrives with the call it authorizes. Your kernel checks it in order, dispatches only when every check passes, and consumes the proof's nonce at dispatch.

Possession at the doorChoose what arrives.
Their operatorYour operatoraK′Kdρtheir agenttheir kernelyour kerneltoolTheir operatorYour operatoraK′Kdρagenttheir kernelyour kerneltool

κgrantσpossessiongguardsτtreatyBbudget

The proof binds the grant to this call

Their agent presents the federated grant with a DPoP proof signed by the key the grant names. Your kernel verifies the grant, compares each of the proof's bindings with the request it received, then runs your guards, the treaty check, and your budget. The proof's nonce is consumed at dispatch, and your kernel signs the receipt. Proof of possession.

One federated call at your kernel's door: the grant and DPoP proof their agent presents, the proof's five bindings, and the checks your kernel runs under its own policy, in order. Scope runs inside the grant check. Output checks after dispatch and the durable replay profile are left out.Proof of possession

Federated grants require a DPoP proof at your door, signed by the key the grant names. A process that copied the grant signs with its own key and is refused because agent_key does not match the capability subject. After your guards, the treaty check reads the treaty scope and ladder intersection from your own store. A stale treaty is refused before budget or dispatch, with chio_treaty_stale in the receipt's chio_runtime.failure_code.

Read more in Cross-org admission.

One grant under a treaty bounds a partner's whole delegation tree

Fork the project and grant their agents a slice of the fork under the treaty.

partners.tspartners.pysrc/main.rs · in main
const fork = await project.fork();
const authority = fork.grant({
  to: partner,
  under: treaty,
  resources: { "/workspace": ["read", "write"], "/models/default": ["invoke"] },
  delegation: { depth: 2, fanout: 4 },
  budget: USD(5),   // one pool for all of their agents
  expiresIn: "30m",
});
console.log(authority.describe());
Output
grant      cap-01a9…7e40, under trt-01aa…4c19
to         partner, delegating up to 2 deep and 4 wide
on         quickstart, fork c4e81b7 of main 2f60a91
allows     /workspace         read, write
           /models/default    invoke
budget     USD 5.00 pool shared by all of their agents, charged at your door
expires    in 30 minutes

You should see the grant bound to the treaty and the delegation limits. Model calls reach your route through your kernel, which holds the pool. Revoking the treaty ends every grant issued under it, delegated ones included.

Read more in Quickstart: partners.

A delegated chain verifies against the issuers you trust

The receiving kernel checks who issued the parent capability separately from which peers it has pinned. The chain is admitted in four steps:

  1. Parent. An agent holds a capability from its operator's authority. The receiving kernel lists that authority among its trusted capability issuers; pinning the operator as a federation peer adds nothing to issuer trust.
  2. Child. The agent signs a delegated child for a worker whose subject key lives with the other operator. The child holds the same or narrower scope, lifetime, and resource limits.
  3. Verify. The receiving kernel verifies the parent against its trusted issuers, the child's signature against the parent's subject, and the stored treaty context and evidence.
  4. Admit. The action class lies inside the shared ladder intersection and its evidence verifies. Local admission and dispatch-time checks then run as for any call.

An unknown issuer fails capability validation. A federated request without its runtime treaty context fails before dispatch, even on a kernel with no runtime admission hook installed. What a receipt records along this path is on Receipts.

Where the runtime admission hook lives

The hook resolves the treaty context in admission_hook.rs and admission_hook/treaty_evidence.rs of chio-runtime-core.

A signed delegation policy caps what a partner may request

The issuing operator signs a chio.federated-delegation-policy.v1 from one default capability definition. It names the partner and its verifier and sets the parent scope and TTL ceiling every request from that partner is checked against.

Sign the delegation policytranscript
$ chio trust federated-delegation-policy-create \
    --output ./signed-delegation-policy.json \
    --signing-seed-file ./issuer.seed \
    --issuer org-a \
    --partner acme-corp \
    --verifier https://verify.acme.example \
    --capability-policy ./capability-policy.yaml \
    --expires-at 4102444800 \
    --purpose "span review for the acme incident bridge"
federated delegation policy created
output:              ./signed-delegation-policy.json
issuer:              org-a
partner:             acme-corp
verifier:            https://verify.acme.example
signer_public_key:   4cb5abf6ad79fbf5abbccafcc269d85cd2651ed4b885b5869f241aedf0a5ba29
ttl_seconds:         300
expires_at:          4102444800
exit 0
Read the signed bodytranscript
$ jq '.body' ./signed-delegation-policy.json
{
  "schema": "chio.federated-delegation-policy.v1",
  "issuer": "org-a",
  "partner": "acme-corp",
  "verifier": "https://verify.acme.example",
  "signerPublicKey": "4cb5abf6ad79fbf5abbccafcc269d85cd2651ed4b885b5869f241aedf0a5ba29",
  "createdAt": 1788589028,
  "expiresAt": 4102444800,
  "ttlSeconds": 300,
  "scope": {
    "grants": [
      {
        "server_id": "mcp-observability",
        "tool_name": "query_spans",
        "operations": [
          "invoke"
        ]
      }
    ]
  },
  "purpose": "span review for the acme incident bridge"
}
exit 0

You should see a 300-second TTL and a scope of one grant, invoke on query_spans of mcp-observability. The protocol specification lists this policy among the federation artifacts in section 10.2.

A policy that expires before its creation is refused before signing

An expiry before the creation time stops the command before anything is signed, with exit 1.

An expiry in the pasttranscript
$ chio trust federated-delegation-policy-create \
    --output ./stale.json \
    --signing-seed-file ./issuer.seed \
    --issuer org-a \
    --partner acme-corp \
    --verifier https://verify.acme.example \
    --capability-policy ./capability-policy.yaml \
    --expires-at 1776302557
error[CHIO-DELEGATION-POLICY-WINDOW-INVALID]: the federated delegation policy would expire before it is created
  help: pass an --expires-at later than the current time, in Unix seconds
  code: urn:chio:error:delegation:policy-window-invalid
  docs: https://chio.computer/docs/reference/errors#error-delegation-policy-window-invalid
exit 1

An imported capability can parent a local delegation

chio trust federated-issue --upstream-capability-id issues a local child whose parent is a capability imported from the other operator. It first verifies a challenge-bound passport presentation, as shown on Passports.

The child in the lineage exporttranscript
$ jq 'del(.signed_capability)' \
    evidence-export-package/capability-lineage.ndjson
{
  "capability_id": "cap-ioa-web3-provider",
  "subject_key": "bff663535a5cf58658cc38595d20dc4501f6dfc076ddf07e20571d413a3ceb5a",
  "issuer_key": "a090e1a43efcd3a3bd5ea5b015e6014d20e33e0e2d480194802720e4d38f108b",
  "issued_at": 1776995579,
  "expires_at": 1776996779,
  "grants_json": "{\"grants\":[{\"constraints\":[],\"operations\":[\"invoke\"],\"server_id\":\"provider-review\",\"tool_name\":\"inspect_service_order\"},{\"constraints\":[],\"operations\":[\"invoke\"],\"server_id\":\"provider-review\",\"tool_name\":\"evaluate_provider_reputation\"},{\"constraints\":[],\"operations\":[\"invoke\"],\"server_id\":\"provider-review\",\"tool_name\":\"issue_review_attestation\"}],\"prompt_grants\":[],\"resource_grants\":[]}",
  "delegation_depth": 1,
  "parent_capability_id": "cap-019dbd30-b376-7b92-ba54-d00aec973369"
}
exit 0

You should see delegation_depth 1 and the imported parent in parent_capability_id. Revoking that parent stops further use of the child and leaves the child's recorded history as it was:

Revoke the imported parenttranscript
$ chio --revocation-db ./revocations.sqlite3 \
    trust revoke --capability-id cap-019dbd30-b376-7b92-ba54-d00aec973369
capability_id: cap-019dbd30-b376-7b92-ba54-d00aec973369
revoked:       true
newly_revoked: true
backend:       ./revocations.sqlite3
exit 0

Read more in the CLI reference.

Swarm defines how authority narrows at each hop

Federation sets what the relationship permits. How a grant narrows at each hop of a task graph, and how a continuation binds a child to its route, allocation, and revocation epoch, is the Swarm model.

Read more in Swarm Authority and Continuation Tokens.

Next: share the evidence both sides verify

Cross-Operator Delegation · Chio Docs