{
  "schemaVersion": "1.0",
  "title": "Delegation",
  "description": "Use this page to understand how one AIP participant asks another participant to execute a child action. It is for application, runtime, and gateway developers who need to preserve a parent-child graph, choose local or remote execution, and ",
  "canonical": "https://getaip.org/docs/concepts/delegation",
  "route": "/docs/concepts/delegation",
  "source": "docs/concepts/delegation.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Core Concepts",
  "documentType": "Concept",
  "language": "en",
  "revision": {
    "lastReviewedRevision": "97be86e9efedf07ecf1783b03800f683f107fb04",
    "documentationSourceRevision": "9192fef3695ad294994f2712f6d156241e5e92fb",
    "basis": "frontmatter"
  },
  "downloads": {
    "md": "/docs/download/concepts/delegation.md",
    "txt": "/docs/download/concepts/delegation.txt",
    "json": "/docs/download/concepts/delegation.json",
    "pdf": "/docs/download/concepts/delegation.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Delegation\ndescription: Understand AIP child-action delegation, authenticated peer routing, and recovery boundaries\nkind: explanation\naudience: developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\n---\n\n# Delegation\n\nUse this page to understand how one AIP participant asks another participant to\nexecute a child action. It is for application, runtime, and gateway developers\nwho need to preserve a parent-child graph, choose local or remote execution, and\nsettle the result without treating a connector call as agent delegation.\n\nDelegation is a first-class AIP graph edge. The request names a parent action,\ncontains a complete child action, and identifies both the requester and the\ndelegate. The child still passes through the ordinary capability, policy,\napproval, transaction, idempotency, and result lifecycle. A delegation does not\ntransfer unlimited authority, make remote delivery exactly once, or turn a\nhuman-readable scope into an authenticated grant.\n\nThis page describes the reviewed Rust implementation of AIP 1.0 at source\nrevision `97be86e9efedf07ecf1783b03800f683f107fb04`. Durability and remote reach\ndepend on the stores, routes, peer keys, and transports configured by a\ndeployment.\n\n## Start with the graph edge\n\nKeep the parent action, child action, and delegation edge separate. Each has a\nstable identity and a different job.\n\n| Identity | What it names | What it does not prove |\n|---|---|---|\n| Parent action ID | The action named as the parent of this edge | That the record exists, is owned by the requester, or can cancel the child |\n| Child action ID | The independently executed action | That the action was accepted by the intended delegate |\n| Delegation ID | The durable edge between parent and child | Exactly-once delivery or successful execution |\n| Requester principal | The participant creating the edge | Authority merely because the value appears in the payload |\n| Delegate principal | The participant expected to execute the child | Possession of a peer key or permission for the capability |\n| Correlation ID | The surrounding request relationship | Ownership of either action |\n\nThe runtime persists a `DelegationRecord` containing the effective request,\ncurrent delegation status, optional result, and creation and update times. It\ncan also index records by parent action and child action. These indexes make the\ngraph observable inside the runtime; they do not create a public delegation\nquery message in the reviewed protocol surface.\n\n```mermaid\nflowchart LR\n    P[\"Parent action\"] --> Q[\"DelegationRequest\"]\n    Q --> G[\"Durable graph edge\"]\n    G --> D{\"Registered peer route?\"}\n    D -->|\"No\"| L[\"Execute child locally as delegate\"]\n    D -->|\"Yes\"| O[\"Durable remote outbox\"]\n    O --> R[\"Authenticated AIP peer\"]\n    L --> A[\"Child ActionResult\"]\n    R --> B[\"Correlated DelegationResult\"]\n    A --> S[\"Settle delegation record\"]\n    B --> S\n    S --> E[\"Event, receipt chain, and optional callback\"]\n```\n\nThe text equivalent has five steps. Admit one request, bind it to a durable\ngraph edge, choose local execution or a registered peer route, and execute the\nchild. Settle the same delegation ID with a correlated result.\n\n## The wire contract carries a complete child action\n\nA `DelegationRequest` contains:\n\n| Field | Role in the graph |\n|---|---|\n| `delegation_id` | Stable identity for this parent-child edge |\n| `parent_action_id` | Action named as the parent of the edge |\n| `child_action` | Complete action to execute, including its own ID and capability |\n| `requested_by` | Principal creating the delegation |\n| `delegate` | Principal expected to execute the child |\n| `scope` | Non-empty description retained on the request and delegation hop |\n| `callback` | Optional destination for a final delegation result |\n| `metadata` | Optional routing, scheduling, or product-specific data |\n\nThe core envelope validator rejects an empty `scope`, equal parent and child\naction IDs, or an invalid child action. The child action's existing\n`delegation_chain` may contain at most ten entries when that action passes core\nenvelope validation.\n\nThe reviewed generic runtime does not look up the named parent action or prove\nthat `requested_by` owns it while admitting this request. An ingress or\nworkflow that requires an existing, requester-owned parent must enforce that\nrelationship before calling the delegation path.\n\nA `DelegationResult` repeats the delegation, parent, and child IDs. It carries\none of six statuses:\n\n| Status | Meaning in the model | Reviewed runtime behavior |\n|---|---|---|\n| `accepted` | The delegation was admitted but has not started | Available on the wire; a new local record is stored as `running` |\n| `running` | Child work is still in progress | Returned immediately for a locally scheduled asynchronous child and allowed from a remote peer |\n| `completed` | Child work completed | Terminal |\n| `failed` | Scheduling or child execution failed | Terminal |\n| `cancelled` | The child reached a cancelled result | Terminal; it does not imply parent-driven cascade |\n| `requires_human` | The child needs approval or human input | Terminal for the delegation lifecycle at this revision |\n\nA terminal delegation result must include at least one of `ActionResult` or\n`ProtocolError`; it may contain both. When local execution reaches the child\naction lifecycle, the runtime maps the child's result status to the delegation\nstatus and includes the child result.\n\nA failure that prevents a retryable\nremote dispatch from ever settling remains an outbox concern until delivery\nsucceeds, becomes a permanent failure result, or reaches dead letter.\n\n## Path validation protects graph shape\n\nFor a new edge, the runtime appends a `DelegationEntry` to the child action\nunless the exact current hop is already the last entry. Each entry records\n`from`, `to`, `scope`, and `delegated_at`.\n\nBefore accepting the path, the reviewed runtime checks that:\n\n- the requester does not delegate to itself;\n- every earlier scope is non-empty;\n- no hop delegates a principal to itself;\n- each hop starts where the previous hop ended;\n- the chain ends at the current requester;\n- a principal does not appear twice in a cycle; and\n- the new target is absent from the earlier path.\n\nThe runtime accepts an exact replay of a stored request. It also normalizes the\ntwo fields that it may add itself—the current hop and a copied callback—before\ndeciding whether a retry is the same request.\n\nReusing a delegation ID for a\ndifferent parent, child, requester, delegate, scope, callback, or metadata is an\nauthorization conflict. A previously stored terminal result is returned for a\nmatching replay.\n\nThe numeric hop limit and the path checks are related but distinct. The core\nwire validator limits the incoming child action's existing chain to ten\nentries.\n\nThe direct runtime path validator has no separate numeric limit, and\nthe reviewed code does not repeat the length check after appending a missing\ncurrent hop. Embedders that call the runtime without validated AIP envelopes\nneed to enforce their intended bound at that boundary.\n\n## Scope records intent; policy grants authority\n\nThe `scope` field is a non-empty string. The runtime copies it into the\ndelegation chain, event data, and `DelegationMade` receipt. It compares the\nstring when recognizing an already-recorded current hop.\n\nThe reviewed generic delegation path does not parse that string, compare it\nwith the requester's authenticated grants, prove that each hop narrows\nauthority, or add it to the delegate's authenticated scopes. Treat it as an\nauditable statement of delegated purpose, not as the authorization decision.\n\nThe child action still enters ordinary action processing. The selected\ncapability contract, resolved identity, policy decision, required approval,\ntransaction mode, credential context, and connector handler govern what can\nactually execute. Deployments that require scope narrowing need an explicit\npolicy vocabulary and enforcement point in addition to the delegation string.\n\n`FederationContext` similarly carries a current `trust_domain` and a list of\ndomain `hops` on an action. The reviewed generic delegation validator does not\nupdate or evaluate those fields. A label can preserve routing context for\ndeployment policy, but it does not establish transitive trust or cross-domain\nauthorization by itself.\n\n## Local delegation changes execution identity deliberately\n\nWhen no registered router owns the request, the runtime executes the child\nlocally. Before doing so, it requires transport-established authentication for\nthe requester and matches both the authenticated principal ID and kind to\n`requested_by`. It also requires the runtime-verified current hop to end at the\ndeclared delegate.\n\nThe runtime then constructs a child execution context with:\n\n- the delegate as the current actor and service account;\n- the requester as `acted_on_behalf_of`;\n- the existing resolved identity context otherwise preserved;\n- an internal authenticated-principal projection for the delegate;\n- an issuer derived from the requester's authenticated issuer;\n- the requester's expiry and credential fingerprint; and\n- an empty authenticated scope set.\n\nThis projection gives ordinary action processing a precise principal and\non-behalf-of relationship. It is not evidence that the delegate presented a\nnew external credential at this local boundary, and it does not copy the\nfree-form delegation scope into authenticated grants.\n\nSynchronous and streaming child actions execute on the request path. A local\nasynchronous child returns a `running` delegation result, records a receipt\nchain, and continues in a spawned task. A configured persistent backend can\nretain the running record for recovery; the default in-memory stores do not\nturn process memory into durable storage.\n\n## Remote delegation uses an explicit peer route\n\nA gateway delegation route can select by delegate principal ID, child\ncapability ID, or both. A route with both selectors matches only when both\nmatch; a route with neither selector is a catch-all. The gateway uses the first\nmatching explicit route before consulting extension routers, so overlapping\nroutes require deliberate registration order.\n\nThe selected binding sends the first-class `DelegationRequest` over native HTTP\nor native NATS request/reply. If no peer route or extension router owns the\nrequest, the gateway accepts local execution only when the delegate matches its\nown manifest agent; otherwise it returns `delegation.target_mismatch`.\n\nNative peer security is configured per route. It contains a non-empty trust\ndomain, a local request signer, the expected peer principal, an exact expected\npeer `did:key`, an optional opaque credential handle, a transport retry budget,\nand an endpoint policy. The request is signed and carries the configured trust\ndomain. The peer response is accepted only after the gateway verifies:\n\n- the exact expected DID and envelope signature;\n- the expected peer principal as sender;\n- the local request signer as recipient;\n- the request correlation ID;\n- an `in_response_to` reference to the exact request message; and\n- a response timestamp within five minutes of the verifier's current time.\n\nThe body must be a `DelegationResult` whose delegation, parent, and child IDs\nmatch the request, or a protocol error. Native HTTP also applies the configured\nURL, DNS, redirect, TLS, timeout, and response-size policy. These checks\nauthenticate one configured peer exchange. They do not make every principal in\nan earlier delegation chain trusted by the current gateway.\n\n## The remote outbox makes retries explicit\n\nThe runtime asks `can_route` before creating a remote outbox item, so route\nownership must be deterministic for a stable route table. A new outbox record\nretains the request and trusted message context, but not secret credential\nmaterial; a `CredentialHandle` is only an opaque reference.\n\nThe dispatch states are `pending`, `leased`, `delivered`, and `dead_lettered`.\nOne worker acquires a time-bounded lease with a fencing token and renews it\nduring the peer call. A successful correlated result is stored with the\ndelivered record and returned on replay. Losing the lease blocks stale\nsettlement.\n\nThe reviewed runtime creates each outbox item with five total lease attempts.\nRetry scheduling uses exponential backoff starting at 250 milliseconds and\ncapped at 30 seconds.\n\nA route that declines a request it claimed to own is\ntreated as a retryable dispatch error. An error explicitly marked\nnon-retryable becomes a terminal failed delegation result; other dispatch\nerrors return the record to pending until the attempt budget is exhausted.\n\nNative HTTP has its own route-level retry budget, two retries after the initial\nattempt by default. Those transport attempts can occur within one durable\noutbox lease.\n\nThe gateway sends the delegation ID as the HTTP idempotency key, but network\nfailure can still leave the sender unable to know whether the peer received a\nrequest. Remote peers therefore need idempotent handling of the stable\ndelegation ID and, for side-effecting child work, the child action's own\nidempotency contract.\n\nRecovery scans delegation records in `accepted` or `running` state. It reuses\nthe remote outbox when a router still owns the request and otherwise re-enters\nlocal child execution. Recovery is a replay mechanism, not exactly-once proof.\nPersistent stores, stable routes, child idempotency, and operator handling of\ndead letters remain deployment responsibilities.\n\n## Results, streams, receipts, callbacks, and cancellation\n\nRemote result ingestion binds an update to the stored graph and to the\ntransport-established delegate principal. If an embedded `ActionResult` is\npresent, its action ID must match the child ID. Replaying the same terminal\nresult is idempotent; a different result cannot replace a terminal record.\n\nRemote stream chunks are accepted only for a child already present in the\ndelegation graph, from the expected delegate, and before terminal delegation\nsettlement. The runtime annotates stream events with the delegation and parent\nIDs. A stream chunk remains progress evidence; the final delegation result is\nthe settlement authority.\n\nThe reviewed runtime attaches a receipt chain if the result does not already\ncarry one. Its locally constructed chain contains a `DelegationMade` receipt\nwith the graph IDs, delegate, scope, actor, time, and correlation. That receipt\nrecords creation of the edge; it is not by itself proof of the external effect\nperformed by the child.\n\nAn optional request callback can receive a terminal `DelegationResult` on the\nruntime paths that own terminal callback dispatch. For a new request, the\nruntime also copies that callback to the child action when the child has none.\n\nChild lifecycle paths can then use it for outputs such as stream chunks or a\nqueued approval continuation. Callback delivery has its own durable retry and\nsecurity policy; consumers must select behavior by message type and stable IDs\nrather than assuming that every callback is the final delegation result.\n\n`cancelled` is a valid terminal delegation status, normally derived from a\ncancelled child result or accepted from the authenticated remote delegate. The\nreviewed runtime does not walk from a cancelled parent through its delegation\nchildren and issue cancellation automatically. Workflow code that needs\ncascade cancellation must address active child action IDs explicitly, observe\ntheir terminal results, and handle remote or provider uncertainty separately.\n\n## Peer delegation is not connector-fleet routing\n\nBoth paths may cross a process boundary, but they represent different work.\n\n| Question | Peer delegation | Connector-fleet routing |\n|---|---|---|\n| Protocol unit | `DelegationRequest` containing a child action | Ordinary `Action` execution |\n| Semantic result | New durable parent-child graph edge and `DelegationResult` | `ActionResult` for the same action |\n| Target selection | Delegate principal and/or child capability in an explicit peer route | Registered connector instance and replica for the action's tenant and capability |\n| Trust binding | Expected peer principal, exact peer DID, signed request and correlated response | Registry state, instance and replica identity, active lease, route assignment, and fencing evidence |\n| Retry record | Delegation outbox keyed by delegation ID | Action lifecycle plus an action-scoped connector route assignment |\n| Primary purpose | Ask another AIP participant to own a child action | Invoke an external product through a connector host |\n\nRegistering a connector instance does not automatically create a delegation\nroute. An implementation can explicitly provide both roles, but the runtime\ncontracts remain separate. Do not invent a delegation edge merely because a\ncentral runtime dispatched an action to a remote connector replica.\n\n## Trust and data boundaries\n\n- Payload requester, delegate, scope, chain, federation labels, metadata, and\n  callback values are claims until the appropriate ingress and policy establish\n  their authority.\n- Local child execution requires a transport-established requester and a\n  runtime-verified terminal hop. Remote execution additionally requires the\n  configured peer key, principal, response correlation, and graph IDs.\n- A delegation scope records intent but does not grant a capability, tenant,\n  object, provider account, credential, or approval.\n- A route trust domain is administrative context, not transitive trust in every\n  earlier or later domain.\n- The complete child action and optional metadata cross the peer boundary.\n  Deployments must minimize or redact sensitive context before routing it.\n- Opaque credential handles may be retained for recovery; secret material must\n  remain behind the credential provider and transport boundary.\n- A receipt chain can prove the data actually included in its receipts. It does\n  not prove an unstated provider outcome.\n- Persistent graph and outbox state can contain identity and business context;\n  retention, tenant isolation, read authorization, and redaction remain\n  deployment responsibilities.\n\n## Design choices and trade-offs\n\nEmbedding a complete child action makes delegation transport-independent and\nlets the child use the normal AIP lifecycle. It also means the delegating side\nmust choose a new action identity, minimize the payload, and preserve both\naction and delegation idempotency.\n\nKeeping local and remote execution behind one `DelegationRouter` decision gives\napplications one semantic graph model. Deterministic route ownership becomes a\nhard requirement: a route-table change during recovery can move a running edge\nbetween remote and local paths unless deployment policy prevents it.\n\nSeparating the free-form scope from authenticated scopes avoids pretending that\none string is a universal authorization language. The cost is that deployments\nrequiring formal attenuation must define and enforce it explicitly.\n\nA leased durable outbox prevents concurrent workers from settling the same\ndispatch and preserves a terminal replay. It cannot eliminate duplicate peer\nreceipt across network uncertainty, so stable IDs and idempotent child behavior\nremain necessary.\n\nTreating `requires_human` as terminal gives the parent a clear result at the\ncurrent delegation edge. The reviewed delegation record does not remain open\nwaiting for a later approval; workflow code must decide explicitly how to\ncontinue.\n\n## What delegation does not guarantee\n\n- A delegation ID does not make remote delivery or a provider side effect\n  exactly once.\n- A named parent action ID does not prove that the parent exists or belongs to\n  the requester.\n- A non-empty `scope` does not prove authority, attenuation, or authenticated\n  scopes.\n- A contiguous delegation chain does not authenticate every historical hop.\n- A federation trust-domain label does not create transitive trust.\n- The ten-entry wire validation limit is not a second limit inside the direct\n  runtime path after it appends a hop.\n- A `running` result does not prove that a remote peer or child handler has\n  started work.\n- A `DelegationMade` receipt does not prove child completion or an external\n  provider effect.\n- Cancelling a parent does not automatically cancel its delegated children.\n- Registering a connector instance does not register an AIP peer-delegation\n  route.\n- The reviewed message set does not expose a public delegation query or list\n  request.\n- This page does not claim live peer connectivity, connector qualification, or\n  product coverage beyond the separately documented Cal.diy, Hermes Agent,\n  Chatwoot, Dify, CrewAI, and Twenty connectors.\n\n## Related pages\n\n- [Actions and sessions](actions-and-sessions.md)\n- [Capabilities and contracts](capabilities.md)\n- [Identity and trust](identity-and-trust.md)\n- [Transactions and compensation](transactions-and-compensation.md)\n- [Profiles and connectors](profiles-and-connectors.md)\n",
    "text": "Delegation\n\nUse this page to understand how one AIP participant asks another participant to\nexecute a child action. It is for application, runtime, and gateway developers\nwho need to preserve a parent-child graph, choose local or remote execution, and\nsettle the result without treating a connector call as agent delegation.\n\nDelegation is a first-class AIP graph edge. The request names a parent action,\ncontains a complete child action, and identifies both the requester and the\ndelegate. The child still passes through the ordinary capability, policy,\napproval, transaction, idempotency, and result lifecycle. A delegation does not\ntransfer unlimited authority, make remote delivery exactly once, or turn a\nhuman-readable scope into an authenticated grant.\n\nThis page describes the reviewed Rust implementation of AIP 1.0 at source\nrevision 97be86e9efedf07ecf1783b03800f683f107fb04. Durability and remote reach\ndepend on the stores, routes, peer keys, and transports configured by a\ndeployment.\n\nStart with the graph edge\n\nKeep the parent action, child action, and delegation edge separate. Each has a\nstable identity and a different job.\n\n| Identity | What it names | What it does not prove |\n\n| Parent action ID | The action named as the parent of this edge | That the record exists, is owned by the requester, or can cancel the child |\n| Child action ID | The independently executed action | That the action was accepted by the intended delegate |\n| Delegation ID | The durable edge between parent and child | Exactly-once delivery or successful execution |\n| Requester principal | The participant creating the edge | Authority merely because the value appears in the payload |\n| Delegate principal | The participant expected to execute the child | Possession of a peer key or permission for the capability |\n| Correlation ID | The surrounding request relationship | Ownership of either action |\n\nThe runtime persists a DelegationRecord containing the effective request,\ncurrent delegation status, optional result, and creation and update times. It\ncan also index records by parent action and child action. These indexes make the\ngraph observable inside the runtime; they do not create a public delegation\nquery message in the reviewed protocol surface.\n\nflowchart LR\n    P[\"Parent action\"] --> Q[\"DelegationRequest\"]\n    Q --> G[\"Durable graph edge\"]\n    G --> D{\"Registered peer route?\"}\n    D -->|\"No\"| L[\"Execute child locally as delegate\"]\n    D -->|\"Yes\"| O[\"Durable remote outbox\"]\n    O --> R[\"Authenticated AIP peer\"]\n    L --> A[\"Child ActionResult\"]\n    R --> B[\"Correlated DelegationResult\"]\n    A --> S[\"Settle delegation record\"]\n    B --> S\n    S --> E[\"Event, receipt chain, and optional callback\"]\n\nThe text equivalent has five steps. Admit one request, bind it to a durable\ngraph edge, choose local execution or a registered peer route, and execute the\nchild. Settle the same delegation ID with a correlated result.\n\nThe wire contract carries a complete child action\n\nA DelegationRequest contains:\n\n| Field | Role in the graph |\n\n| delegationid | Stable identity for this parent-child edge |\n| parentactionid | Action named as the parent of the edge |\n| childaction | Complete action to execute, including its own ID and capability |\n| requestedby | Principal creating the delegation |\n| delegate | Principal expected to execute the child |\n| scope | Non-empty description retained on the request and delegation hop |\n| callback | Optional destination for a final delegation result |\n| metadata | Optional routing, scheduling, or product-specific data |\n\nThe core envelope validator rejects an empty scope, equal parent and child\naction IDs, or an invalid child action. The child action's existing\ndelegationchain may contain at most ten entries when that action passes core\nenvelope validation.\n\nThe reviewed generic runtime does not look up the named parent action or prove\nthat requestedby owns it while admitting this request. An ingress or\nworkflow that requires an existing, requester-owned parent must enforce that\nrelationship before calling the delegation path.\n\nA DelegationResult repeats the delegation, parent, and child IDs. It carries\none of six statuses:\n\n| Status | Meaning in the model | Reviewed runtime behavior |\n\n| accepted | The delegation was admitted but has not started | Available on the wire; a new local record is stored as running |\n| running | Child work is still in progress | Returned immediately for a locally scheduled asynchronous child and allowed from a remote peer |\n| completed | Child work completed | Terminal |\n| failed | Scheduling or child execution failed | Terminal |\n| cancelled | The child reached a cancelled result | Terminal; it does not imply parent-driven cascade |\n| requireshuman | The child needs approval or human input | Terminal for the delegation lifecycle at this revision |\n\nA terminal delegation result must include at least one of ActionResult or\nProtocolError; it may contain both. When local execution reaches the child\naction lifecycle, the runtime maps the child's result status to the delegation\nstatus and includes the child result.\n\nA failure that prevents a retryable\nremote dispatch from ever settling remains an outbox concern until delivery\nsucceeds, becomes a permanent failure result, or reaches dead letter.\n\nPath validation protects graph shape\n\nFor a new edge, the runtime appends a DelegationEntry to the child action\nunless the exact current hop is already the last entry. Each entry records\nfrom, to, scope, and delegatedat.\n\nBefore accepting the path, the reviewed runtime checks that:\n• the requester does not delegate to itself;\n• every earlier scope is non-empty;\n• no hop delegates a principal to itself;\n• each hop starts where the previous hop ended;\n• the chain ends at the current requester;\n• a principal does not appear twice in a cycle; and\n• the new target is absent from the earlier path.\n\nThe runtime accepts an exact replay of a stored request. It also normalizes the\ntwo fields that it may add itself—the current hop and a copied callback—before\ndeciding whether a retry is the same request.\n\nReusing a delegation ID for a\ndifferent parent, child, requester, delegate, scope, callback, or metadata is an\nauthorization conflict. A previously stored terminal result is returned for a\nmatching replay.\n\nThe numeric hop limit and the path checks are related but distinct. The core\nwire validator limits the incoming child action's existing chain to ten\nentries.\n\nThe direct runtime path validator has no separate numeric limit, and\nthe reviewed code does not repeat the length check after appending a missing\ncurrent hop. Embedders that call the runtime without validated AIP envelopes\nneed to enforce their intended bound at that boundary.\n\nScope records intent; policy grants authority\n\nThe scope field is a non-empty string. The runtime copies it into the\ndelegation chain, event data, and DelegationMade receipt. It compares the\nstring when recognizing an already-recorded current hop.\n\nThe reviewed generic delegation path does not parse that string, compare it\nwith the requester's authenticated grants, prove that each hop narrows\nauthority, or add it to the delegate's authenticated scopes. Treat it as an\nauditable statement of delegated purpose, not as the authorization decision.\n\nThe child action still enters ordinary action processing. The selected\ncapability contract, resolved identity, policy decision, required approval,\ntransaction mode, credential context, and connector handler govern what can\nactually execute. Deployments that require scope narrowing need an explicit\npolicy vocabulary and enforcement point in addition to the delegation string.\n\nFederationContext similarly carries a current trustdomain and a list of\ndomain hops on an action. The reviewed generic delegation validator does not\nupdate or evaluate those fields. A label can preserve routing context for\ndeployment policy, but it does not establish transitive trust or cross-domain\nauthorization by itself.\n\nLocal delegation changes execution identity deliberately\n\nWhen no registered router owns the request, the runtime executes the child\nlocally. Before doing so, it requires transport-established authentication for\nthe requester and matches both the authenticated principal ID and kind to\nrequestedby. It also requires the runtime-verified current hop to end at the\ndeclared delegate.\n\nThe runtime then constructs a child execution context with:\n• the delegate as the current actor and service account;\n• the requester as actedonbehalfof;\n• the existing resolved identity context otherwise preserved;\n• an internal authenticated-principal projection for the delegate;\n• an issuer derived from the requester's authenticated issuer;\n• the requester's expiry and credential fingerprint; and\n• an empty authenticated scope set.\n\nThis projection gives ordinary action processing a precise principal and\non-behalf-of relationship. It is not evidence that the delegate presented a\nnew external credential at this local boundary, and it does not copy the\nfree-form delegation scope into authenticated grants.\n\nSynchronous and streaming child actions execute on the request path. A local\nasynchronous child returns a running delegation result, records a receipt\nchain, and continues in a spawned task. A configured persistent backend can\nretain the running record for recovery; the default in-memory stores do not\nturn process memory into durable storage.\n\nRemote delegation uses an explicit peer route\n\nA gateway delegation route can select by delegate principal ID, child\ncapability ID, or both. A route with both selectors matches only when both\nmatch; a route with neither selector is a catch-all. The gateway uses the first\nmatching explicit route before consulting extension routers, so overlapping\nroutes require deliberate registration order.\n\nThe selected binding sends the first-class DelegationRequest over native HTTP\nor native NATS request/reply. If no peer route or extension router owns the\nrequest, the gateway accepts local execution only when the delegate matches its\nown manifest agent; otherwise it returns delegation.targetmismatch.\n\nNative peer security is configured per route. It contains a non-empty trust\ndomain, a local request signer, the expected peer principal, an exact expected\npeer did:key, an optional opaque credential handle, a transport retry budget,\nand an endpoint policy. The request is signed and carries the configured trust\ndomain. The peer response is accepted only after the gateway verifies:\n• the exact expected DID and envelope signature;\n• the expected peer principal as sender;\n• the local request signer as recipient;\n• the request correlation ID;\n• an inresponseto reference to the exact request message; and\n• a response timestamp within five minutes of the verifier's current time.\n\nThe body must be a DelegationResult whose delegation, parent, and child IDs\nmatch the request, or a protocol error. Native HTTP also applies the configured\nURL, DNS, redirect, TLS, timeout, and response-size policy. These checks\nauthenticate one configured peer exchange. They do not make every principal in\nan earlier delegation chain trusted by the current gateway.\n\nThe remote outbox makes retries explicit\n\nThe runtime asks canroute before creating a remote outbox item, so route\nownership must be deterministic for a stable route table. A new outbox record\nretains the request and trusted message context, but not secret credential\nmaterial; a CredentialHandle is only an opaque reference.\n\nThe dispatch states are pending, leased, delivered, and deadlettered.\nOne worker acquires a time-bounded lease with a fencing token and renews it\nduring the peer call. A successful correlated result is stored with the\ndelivered record and returned on replay. Losing the lease blocks stale\nsettlement.\n\nThe reviewed runtime creates each outbox item with five total lease attempts.\nRetry scheduling uses exponential backoff starting at 250 milliseconds and\ncapped at 30 seconds.\n\nA route that declines a request it claimed to own is\ntreated as a retryable dispatch error. An error explicitly marked\nnon-retryable becomes a terminal failed delegation result; other dispatch\nerrors return the record to pending until the attempt budget is exhausted.\n\nNative HTTP has its own route-level retry budget, two retries after the initial\nattempt by default. Those transport attempts can occur within one durable\noutbox lease.\n\nThe gateway sends the delegation ID as the HTTP idempotency key, but network\nfailure can still leave the sender unable to know whether the peer received a\nrequest. Remote peers therefore need idempotent handling of the stable\ndelegation ID and, for side-effecting child work, the child action's own\nidempotency contract.\n\nRecovery scans delegation records in accepted or running state. It reuses\nthe remote outbox when a router still owns the request and otherwise re-enters\nlocal child execution. Recovery is a replay mechanism, not exactly-once proof.\nPersistent stores, stable routes, child idempotency, and operator handling of\ndead letters remain deployment responsibilities.\n\nResults, streams, receipts, callbacks, and cancellation\n\nRemote result ingestion binds an update to the stored graph and to the\ntransport-established delegate principal. If an embedded ActionResult is\npresent, its action ID must match the child ID. Replaying the same terminal\nresult is idempotent; a different result cannot replace a terminal record.\n\nRemote stream chunks are accepted only for a child already present in the\ndelegation graph, from the expected delegate, and before terminal delegation\nsettlement. The runtime annotates stream events with the delegation and parent\nIDs. A stream chunk remains progress evidence; the final delegation result is\nthe settlement authority.\n\nThe reviewed runtime attaches a receipt chain if the result does not already\ncarry one. Its locally constructed chain contains a DelegationMade receipt\nwith the graph IDs, delegate, scope, actor, time, and correlation. That receipt\nrecords creation of the edge; it is not by itself proof of the external effect\nperformed by the child.\n\nAn optional request callback can receive a terminal DelegationResult on the\nruntime paths that own terminal callback dispatch. For a new request, the\nruntime also copies that callback to the child action when the child has none.\n\nChild lifecycle paths can then use it for outputs such as stream chunks or a\nqueued approval continuation. Callback delivery has its own durable retry and\nsecurity policy; consumers must select behavior by message type and stable IDs\nrather than assuming that every callback is the final delegation result.\n\ncancelled is a valid terminal delegation status, normally derived from a\ncancelled child result or accepted from the authenticated remote delegate. The\nreviewed runtime does not walk from a cancelled parent through its delegation\nchildren and issue cancellation automatically. Workflow code that needs\ncascade cancellation must address active child action IDs explicitly, observe\ntheir terminal results, and handle remote or provider uncertainty separately.\n\nPeer delegation is not connector-fleet routing\n\nBoth paths may cross a process boundary, but they represent different work.\n\n| Question | Peer delegation | Connector-fleet routing |\n\n| Protocol unit | DelegationRequest containing a child action | Ordinary Action execution |\n| Semantic result | New durable parent-child graph edge and DelegationResult | ActionResult for the same action |\n| Target selection | Delegate principal and/or child capability in an explicit peer route | Registered connector instance and replica for the action's tenant and capability |\n| Trust binding | Expected peer principal, exact peer DID, signed request and correlated response | Registry state, instance and replica identity, active lease, route assignment, and fencing evidence |\n| Retry record | Delegation outbox keyed by delegation ID | Action lifecycle plus an action-scoped connector route assignment |\n| Primary purpose | Ask another AIP participant to own a child action | Invoke an external product through a connector host |\n\nRegistering a connector instance does not automatically create a delegation\nroute. An implementation can explicitly provide both roles, but the runtime\ncontracts remain separate. Do not invent a delegation edge merely because a\ncentral runtime dispatched an action to a remote connector replica.\n\nTrust and data boundaries\n• Payload requester, delegate, scope, chain, federation labels, metadata, and\n  callback values are claims until the appropriate ingress and policy establish\n  their authority.\n• Local child execution requires a transport-established requester and a\n  runtime-verified terminal hop. Remote execution additionally requires the\n  configured peer key, principal, response correlation, and graph IDs.\n• A delegation scope records intent but does not grant a capability, tenant,\n  object, provider account, credential, or approval.\n• A route trust domain is administrative context, not transitive trust in every\n  earlier or later domain.\n• The complete child action and optional metadata cross the peer boundary.\n  Deployments must minimize or redact sensitive context before routing it.\n• Opaque credential handles may be retained for recovery; secret material must\n  remain behind the credential provider and transport boundary.\n• A receipt chain can prove the data actually included in its receipts. It does\n  not prove an unstated provider outcome.\n• Persistent graph and outbox state can contain identity and business context;\n  retention, tenant isolation, read authorization, and redaction remain\n  deployment responsibilities.\n\nDesign choices and trade-offs\n\nEmbedding a complete child action makes delegation transport-independent and\nlets the child use the normal AIP lifecycle. It also means the delegating side\nmust choose a new action identity, minimize the payload, and preserve both\naction and delegation idempotency.\n\nKeeping local and remote execution behind one DelegationRouter decision gives\napplications one semantic graph model. Deterministic route ownership becomes a\nhard requirement: a route-table change during recovery can move a running edge\nbetween remote and local paths unless deployment policy prevents it.\n\nSeparating the free-form scope from authenticated scopes avoids pretending that\none string is a universal authorization language. The cost is that deployments\nrequiring formal attenuation must define and enforce it explicitly.\n\nA leased durable outbox prevents concurrent workers from settling the same\ndispatch and preserves a terminal replay. It cannot eliminate duplicate peer\nreceipt across network uncertainty, so stable IDs and idempotent child behavior\nremain necessary.\n\nTreating requireshuman as terminal gives the parent a clear result at the\ncurrent delegation edge. The reviewed delegation record does not remain open\nwaiting for a later approval; workflow code must decide explicitly how to\ncontinue.\n\nWhat delegation does not guarantee\n• A delegation ID does not make remote delivery or a provider side effect\n  exactly once.\n• A named parent action ID does not prove that the parent exists or belongs to\n  the requester.\n• A non-empty scope does not prove authority, attenuation, or authenticated\n  scopes.\n• A contiguous delegation chain does not authenticate every historical hop.\n• A federation trust-domain label does not create transitive trust.\n• The ten-entry wire validation limit is not a second limit inside the direct\n  runtime path after it appends a hop.\n• A running result does not prove that a remote peer or child handler has\n  started work.\n• A DelegationMade receipt does not prove child completion or an external\n  provider effect.\n• Cancelling a parent does not automatically cancel its delegated children.\n• Registering a connector instance does not register an AIP peer-delegation\n  route.\n• The reviewed message set does not expose a public delegation query or list\n  request.\n• This page does not claim live peer connectivity, connector qualification, or\n  product coverage beyond the separately documented Cal.diy, Hermes Agent,\n  Chatwoot, Dify, CrewAI, and Twenty connectors.\n\nRelated pages\n• Actions and sessions (actions-and-sessions.md)\n• Capabilities and contracts (capabilities.md)\n• Identity and trust (identity-and-trust.md)\n• Transactions and compensation (transactions-and-compensation.md)\n• Profiles and connectors (profiles-and-connectors.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "f47595f054a71a9befa5b3953f36b4f0767a0166285d18a430c4afaf385495b0"
  }
}
