A DelegationReceipt is a signed authorization from a workflow owner or principal to an agent. It says which agent may request a bounded class of actions, for what purpose, and during which validity window. The receipt is signed locally by the principal and can be verified offline.
Use a DelegationReceipt when an agent needs authority evidence for deployment,
infrastructure, financial, or other risky actions. The receipt does not execute
anything by itself; controlled_action(...) and the Runtime Gate still evaluate
the requested action, resource, environment, policy, and approval state.
def issue_delegation_receipt(
self,
*,
agent_did: str,
allowed_categories: list[str],
valid_for: datetime.timedelta,
max_spend: dict[str, object] | None = None,
purpose: str = "Controlled-action delegation",
) -> dict[str, object]Parameters:
| Parameter | Meaning |
|---|---|
agent_did |
did:key of the agent receiving delegated authority. |
allowed_categories |
One or more runtime categories, such as deploy or infrastructure. |
valid_for |
Positive timedelta validity window from issue time. |
max_spend |
Optional cap shaped as {"currency": "USD", "amount": 100}. |
purpose |
Human-readable audit note. It is signed, but not used as a policy rule. |
issue_delegation_receipt(...) raises ValueError for invalid scope values
and TypeError for unexpected arguments. Current v1 receipts support
allowed_category and optional max_spend predicates. Exact
allowed_actions, allowed_resources, and allowed_environments are supplied
to controlled_action(...) and checked there.
The returned receipt is a W3C VC v2.0 dictionary:
| Field | Meaning |
|---|---|
@context |
Includes W3C VC v2 and AgentVeil delegation v1 contexts. |
type |
Includes VerifiableCredential and AgentDelegation. |
id |
Receipt identifier, usually urn:uuid:.... |
issuer |
Principal DID that signed the receipt. |
validFrom / validUntil |
UTC validity window. |
credentialSubject.id |
Agent DID receiving delegated authority. |
credentialSubject.scope |
Signed scope predicates. |
credentialSubject.purpose |
Signed human-readable purpose. |
proof |
eddsa-jcs-2022 DataIntegrityProof over the canonical receipt body. |
verification = agent.verify_delegation_receipt(receipt)On success, verify_delegation_receipt(...) returns:
{
"valid": True,
"issuer": "did:key:...",
"subject": "did:key:...",
"scope": [...],
"purpose": "...",
"valid_from": datetime.datetime(...),
"valid_until": datetime.datetime(...),
"id": "urn:uuid:...",
}The verifier is offline: it does not call the AgentVeil API. Invalid receipts
raise agentveil.delegation.DelegationInvalid with a .reason string such as
delegation expired, signature verification failed,
verificationMethod does not match issuer, or invalid scope: ....
See Error Handling for how DelegationInvalid fits with SDK
HTTP exceptions.
| Pattern | Scope shape | Notes |
|---|---|---|
| Short-lived deploy delegation | allowed_categories=["deploy"], valid_for=timedelta(minutes=15) |
Good default for release workflows and CI jobs. |
| Multi-resource delegation | allowed_categories=["deploy", "infrastructure"] |
The receipt authorizes categories; exact action/resource/environment are checked by controlled_action(...). |
| Approval-required delegation | allowed_categories=["infrastructure"], short validity |
Delegation supplies authority evidence; policy can still return approval_required. See Approval Routing. |
| Long-lived service delegation | valid_for=timedelta(days=7) or similar |
Use sparingly. Prefer short windows and rotate receipts when automation allows. |
DelegationReceipts are JSON-compatible dictionaries. Store the exact JSON object,
then reload it before calling verify_delegation_receipt(...) or
controlled_action(...).
import json
from pathlib import Path
path = Path("delegation-receipt.json")
path.write_text(json.dumps(receipt, indent=2), encoding="utf-8")
loaded = json.loads(path.read_text(encoding="utf-8"))
assert agent.verify_delegation_receipt(loaded)["valid"] is TrueDo not store the principal private key with the receipt. The receipt is intended to be shareable authority evidence; the key that issued it is not.
After verification, pass the receipt to controlled_action(...):
outcome = agent.controlled_action(
action="deploy.release",
resource="service:billing-api",
environment="production",
delegation_receipt=receipt,
)If outcome.status == "executed", retain the signed receipt and export a proof
packet with agent.build_proof_packet(...). If the status is
approval_required, route the approval to the principal and resume with
execute_after_approval(...).
See Approval Routing for the full grant and resume
pattern.
See Proof Packet Guide for export, save, and offline
verification.
See Customer Integration for the full runtime path and examples/delegation for runnable offline DelegationReceipt examples.