New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@tracelanedev/sdk

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tracelanedev/sdk

Tracelane TypeScript SDK — auto-instrument AI agent frameworks

Source
npmnpm
Version
0.3.0
Version published
Weekly downloads
13
18.18%
Maintainers
1
Weekly downloads
 
Created
Source

@tracelanedev/sdk

npm License: Apache 2.0

Instrumentation for TypeScript AI agents, built on the OpenTelemetry Node SDK. Spans are emitted via OTLP/HTTP (JSON) to the endpoint you configure — https://gateway.tracelane.dev on Tracelane Cloud, or a receiver you run.

Install

npm install @tracelanedev/sdk
# or
pnpm add @tracelanedev/sdk

Fastest path — route through the gateway (no SDK)

For Tracelane Cloud, the shortest path to your first trace needs no SDK at all: point your existing client's base URL at the gateway and use your tlane_… key. The gateway routes the call and captures the trace.

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://gateway.tracelane.dev/v1",
  apiKey: process.env.TRACELANE_API_KEY!, // tlane_… from app.tracelane.dev
});

await client.chat.completions.create({
  model: "claude-sonnet-4-6",
  messages: [{ role: "user", content: "Hello" }],
});
// → Trace visible at https://app.tracelane.dev/traces within ~1 second

That captures the model call. Use this SDK when you want the shape of your agent — the planner step, each tool call, the summariser — as a nested trace rather than one span per model call. It exports OTLP to Tracelane Cloud's gateway, a self-hosted Tracelane ingest, or your own collector (Jaeger, Tempo, …).

Sessions — group turns into one conversation

/sessions groups traces by conversation id. The id travels as the x-conversation-id request header (the gateway also accepts x-session-id), and it lands on the span as gen_ai.conversation.id. This SDK is what sets it — an un-sessioned call sends no session header and carries no conversation id.

Wrap the turn and every call inside the scope joins the session:

import { instrumentOpenAI, withSession } from "@tracelanedev/sdk";

instrumentOpenAI(client);

await withSession(conversationId, async () => {
  await client.chat.completions.create({ model: "claude-sonnet-4-6", messages });
  await client.chat.completions.create({ model: "claude-sonnet-4-6", messages: followUp });
});
// Both calls land in the same session.

withSession is backed by AsyncLocalStorage, so overlapping conversations in one server process never bleed into each other. For a single-conversation script or CLI, setSession(id) sets it process-wide instead, and getSession() reads back whichever is active.

Auto-attach covers the four adapters that wrap a request-options argument: instrumentOpenAI, instrumentAnthropic, instrumentLiteLLM and instrumentOpenRouter. For every other client — including the no-SDK gateway path above — pass the header yourself:

import { sessionHeaders } from "@tracelanedev/sdk";

await client.chat.completions.create(
  { model: "claude-sonnet-4-6", messages },
  { headers: sessionHeaders(conversationId) },
);

sessionHeaders() with no argument returns the active session, or {} when there is none, so it is always safe to spread. A header you set explicitly always wins over the ambient session.

A session id must be non-empty visible ASCII, at most 256 characters. Anything else throws at the call you wrote, rather than being dropped in transit and leaving the session silently empty — and it is rejected, never truncated, because a truncated id would split one conversation into two.

SDK quick start (OTLP export)

Two steps: init() once at startup, then wrap each client with its instrument* function. There is no zero-config magic in v1 — wrapping is explicit, so what's traced is exactly what you opted in.

import { init, instrumentAnthropic } from "@tracelanedev/sdk";
import Anthropic from "@anthropic-ai/sdk";

// 1. Initialise once. endpoint + apiKey are REQUIRED (no env-var auto-read).
init({
  endpoint: "https://gateway.tracelane.dev", // or a receiver you run
  apiKey: process.env.TRACELANE_API_KEY!,    // needs the `ingest` scope
  serviceName: "my-agent",
});

// 2. Wrap the client — instrumentAnthropic patches it in place.
const client = new Anthropic();
instrumentAnthropic(client);

// 3. Use it normally — every call now emits a span.
await client.messages.create({
  model: "claude-sonnet-4-6",
  messages: [{ role: "user", content: "Hello" }],
  max_tokens: 128,
});

Your key needs the ingest scope. Keys minted before scopes existed carry the full API surface and work as-is. A key scoped to chat and read does not — the gateway answers 403 insufficient_scope and names ingest in the body. Tick Ingest in Settings → API Keys; it is on by default for new keys.

init() options

FieldRequiredDescription
endpointyesOTLP HTTP endpoint. https://gateway.tracelane.dev for Cloud, or a receiver you run (e.g. http://localhost:4318). Spans POST to ${endpoint}/v1/traces.
apiKeyyesYour tlane_… key. Sent as the x-tracelane-api-key header.
serviceNamenoResource service.name (default unknown-service).
sampleRateno0.0–1.0 (default 1.0 — full trace; the tail sampler decides).

Call shutdown() on exit to flush pending spans (an automatic flush is also registered on beforeExit).

Streaming (v1 limitation)

Streamed calls (stream: true) pass through untouched and still produce a span with model + latency, marked tracelane.streaming = true. Token usage and finish reason are not captured for streamed responses yet — that is not implemented. A once-per-process runtime warning says exactly this.

Instrumented libraries

Each library has its own instrument*(client) function — import it from the package root or the matching subpath. Call it once, after constructing the client (or, for module-level libraries, after import).

ImportWrap withWhat is traced
@anthropic-ai/sdkinstrumentAnthropic(client)messages.create, streaming, tool use
openaiinstrumentOpenAI(client)chat.completions, embeddings, Responses
@openai/agentsinstrumentOpenAIAgents(...)agent steps, tool calls, handoffs
langchaininstrumentLangGraph(graph)chains, agents, tool calls
@modelcontextprotocol/sdkinstrumentMCP(...)tool_call, tool_result
Vercel AI SDKinstrumentVercelAI(...)generateText, streamText, generateObject

Full list (one export per library): instrumentAnthropic, instrumentOpenAI, instrumentOpenAIAsync, instrumentLiteLLM, instrumentOpenRouter, instrumentLangGraph, instrumentOpenAIAgents, instrumentVercelAI, instrumentMCP, instrumentClaudeCode, instrumentCursor, instrumentPinecone, instrumentQdrant, instrumentComposio, instrumentBrowserbase, instrumentE2B, instrumentMem0, instrumentLetta, instrumentFirecrawl.

Zero-config autoInstrument() is not in v1 — calling it throws with a pointer to this explicit API. Auto-detection is not implemented.

Next.js App Router

Initialise in instrumentation.ts (runs once per server process):

// instrumentation.ts
export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { init } = await import("@tracelanedev/sdk");
    init({
      endpoint: "http://localhost:4318", // an OTLP receiver you run
      apiKey: process.env.TRACELANE_API_KEY!,
      serviceName: "my-nextjs-app",
    });
  }
}

Manual spans

The SDK sets up a standard OpenTelemetry tracer provider, so custom spans use @opentelemetry/api directly — no Tracelane-specific wrapper:

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

const tracer = trace.getTracer("my-agent");
const hits = await tracer.startActiveSpan("retrieval", async (span) => {
  span.setAttribute("retrieval.top_k", 10);
  const results = await vectorStore.search(query, { topK: 10 });
  span.end();
  return results;
});

Design invariants

  • Telemetry goes to your configured endpoint only — the SDK never calls home.
  • Instrumentation is additive — instrument* patches a client in place and does not modify the OpenAI/Anthropic module exports.
  • Redaction — set TRACELANE_TRACE_CONTENT=false to redact prompt and completion text from captured traces (honored on the gateway path).
  • Zero runtime dependencies beyond the OpenTelemetry SDK.

Documentation

Full docs at docs.tracelane.dev/sdk-typescript.

Stack

TypeScript 5.5+ strict, Biome (lint + format), Vitest.

License

Apache 2.0 — see LICENSE.

Keywords

tracelane

FAQs

Package last updated on 02 Sep 2026

Related posts