Observability

OpenTelemetry

Send Anvia traces through OpenTelemetry.

Use @anvia/otel when your application already initializes OpenTelemetry and you want Anvia observer events emitted as standard spans.

1. Install the Adapter

pnpm add @anvia/otel @opentelemetry/api

The adapter is separate from @anvia/core. Core Anvia does not export otel.

For OTLP HTTP export, install the SDK and exporter in your application:

pnpm add @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http

2. Initialize OpenTelemetry

Configure the OpenTelemetry SDK before running agents. The endpoint can also come from OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.

import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { NodeSDK } from "@opentelemetry/sdk-node";

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter(),
});

sdk.start();

The adapter does not call sdk.start(), forceFlush(), or shutdown().

3. Create the Tracing Observer

import { otel } from "@anvia/otel";

const tracing = otel.create({
  serviceName: "support-agent",
});

Pass tracer when your application needs a specific tracer instance. Otherwise, the adapter uses trace.getTracer("@anvia/otel").

4. Attach It to an Agent

const agent = new AgentBuilder("support", model)
  .instructions("Answer with a short engineering-focused summary.")
  .observe(tracing)
  .defaultMaxTurns(2)
  .build();

5. Send Trace Metadata

const response = await agent
  .prompt("Summarize ticket TICKET-1001 for engineering.")
  .withTrace({
    name: "support-ticket-summary",
    userId: "user_123",
    sessionId: "session_456",
    metadata: {
      ticketId: "TICKET-1001",
      surface: "support-console",
    },
    tags: ["support", "anvia"],
  })
  .send();

console.log(response.trace?.traceId);

OpenTelemetry receives spans for the run, model generations, tool calls, token usage, errors, and trace metadata.

6. Join an Existing Trace

Pass a valid 32-character hex trace id to continue an existing distributed trace.

await agent
  .prompt("Summarize ticket TICKET-1001.")
  .withTrace({ traceId: incomingTraceId })
  .send();

The root Anvia span is parented under a synthetic remote parent so generated spans share that trace id.

7. Shutdown Your SDK

Your application owns SDK lifecycle.

await sdk.shutdown();