SDK Reference
Tracing

Tracing

Grounded tracing is built around four objects:

  • trace
  • span
  • event
  • score

The tracing SDK sends completed traces into:

  • POST /api/traces/batch
  • GET /api/traces
  • GET /api/traces/:traceId
  • GET /api/traces/:traceId/spans
  • GET /api/traces/:traceId/scores

Core Flow

const trace = tracing.startTrace({
  traceId: 'chat_123',
  sessionId: 'chat_123',
  anonymousId: 'anon_123',
  userId: 'user_123',
  name: 'support.reply',
  resource: {
    snapshotId: 'snap_456',
  },
  tags: ['support', 'prod'],
  metadata: {
    channel: 'api',
  },
  input: {
    message: 'where is my refund?',
  },
});
 
const span = trace.startSpan({
  name: 'policy.lookup',
  kind: 'retrieval',
  input: {
    source: 'faq',
  },
});
 
span.recordEvent('cache_hit', {
  index: 'policy-cache',
});
 
span.end({
  status: 'ok',
  output: {
    articleId: 'refund-policy-v3',
  },
});
 
trace.score({
  name: 'resolved',
  value: true,
  dataType: 'boolean',
});
 
trace.recordEvent('handoff_skipped', {
  reason: 'policy answered directly',
});
 
await trace.end({
  status: 'ok',
  output: {
    text: 'your refund is processing',
  },
});
 
await tracing.flush();

Correlation Rules

For real ingestion, every trace must resolve:

  • an agent
    • pass agentId to new GroundedTracing(...), or
    • pass resource.agentId on startTrace(...)
  • and at least one stitch key
    • sessionId, or
    • anonymousId, or
    • userId plus non-empty correlationKeys

The SDK now fails fast if a trace cannot be linked into Grounded's session model.

Trace Shape

The SDK writes the backend TraceWrite model:

type TraceWrite = {
  traceId: string;
  sessionId?: string;
  anonymousId?: string;
  userId?: string;
  name: string;
  startTime: string;
  endTime: string;
  status?: 'ok' | 'error';
  source?: 'sdk' | 'otel' | 'connector';
  ingestMode?: 'direct' | 'mirror' | 'import';
  provider?: string;
  providerTraceId?: string;
  providerSessionId?: string;
  correlationKeys?: Record<string, unknown>;
  metadata?: Record<string, unknown>;
  resource?: {
    agentId?: string;
    snapshotId?: string;
    environment?: string;
    release?: string;
  };
  tags?: string[];
  input?: unknown;
  output?: unknown;
  error?: {
    message: string;
    type?: string;
    stack?: string;
  };
  spans?: TraceWriteSpan[];
  scores?: TraceWriteScore[];
  events?: TraceEvent[];
};

Span Kinds

Current span kinds:

  • llm
  • tool
  • retrieval
  • guardrail
  • app

Scores

Scores are lightweight outcome annotations attached to a trace:

trace.score({
  name: 'resolved',
  value: true,
  dataType: 'boolean',
});
 
trace.score({
  name: 'groundedness',
  value: 0.91,
  dataType: 'numeric',
});

Readback

You can inspect raw stored trace data through @grounded/client:

const traces = await grounded.traces.list({
  agentId: 'agt_123',
});
 
const detail = await grounded.traces.get(traces.data[0]!.id);
const spans = await grounded.traces.listSpans(detail.id);
const scores = await grounded.traces.listScores(detail.id);

OpenTelemetry Mirroring

@grounded/tracing includes a lightweight exporter bridge for already-instrumented apps:

const exporter = tracing.createOpenTelemetryExporter();
 
await exporter.export(spans);
await tracing.flush();

This is the main "sit on top of an existing runtime" path. It lets you mirror already-instrumented spans into Grounded without replacing your upstream OTel pipeline.

Normalization Into Sessions

If Grounded can resolve a snapshot for the target agent, a direct trace is converted into an internal session record.

That session then becomes visible to:

  • sessions
  • insights
  • evals
  • snapshot optimization workflows