JavaScript SDK

Typed TypeScript helpers for instrumenting your AI agent — track cost, tokens, errors, and traces from any Node.js app.

There is no Python SDK. Use the generic webhook from Python — it is a plain HTTP POST and works with the standard requests or httpx library.

Install

bash
npm install @obsivara/sdk

Published on npm as @obsivara/sdk. Requires Node.js 18+ (uses the built-in fetch and crypto). Prefer no dependency? The generic webhook and OTLP methods give the same result with a plain HTTP call.

Exported API surface

The SDK exports the following from @obsivara/sdk:

ExportKindDescription
ObsivaraClientclassMain client. Construct with { apiKey, endpoint? }.
client.startRun(data)methodPush a run_start event; returns runId (auto-generated UUID if not provided).
client.recordLlmCall(data)methodPush an llm_call event; accumulates tokens/cost for the run automatically.
client.endRun(runId, data)methodPush a run_end event; auto-fills totalTokens/totalCost from accumulated LLM calls.
client.flush()async methodFlush all buffered events immediately. Call before process exit.
client.wrapGemini(opts)methodReturns a { generate(runId, prompt, config?) } wrapper that auto-records the full llm_call (tokens, cost, latency, prompt, completion).
EventBufferclassInternal buffer (exported for advanced use — not needed in normal usage).

Type exports: ClientConfig, RunStart, RunEnd, LlmCallData, ToolCallData, SpanData, ErrorEventData, PromptVersionData, Event.

Basic usage

typescript
import { ObsivaraClient } from "@obsivara/sdk";

const client = new ObsivaraClient({
  apiKey: process.env.OBSIVARA_API_KEY!, // obs_live_...
  // endpoint defaults to https://api.obsivara.com
  // (the workspace is derived from the API key — no workspaceId needed)
});

// Start a run — returns a runId
const runId = client.startRun({
  name: "Support reply",
  assetId: "support-agent",
  input: "Where is my order?",
});

// Record an LLM call within the run
client.recordLlmCall({
  runId,
  provider: "openai",
  model: "gpt-4o",
  promptTokens: 312,
  completionTokens: 87,
  totalTokens: 399,
  costUsd: 0.0048,
  latencyMs: 1240,
});

// End the run — totalTokens/totalCost auto-derived from recordLlmCall if omitted
client.endRun(runId, {
  status: "success",
  durationMs: 3500,
});

// Flush buffered events before process exit
await client.flush();

Trace helper

client.trace() handles startRun + endRun automatically, including error handling:

typescript
// client.trace() handles startRun + endRun automatically
const result = await client.trace("Support reply", "support-agent", async (runId) => {
  const answer = await callMyLLM(runId);
  return answer;
});

Auto-instrument Gemini

wrapGemini calls the Gemini API and records a complete llm_call event automatically — tokens (from usageMetadata), cost (from the built-in pricing table), latency, prompt, and completion. PII is redacted before transmission.

typescript
import { ObsivaraClient } from "@obsivara/sdk";

const client = new ObsivaraClient({
  apiKey: process.env.OBSIVARA_API_KEY!,
});

// wrapGemini auto-records tokens, cost, latency, prompt, and completion
const gemini = client.wrapGemini({
  apiKey: "GOOGLE_API_KEY",
  model: "gemini-2.0-flash",
});

const runId = client.startRun({ name: "Chat", assetId: "my-chatbot" });
const reply = await gemini.generate(runId, "Explain OTLP in one sentence.");
client.endRun(runId, { status: "success", durationMs: 800 });

await client.flush();

Buffering and flushing

Events are buffered in memory and sent to POST /ingest/batch in batches (default: flush every 5 seconds or every 50 events, whichever comes first). Call client.flush() before your process exits to avoid losing the final batch. For serverless environments where the process terminates immediately, call await client.flush() before returning from your handler.

The SDK sends all events to POST https://api.obsivara.com/ingest/batch — the same endpoint you can call directly. If you prefer no dependencies, the generic webhook gives you the same result with a plain HTTP call.

Next steps