Docs/telemetryv1.0.0-rc.1

Run-Event Telemetry

Added: v0.16.0 Primary types: RunEvent, RunEventStream, MemoryRunEventStream, RedisRunEventStream, PostgresRunEventStore

Run events are structured telemetry records for long-running work such as LLM calls, agent steps, retry loops, and sandbox operations. They complement logs, metrics, and spans by giving product code a stable stream keyed by runId.

When To Use Run Events

Use run events when a browser, admin UI, quota system, or audit log needs to reconstruct what happened during a workflow:

  • Agent iteration progress
  • LLM token and cost accounting
  • Retry and terminal outcomes
  • Tool invocation summaries
  • Per-tenant or per-user run inspection

Event Shape

import type { RunEvent } from '@tagna/udiot/telemetry';

const event: RunEvent = {
  level: 'info',
  message: 'generation complete',
  runId: 'run_123',
  agent: 'codegen',
  step: 'generate-component',
  tokensIn: 1200,
  tokensOut: 350,
  costUSD: 0.0042,
  outcome: 'success',
};

Terminal outcomes are success, failure, cancelled, timeout, and oscillation. Consumers can subscribe with untilTerminal: true to stop reading once one of those events arrives.

In-Memory Stream

import { MemoryRunEventStream } from '@tagna/udiot/telemetry';

const stream = new MemoryRunEventStream({ historyPerRun: 500 });

await stream.publish({
  level: 'info',
  message: 'started',
  runId: 'run_123',
  agent: 'planner',
  step: 'start',
  outcome: 'in_progress',
});

for await (const event of stream.subscribe('run_123', { untilTerminal: true })) {
  console.log(event.step, event.outcome);
}

The memory backend stores recent history per run and supports replay plus live tailing in a single subscription. It is suitable for tests and single-process development.

Redis Stream

Use Redis when multiple app instances need to publish and subscribe to the same run stream.

import Redis from 'ioredis';
import { createRunEventStream } from '@tagna/udiot/telemetry';

const stream = createRunEventStream({
  backend: 'redis',
  redis: {
    publisher: new Redis(process.env.REDIS_URL),
    subscriber: new Redis(process.env.REDIS_URL),
  },
  prefix: 'myapp:runs',
});

The Redis backend keeps replay history with a TTL and publishes live events through Redis pub/sub.

Persistent Store

PostgresRunEventStore batches events into a table you control through a MikroORM-compatible entity manager.

import { MemoryRunEventStream, PostgresRunEventStore } from '@tagna/udiot/telemetry';

const store = new PostgresRunEventStore({
  em,
  table: 'udiot_run_events',
  batchSize: 100,
});

const stream = new MemoryRunEventStream({ store });

Use a persistent store for audit trails, billing reconciliation, and admin run-inspector pages. Live subscribers still receive events even if the store temporarily fails.

LLM Integration

LLMClient emits run events automatically when the request includes runId:

await llm.complete({
  model: 'gpt-4o-mini',
  runId: 'run_123',
  agent: 'summarizer',
  step: 'complete',
  messages: [{ role: 'user', content: 'Summarize this...' }],
});

Each emitted event includes outcome, duration, token counts, cost, cache status, and any metadata passed on the request.

From the canonical UDIOT public documentation.Try it in the playground ↗