Agentoria

Telemetry & cost

Log every call, price it, and get an admin dashboard for free.

Record calls

A TelemetryStore records each LLM and tool call. Wire it into the agent's monitor sink:

import { InMemoryTelemetryStore } from '@agentoria/telemetry';

const telemetry = new InMemoryTelemetryStore();

const agent = createAgent({
  provider,
  tools,
  monitor: { operation: 'chat', provider: 'anthropic', model, sink: (m) => telemetry.recordLlmCall(m) },
});

For production, @agentoria/telemetry/drizzle provides a DrizzleTelemetryStore over any Drizzle SQLite driver (Cloudflare D1, better-sqlite3, libSQL), with hand-authorable DDL in AGENTORIA_TELEMETRY_DDL.

Cost

@agentoria/usage prices any call from its token usage, cache-aware, across the full Claude and GPT lineups:

import { costOf, computeCost, resolvePricing } from '@agentoria/usage';

const usd = costOf(usage, 'claude-sonnet-4-6');           // by model name
const c = computeCost(usage, resolvePricing('gpt-4o'));   // or an explicit pricing table

A createBudget helper enforces a spend ceiling across a run.

Stats

Pure aggregators turn records into dashboards — headline totals, success rate, latency distribution (p50/p95/p99), per-model / per-day / per-tool breakdowns, and fine-grained tool outcomes:

import { llmCallStats, toolCallStats, toolOutcomeCounts } from '@agentoria/telemetry';

const stats = llmCallStats(await store.listLlmCalls());
const tools = toolCallStats(await store.listToolCalls());
const outcomes = toolOutcomeCounts(await store.listToolCalls());

At scale, llmCallStatsSql / toolCallStatsSql compute the same numbers with GROUP BY in the database (D1/libSQL) instead of loading rows — verified byte-identical against the in-memory aggregators.

The dashboard

Feed the stats straight into <MetricsDashboard/> (from @agentoria/ui) for the admin view — stat tiles, a cost + calls/errors trend, outcome pills, and per-model / per-tool tables:

import { MetricsDashboard, AgentoriaStyles } from '@agentoria/ui';

<>
  <AgentoriaStyles />
  <MetricsDashboard stats={stats} tools={tools} toolOutcomes={outcomes} />
</>

For per-call debugging, <LlmCallLog/> renders an expandable log (metadata, tokens, TTFT, error) and <TraceTimeline/> shows a span waterfall of where a turn spent its time.

On this page