Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.svantic.com/llms.txt

Use this file to discover all available pages before exploring further.

Trace propagation

import {
  parse_traceparent,
  parse_baggage,
  extract_trace_context,
  type ParsedTraceparent,
  type ExtractedTraceContext,
} from '@svantic/sdk';

What it is

A small set of pure functions for working with W3C Trace Context. Svantic embeds a traceparent (and optionally baggage) in every dispatch so your agent’s spans connect back to the caller’s trace tree. The SDK already parses those headers for you and surfaces the parent trace-id and span-id on CapabilitySessionContext, so you normally don’t need these helpers. You import them only when you need to do one of three things:
  1. Forward the trace downstream — you’re calling a non-Svantic service (REST, gRPC) from inside a capability and want the same trace tree to span both hops.
  2. Inspect trace context in custom transports — you’re writing your own dispatch path and need to extract trace fields from a raw payload.
  3. Read baggage — you want tenant or user context the upstream caller attached.

When to use it

  • Forwarding trace context to an outbound fetch / HTTP client.
  • Building a custom exporter or middleware that reads upstream trace fields.
  • Writing tests that assert trace context was wired through.
If you’re happy with the automatic ctx.trace_id / ctx.parent_span_id on the session context, you can ignore this module entirely.

Functional usage

import { extract_trace_context } from '@svantic/sdk';

agent.define_capability({
  name: 'fetch_external_quote',
  parameters: { /* … */ },
  handler: async (args, ctx) => {
    // ctx.trace_id / ctx.parent_span_id are already available, but if
    // you want the raw header strings (to forward as-is), parse the
    // dispatch payload yourself:
    const trace = extract_trace_context(ctx.raw_dispatch);

    const res = await fetch('https://quotes.example.com/v1/lookup', {
      headers: {
        ...(trace?.traceparent && { traceparent: trace.traceparent }),
        ...(trace?.baggage && { baggage: trace.baggage }),
      },
    });

    return await res.json();
  },
});
With this in place, spans from the quotes service will show up as children of the caller’s trace in the Svantic dashboard.

parse_traceparent(raw)

function parse_traceparent(raw: string | undefined | null): ParsedTraceparent | null;
Parse a W3C traceparent header. Returns null if the header is missing, malformed, or uses an unsupported version — never throws. Only version 00 is accepted. All-zero trace-ids and span-ids are rejected per spec.

ParsedTraceparent

FieldTypeDescription
versionstringAlways '00'.
trace_idstring32-hex lowercase.
parent_span_idstring16-hex lowercase.
flagsstring2-hex lowercase.
sampledbooleantrue iff the sampled flag (bit 0) is set.

parse_baggage(raw)

function parse_baggage(raw: string | undefined | null): Record<string, string>;
Parse a W3C baggage header into a plain map. Malformed entries are skipped silently (per spec). Values are percent-decoded. Always returns an object — never null — so callers can unconditionally spread it.

extract_trace_context(session)

function extract_trace_context(session: unknown): ExtractedTraceContext | null;
High-level helper that pulls trace context out of a dispatch’s session blob. Returns null when the session has no propagation_headers. Never throws — bad headers simply produce missing fields on the result.

ExtractedTraceContext

FieldTypeDescription
propagation_headersRecord<string, string>Raw headers as sent by the mesh. Forward verbatim to downstream HTTP services.
parent_trace_id?stringFrom traceparent, when valid.
parent_span_id?stringFrom traceparent, when valid.
baggageRecord<string, string>Parsed baggage map. Empty object when absent or unparseable.

Example: forward headers to a downstream service

agent.define_capability({
  name: 'fetch_order',
  description: '…',
  parameters: { /* … */ },
  handler: async (args, ctx) => {
    const res = await fetch('https://legacy.internal/orders/' + args.id, {
      headers: ctx.propagation_headers ?? {},
    });
    return res.json();
  },
});

Example: parent a custom span

import { trace } from '@opentelemetry/api';

const tracer = trace.getTracer('invoice-agent');

agent.define_capability({
  name: 'summarize_invoice',
  description: '…',
  parameters: { /* … */ },
  handler: async (args, ctx) => {
    return tracer.startActiveSpan('summarize', async (span) => {
      if (ctx.parent_trace_id) span.setAttribute('svantic.parent_trace_id', ctx.parent_trace_id);
      if (ctx.parent_span_id) span.setAttribute('svantic.parent_span_id', ctx.parent_span_id);
      try {
        return await do_summarize(args);
      } finally {
        span.end();
      }
    });
  },
});

See also