Recorders
agentObservability(options?)
Section titled “agentObservability(options?)”agentObservability(options?: AgentObservabilityOptions): AgentObservabilityRecorder
Bundles TokenRecorder + ToolUsageRecorder + CostRecorder:
import { agentObservability } from 'agentfootprint/observe';
const obs = agentObservability({ pricing: { 'claude-sonnet-4-20250514': { input: 3, output: 15 } },});
const agent = Agent.create({ provider }) .recorder(obs) .build();
await agent.run('hello');
obs.tokens(); // TokenStatsobs.tools(); // ToolUsageStatsobs.cost(); // number (USD)obs.costEntries(); // CostEntry[]TokenRecorder
Section titled “TokenRecorder”const rec = new TokenRecorder();rec.getStats(); // TokenStatsTokenStats
Section titled “TokenStats”| Field | Type |
|---|---|
totalCalls | number |
totalInputTokens | number |
totalOutputTokens | number |
totalLatencyMs | number |
averageLatencyMs | number |
totalCost | number (USD, 0 if no pricing) |
calls | LLMCallEntry[] (each has cost) |
With pricing:
const rec = new TokenRecorder({ pricing: { 'claude-sonnet-4-20250514': { input: 3, output: 15 } },});CostRecorder
Section titled “CostRecorder”const rec = new CostRecorder({ pricingTable: { 'claude-sonnet-4-20250514': { input: 3, output: 15 } },});rec.getTotalCost(); // number (USD)rec.getEntries(); // CostEntry[]ToolUsageRecorder
Section titled “ToolUsageRecorder”const rec = new ToolUsageRecorder();rec.getStats(); // ToolUsageStatsToolUsageStats
Section titled “ToolUsageStats”| Field | Type |
|---|---|
totalCalls | number |
byTool | Record<string, ToolStats> |
QualityRecorder
Section titled “QualityRecorder”Score each response with a custom judge function:
const rec = new QualityRecorder({ judge: async (response) => ({ score: 0.9, reason: 'Good' }),});GuardrailRecorder
Section titled “GuardrailRecorder”Flag policy violations:
const rec = new GuardrailRecorder({ check: async (response) => ({ passed: true }),});PermissionRecorder
Section titled “PermissionRecorder”Track tool permission decisions:
const rec = new PermissionRecorder();rec.getEvents(); // PermissionEvent[]TurnRecorder
Section titled “TurnRecorder”Track per-turn metadata (timing, message count):
const rec = new TurnRecorder();rec.getTurns(); // TurnEntry[]OTelRecorder
Section titled “OTelRecorder”Export events as OpenTelemetry spans. Zero @opentelemetry dependency — bring your own tracer:
import { trace } from '@opentelemetry/api';import { OTelRecorder } from 'agentfootprint/observe';
const rec = new OTelRecorder(trace.getTracer('agentfootprint'));// Spans: agent.turn, gen_ai.chat, tool.*, agent.error// Attributes follow OpenTelemetry GenAI semantic conventionsExplainRecorder
Section titled “ExplainRecorder”Collect grounding evidence during traversal (no post-processing):
import { ExplainRecorder } from 'agentfootprint/explain';
const rec = new ExplainRecorder();agent.recorder(rec);await agent.run('...');
rec.getSources(); // tool results (ground truth)rec.getClaims(); // LLM responses (to verify)rec.getDecisions(); // tool call decisionsrec.explain(); // structured summary