Usage tracking
createBudgetGuardrail() answers 'has this client exceeded its budget' with one running total. createUsageLedger() answers 'how much has each session/user cost so far' — cumulative tokens and estimated cost, broken down per key and per model.
usage-ledger.ts
import { createClient, anthropic, createUsageLedger } from "samai-sdk";
const ledger = createUsageLedger();
const provider = ledger.wrapProvider(
anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),
(options) => options.metadata?.sessionId as string | undefined
);
const client = createClient({ provider });
await client.generate({
model: "claude-sonnet-4-6",
messages: [{ role: "user", content: "hi" }],
metadata: { sessionId: "session-123" },
});
console.log(ledger.getStats("session-123"));
// { totalTokens, totalCostUsd, callCount, byModel: { "claude-sonnet-4-6": { ... } } }
console.log(ledger.getAllStats()); // every key seen so far
console.log(ledger.toJSON()); // JSON snapshot — feed this to a dashboard or log periodicallyNothing is dropped silently
Calls where
keyFn returns undefined are recorded under "_unattributed" rather than silently dropped. Pass { onRecord } to fire on every recorded call, and { pricing } to override the built-in per-model pricing table — provider pricing changes over time, so treat the defaults as illustrative. The ledger tracks numbers; rendering a dashboard from toJSON() is on you.