Sessions and governance
How spending sessions cap what a buyer agent can spend, and how acceptance policy governs what a seller agent will accept.
An agent negotiates, signs, and funds on its own — but it never gets to decide how much of the owner's money it's allowed to move. That boundary is a spending session: an explicit, owner-approved grant that Passport enforces at the one point where money actually leaves a wallet. This page covers what a spending session contains, how its scope narrows what it covers, what the passkey ceremony that approves it actually authorizes, and the seller-side mirror that governs what an agent will accept in the first place.
What a spending session is
A spending session isn't a raw TTL-plus-limit tuple — it's a runtime wrapper around a delegation, an approved policy payload the owner reviews before granting. A delegation has three parts:
task— a human-readable summary of what the agent is doing. Descriptive only; Passport never tries to enforce the semantic meaning of the task summary, only what the policy below actually constrains.payment_policy— the enforceable part: which payment approaches are allowed, which assets, and hard caps onmax_amount_per_txandmax_total_amount.execution_constraints— optional, payment-approach-specific scoping (for example, allowed HTTP endpoints for an x402 payment).
An approved spending session, as recorded from a live session on dev, has this shape:
{
"type": "dedicated",
"scope": {
"sellers": ["did:kite:ind-lyon:recruiting-claude"]
},
"delegation": {
"task": {
"summary": "Playground purchases from Recruiting Agent (kagent serve)"
},
"payment_policy": {
"currency": "USD",
"max_amount_per_tx": "25",
"max_total_amount": "50"
},
"execution_constraints": {
"agreement": {
"sellers": ["did:kite:ind-lyon:recruiting-claude"]
}
}
},
"usage": {
"spent_total": "0",
"reserved_total": "0"
}
}Everything under delegation is immutable once approved. usage is the only mutable part — spent_total and reserved_total track what the session has actually committed, using row-locked reservation accounting so two in-flight payments can't both pass the same budget check.
Scopes
A spending session request has to declare what it covers, and the CLI exposes four scope flags:
| Flag | Scopes to |
|---|---|
--agreement-id <id> | One specific agreement — the narrowest grant |
--seller <did> | A seller agent DID (repeatable) |
--template <id> | A workflow template (repeatable) |
--all-agreements | The explicit general grant, unscoped |
--agreement-id, --seller, and --template combine as AND — request a session scoped to both a seller and a template, and it only covers agreements that satisfy both. --all-agreements is the odd one out: it's an explicit general grant that can't be narrowed by combining it with any of the other three, and requesting it alongside --agreement-id, --seller, or --template is refused locally (exit code 2, USAGE) before anything reaches Passport. There's no default scope, either — requesting a session with none of the four flags set is refused the same way.
An owner reviewing an approval isn't bound to grant exactly what was asked: approving a session records the approved scope, not the requested one, so an owner can narrow a grant on the way through.
The passkey ceremony
Approving a spending session requires the owner's passkey. What that ceremony authorizes is narrow and specific — the owner isn't approving individual payments, they're approving the delegation the session wraps.
One finding worth calling out from a live run: the approval URL is a token-authenticated public route, not tied to a logged-in browser session. It can be opened in any browser or device where the owner's passkey lives — an agent running headless in one environment can hand the URL to an owner who approves it from a completely different machine, and the requesting side just polls session request-status --wait until it resolves.
The approval link itself expires well before the session it would grant does — a request observed on dev expired in roughly 10 minutes, safely ahead of a multi-hour session TTL. If the link lapses before the owner acts, the fix is a fresh session request, not a retry of the same token.
Funding is the chokepoint
A spending session's whole purpose is enforced at exactly one moment: when the buyer's payment is authorized. If an agent tries to fund an agreement with no session covering it, the CLI refuses locally — exit code 6, error session_scope_forbidden — and nothing is sent. Nothing is charged either way; the refusal happens before any request leaves the machine.
That local check is a convenience, not the actual guarantee. Passport re-checks the scope at the funding chokepoint regardless — the same enforcement that rejects an uncovered local fund call also rejects a funding-authorization request that somehow bypassed it, because the check that matters lives on the server, not in the CLI's own bookkeeping.
Seller-side mirror
A spending session governs what a buyer agent is allowed to spend. The seller side has its own equivalent: an acceptance policy, configured by the seller's owner, that decides which incoming proposals the agent will accept automatically and which ones it won't.
The design principle is the same on both sides — fail closed. A proposal that doesn't clearly satisfy the acceptance policy doesn't get accepted by default; it escalates to a human rather than risk committing to terms the owner never agreed to. See seller governance for how acceptance policy and escalations work from the seller's side.