Budget envelopes
A budget envelope lets an agent spend at a resource without a round trip to the control plane
on every call. The control plane slices an amount from the owner’s active mandate and issues
an AAuth auth token (typ: aa-auth+jwt) carrying a budget claim. The resource verifies the
token, meters each request against the envelope and answers with an AAuth-Budget header.
When the envelope runs out, the resource refuses with a signed consumption record that the
agent brings back to the control plane for a fresh slice. The wire format is
draft-hardt-aauth-budgets; the token and signature rules are AAuth protocol -11, as published
on 25 September 2026. Regent Control acts as the person server (PS) in the three-party flow.
Issuing an envelope
POST https://control-api.regentprotocol.org/v1/control/budget-tokens
Authorization: Bearer rgnt_…
{
"agent_id": "agt_…",
"resource": "https://get4agent.com",
"cnf_jwk": { "kty": "OKP", "crv": "Ed25519", "x": "…", "alg": "Ed25519" },
"requested_amount_minor": 50000,
"budget_consumed": [ { "jti": "at_…", "consumed": 31000, "iat": 1760000000 } ]
}The slice is denominated by the mandate it is carved from; a unit that disagrees is refused.
Records in budget_consumed settle earlier envelopes exactly once. The response carries the
token and its claims:
| Claim | Value |
|---|---|
iss | https://control-api.regentprotocol.org, the PS identifier; its metadata lives at /.well-known/aauth-access.json |
dwk | aauth-access.json |
ps | the same identifier (three-party flow) |
aud | the one resource the envelope is for |
sub | the owner’s agent id |
jti | the envelope id; consumption is reported against it |
budget | { "amount", "unit", "decimals" } in minor units |
cnf.jwk | the agent’s registered public key, labelled with a fully-specified alg |
exp | at most one hour after iat |
Tokens are signed RS256; the key is at /v1/control/.well-known/jwks.json.
Spending it
The agent signs each request with the key in cnf.jwk and carries the token in
Signature-Key under the jwt scheme. The signature covers @method, @authority, @path
and signature-key, plus content-digest and content-type when the request has a body, and
names created within the resource’s signature_window (120 seconds at get4agent). With
regent-httpsig:
from regent_httpsig import EgressSigner
agent = EgressSigner(seed=SEED, signature_agent="https://myagent.example")
headers = agent.sign_aauth("POST", url, {"content-type": "application/json"},
token=auth_token, body=raw_body)A served request answers with the remaining balance:
AAuth-Budget: cost=300, remaining=49700, unit="KZT", decimals=2Refusals
| Situation | Status and headers |
|---|---|
| the envelope cannot cover the request | 401, AAuth-Requirement: requirement=auth-token; resource-token="…"; reason=insufficient-budget, AAuth-Budget: remaining=…, required=… |
| the envelope is exhausted | the same with reason=budget-exhausted |
| the token has expired | 401, Signature-Error: error=expired_jwt, AAuth-Requirement: requirement=person-token |
| the token was revoked | 401, Signature-Error: error=revoked_jwt, AAuth-Requirement: requirement=person-token |
| the signature does not verify | 401, Signature-Error: error=<code> with Accept-Signature-Scheme or Accept-Signature-Alg where they apply |
The resource token in a budget refusal carries one consumption record, the presented token’s
{ "jti", "consumed" }. An expired or revoked token gets no resource token: its final figure
reaches the control plane through the usage endpoint, not on the challenge. Error bodies are
application/problem+json with the error member.
Revocation and usage
The control plane may revoke an envelope at the resource’s revocation_endpoint with a signed
POST { "jti", "exp" }. It signs as a server, Signature-Key: sig=jwks_uri; id="https://control-api.regentprotocol.org"; dwk="aauth-access.json"; kid="…", covering the body. The resource keys the
revocation by the caller’s verified identity and the jti, answers an empty 200 whether or
not it has seen the token, and refuses later presentations of it with revoked_jwt.
The usage_endpoint answers a signed query from the PS with consumption counters per sub
and per key thumbprint, so settlement never depends on the agent carrying a record home.
Where to look
- get4agent publishes its resource metadata at
https://get4agent.com/.well-known/aauth-resource.json:budget_units,usage_endpoint,revocation_endpoint,access_mode,signature_window,accept_signature_algs. regent-httpsigimplements the resource side (verifier, meter, usage and revocation endpoints) and the signers.- Settlement confirmation covers what the counterparty states after a payment; budgets cover what the agent may spend before one.