The budget ledger
ctx.budget meters and alerts. It cannot refuse a spend, and it must never grow the ability to.
budget: BudgetLedger;Source: verifi-harness-sdk/src/budget-ledger.ts, with the schema in
@pragyacyber/engine-contract's budget.ts.
Where spend enters, and what happens when it piles up
The one rule
The reasoning, verbatim from the source:
Capping cost, tokens, tool calls or evidence severs a scan mid-test. The target is left half-examined, the findings are partial, and the delivered report is wrong in a way that is hard to detect from the outside. An overspend is a bill; a truncated assessment is a defective product shipped to a client.
What remains is metering. And because metering is now the entire control surface, the metered path being the only way to spend matters more than it did when caps existed — a bypass is no longer an overspend risk, it is a run nobody can see.
The budget
export const zBudget = z.object({
/** HARD. Breach ⇒ Run → 'timed_out'. Bounds cost by rate × time. */
maxDurationMinutes: z.number().int().positive(),
// crossing these NEVER stops anything
costUsdThresholds: zLevels,
tokenThresholds: zLevels,
toolCallThresholds: zLevels,
evidenceByteThresholds: zLevels,
/** Advisory. A harness may consult it; nothing enforces it. */
maxSubAgents: z.number().int().positive(),
/** Ledger flush + threshold-evaluation cadence. */
checkpointEverySeconds: z.number().int().positive().default(30),
}).strict();zLevels is an array of positive numbers that must be strictly ascending, so "worse"
is unambiguous. A typical shape is [expected, 2×, 5×].
The schema is .strict() specifically so that a resurrected maxCostUsd or
policy: 'hard' | 'soft' is a loud parse error rather than a silently ignored field
somebody believes is being enforced.
Reading it
export class BudgetLedger {
record(delta: Partial<Omit<Spend, 'elapsedMinutes'>>): void;
spent(): Spend;
elapsedMinutes(): number;
/** Minutes until the hard deadline. The only hard bound in the system. */
timeRemaining(): number;
/** True once the deadline has passed. */
pastDeadline(): boolean;
/** Advisory. Nothing enforces it. */
overThreshold(): ThresholdBreach[];
/** An accounting split for a sub-agent. Not a cap. */
allocate(): BudgetLedger;
}export interface Spend {
costUsd: number;
tokens: number;
toolCalls: number;
evidenceBytes: number;
elapsedMinutes: number;
subAgents: number;
}You will rarely call record() — the MCP client and the model client do it for you on
every call. Call it yourself only for spend the SDK cannot see.
Making cheaper choices
You may consult the ledger. Nothing requires you to.
// Shrink the sweep when we are past the first cost threshold.
const breaches = ctx.budget.overThreshold();
const depth = breaches.some((b) => b.metric === 'cost_usd') ? 'fast' : 'thorough';
// Stop starting new work when there is not time to finish it.
if (ctx.budget.timeRemaining() < 5) {
ctx.log('under five minutes remaining — skipping the deep phase');
return finish();
}timeRemaining() and pastDeadline() are the only two that describe an actual bound.
Everything else is advisory.
Thresholds fire once
export function crossedThresholds(
levels: readonly number[],
actual: number,
alreadyFired: readonly number[],
): number[];Each level fires at most once per run. An alert that repeats on every call is noise, and noise is precisely how the platform's only control surface stops being read.
Verified: crossedThresholds([1, 5, 25], 6, [1]) returns [5] — the already-fired 1 is
excluded, and 25 has not been reached.
A crossing produces a ThresholdBreach:
{ metric: 'cost_usd' | 'tokens' | 'tool_calls' | 'evidence_bytes',
threshold: number, actual: number, alertedAt: string }runHarness wires the ledger's onBreach to emit a threshold_breach event at warn.
That alert is the whole mechanism. It does not stop anything.
Sub-agents
const sub = ctx.budget.allocate();Returns a new BudgetLedger sharing the same budget, events and clock. It is an
accounting split, not a cap: exceeding it changes nothing, and a sub-agent that runs past
its share keeps working. Note the returned ledger starts its own elapsed clock and its own
fired-threshold set, so a sub-agent can re-fire a level the parent already fired.
What the engine sends down
The gRPC channel carries a BudgetUpdate down-message with reconciled spend, breach state
and minutes remaining. GrpcEngineChannel ignores it, deliberately:
// budgetUpdate is deliberately ignored here: it is ADVISORY. A harness that wants
// to be frugal reads ctx.budget; nothing about it can halt a run.There is currently no way for a harness to observe the engine's reconciled view of spend.
Your ctx.budget reflects only what this container metered.