Not yet published to npm. Install directly from GitHub until v0.1.0 ships:
npm install github:MukundaKatta/agenttrace. The npm-version and downloads badges will return once the first npm release lands.
Cost and latency tracking for AI agent runs. Wrap your LLM call, get a per-step + per-run breakdown that you can ship to a logger, dashboard, or post-mortem.
Zero dependencies. Async-context aware (steps inside withRun attach automatically). Built-in pricing for Anthropic, OpenAI, Google, xAI, and free-tier providers (Groq, Cerebras, Ollama, OpenRouter).
npm install github:MukundaKatta/agenttraceAgents accumulate cost in places you don't expect — a tool call retry, a misrouted prompt, a forgotten model bump. agenttrace is the lightweight bookkeeping layer that records what each call cost and how long it took, with no external dependency.
It pairs naturally with the rest of the @mukundakatta agent-stack:
agentfitshapes the prompt to fit your context windowagentguardblocks unauthorized network egress from toolsagentvetvalidates tool args before executionagentsnapcaptures regression snapshotsagentcastenforces structured outputagenttrace(this lib) tracks the cost & latency of all of the above
import { withRun, measureLLM } from "@mukundakatta/agenttrace";
const { run, value } = await withRun({ name: "summarize-doc" }, async () => {
const reply = await measureLLM(
"summarize",
"claude-sonnet-4",
async () => anthropic.messages.create({
model: "claude-sonnet-4-5",
messages: [{ role: "user", content: "..." }],
}),
);
return reply.content[0].text;
});
console.log(run.summary());
// Run "summarize-doc" — 1 steps, 842ms, $0.001870
// • summarize [claude-sonnet-4] — 842ms — $0.001870import { withRun, measure, measureLLM } from "@mukundakatta/agenttrace";
const { run } = await withRun({ name: "research" }, async () => {
const docs = await measure("retrieve", () => ragStore.fetch("..."));
const summary = await measureLLM("summarize", "gpt-4.1-mini", () => openai.chat.completions.create({...}));
await measure("write", () => fs.writeFile("out.md", summary));
});
console.log(JSON.stringify(run.toJSON(), null, 2));await measure("custom", async (step) => {
const result = await callMyLLM("...");
step.recordUsage({ input: result.in_tokens, output: result.out_tokens });
return result;
}, { model: "my-custom-model" });import { setPricing, costOf } from "@mukundakatta/agenttrace";
setPricing("my-private-llm", { input: 1.5, output: 6 });
costOf("my-private-llm", { input: 10_000, output: 5_000 }); // → 0.045const { run } = await withRun({ name: "agent-1" }, async () => { /* ... */ });
logger.info({ kind: "agent_run", ...run.toJSON() });Run fn inside a fresh Run. Steps created via measure/measureLLM inside fn attach to it automatically (across awaits, via AsyncLocalStorage).
options.name?: string— display name (default"run").options.tags?: string[]— free-form labels.- Returns
{ run: Run, value: T }.
Time fn, record errors, attach to the active run.
options.model?: string— used for pricing lookup if youstep.recordUsage(...).options.tags?: string[].- Returns the value
fnresolved to.
Convenience wrapper for an LLM call. Calls fn, awaits, then runs defaultExtractUsage over the response and records it.
options.extractUsage?: (value) => UsageRecord | null— override for non-standard SDKs.options.tags?: string[].
Compute USD cost for a usage record. Recognizes longest-prefix matches (e.g. claude-sonnet-4-5-20260101 → claude-sonnet-4).
Register or override pricing for a model. Prices are USD per million tokens.
Returns the active Run (from AsyncLocalStorage) or null.
run.steps: Step[]run.latencyMs: numberrun.totalUsage: { input, output, cacheWrite, cacheRead }run.totalCostUsd: numberrun.summary(): string— one line per steprun.toJSON()— round-trippable JSON for logs/dashboards
step.name: stringstep.model?: stringstep.latencyMs: number | nullstep.usage: { input, output, cacheWrite, cacheRead }step.cost: numberstep.error: Error | nullstep.recordUsage(usage)— accumulates and recomputes coststep.toJSON()
Anthropic (Claude Opus 4 / Sonnet 4 / Haiku 4 / Sonnet 3.7 / Haiku 3.5), OpenAI (GPT-4.1 family, GPT-4o family, o1, o3), Google (Gemini 2.5 Pro/Flash/Lite, Gemini 2.0), xAI Grok 4, plus free-tier providers (Groq, Cerebras, Ollama, OpenRouter :free). Override or extend any with setPricing.
26/26 tests passing. Zero dependencies. ESM-only, Node 20+.
This is the sixth in the @mukundakatta agent-stack:
- @mukundakatta/agentfit — fit messages to LLM context window
- @mukundakatta/agentguard — network egress firewall
- @mukundakatta/agentvet — validate tool args before execution
- @mukundakatta/agentsnap — snapshot tests for tool-call traces
- @mukundakatta/agentcast — structured output enforcer
- agenttrace (this lib) — cost + latency tracking
MIT — see LICENSE.