Tracing & Observability
Every execution in Kikoyu SDK generates a comprehensive RunTrace telemetry object. Tracing provides complete visibility into LLM execution steps, tool invocations, token counts, model latency, and guardrail checks.
Why Tracing is Critical
Building autonomous AI agents requires deep observability:
- Token Usage Tracking: Monitor exact prompt tokens and completion tokens consumed per run.
- Latency Diagnostics: Identify slow tool executions or long model response times.
- Audit Trails: Inspect full step-by-step history of model calls, tool arguments, and handoff transfers.
Accessing RunTrace Telemetry
The RunResult object returned by runner.run() includes the complete trace:
import { Agent, createTool, OpenAIProvider, Runner, z } from '@kikoyu/core';
const lookupOrderTool = createTool({
name: 'lookup_order',
description: 'Lookup order details.',
parameters: z.object({ orderId: z.string() }),
execute: async ({ orderId }) => ({ orderId, status: 'Shipped' }),
});
const agent = Agent.builder()
.setName('SupportAgent')
.setInstructions('Help users with orders.')
.setModel(new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY!, model: 'gpt-4o-mini' }))
.addTool(lookupOrderTool)
.build();
const runner = new Runner();
async function main() {
const result = await runner.run(agent, 'Check status of order ORD-9921');
// Access execution trace telemetry
const trace = result.trace;
if (trace) {
console.log('Run ID:', trace.runId);
console.log('Root Agent:', trace.agentName);
console.log('Execution Status:', trace.finalStatus);
console.log('Total Duration (ms):', trace.durationMs);
console.log('Total Token Usage:', trace.totalTokenUsage);
console.log('\n--- Step Execution History ---');
trace.steps.forEach((step, idx) => {
console.log(`[Step ${idx + 1}] Type: ${step.type} | Duration: ${step.durationMs}ms`);
console.log('Metadata:', step.metadata);
});
}
}
main().catch(console.error);Telemetry Interface Reference
export interface RunTrace {
runId: string; // Unique UUID for the run
agentName: string; // Primary initiating agent name
startTime: string; // ISO timestamp
endTime?: string; // ISO timestamp
durationMs?: number; // Total wall-clock execution time in ms
totalTokenUsage: {
promptTokens: number;
completionTokens: number;
totalTokens: number;
};
steps: StepTrace[]; // Sequential execution steps
finalStatus: 'completed' | 'failed' | 'max_iterations_reached' | 'guardrail_tripped';
error?: string; // Error message if run failed
}
export interface StepTrace {
type: 'model_call' | 'tool_call' | 'guardrail' | 'handoff' | 'structured_output_repair';
timestamp: string;
durationMs: number;
metadata: Record<string, unknown>;
}Exporting Traces to Datadog / OpenTelemetry / LangSmith
Because trace is a clean, serializable JSON object, you can record traces to your telemetry pipeline easily:
async function logTelemetry(result: RunResult) {
if (!result.trace) return;
await fetch('https://telemetry.your-company.com/v1/traces', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
traceId: result.trace.runId,
agent: result.trace.agentName,
latency: result.trace.durationMs,
tokens: result.trace.totalTokenUsage.totalTokens,
steps: result.trace.steps,
}),
});
}