Pre-authorized budgets with Mandate
Cap an autonomous agent's total spend before it starts. Server-side enforced — even a runaway loop can't drain the wallet.
The problem
Letting an autonomous agent invoke capabilities with infinite spend is unwise. A bug in the agent's loop, a confused planner, a malicious prompt — any could empty the wallet.
The solution
Attach a Mandate to invocations. The Hub enforces the cap atomically per call. Calls that would exceed the cap fail with INSUFFICIENT_BUDGET before the Provider is contacted.
const mandate = {
budget_usdc: 1.00, // hard cap across all calls
expires_at: '2026-12-31T00:00:00Z', // mandate dies even if budget unspent
};
await jecp.invoke('a/b', 'action', input, { mandate });
await jecp.invoke('a/b', 'action', input, { mandate }); // accumulates
await jecp.invoke('a/b', 'action', input, { mandate });
// ...eventually:
// INSUFFICIENT_BUDGET — sum exceeded $1.00
Mandates are per-mandate, not per-call. Reusing the same mandate object across calls accumulates spend. Pass a fresh mandate each invocation if you want per-call caps.
Recovery
When a mandate is exhausted, the error includes next_action: { type: 'increase_mandate' }. Your code can decide to raise the budget and retry:
import { InsufficientBudgetError } from '@jecpdev/sdk';
let budget = 1.00;
async function invokeWithBudget(input: unknown) {
try {
return await jecp.invoke('a/b', 'c', input, {
mandate: { budget_usdc: budget },
});
} catch (e) {
if (e instanceof InsufficientBudgetError) {
// Decide whether to raise the cap
if (await operatorApprovesIncrease(budget * 2)) {
budget *= 2;
return invokeWithBudget(input);
}
}
throw e;
}
}
Mandate fields
agent_id+api_key— the SDK auto-fills these fromJecpClientcredentialsbudget_usdc— total cap across all calls under this mandateexpires_at— ISO 8601 absolute time after which the mandate is rejectedprovenance_hash— optional identity-proof hash (advanced use)
From the CLI
jecp invoke a/b c --input '{"...":"..."}' --budget 1.00