# SDK API reference (/docs/sdk-reference)



This page is a centralized, searchable cheat sheet for the browser SDK (`@obsunified/analytics-sdk`) and server-side SDKs (`@obsunified/telemetry-sdk`, Go, and Rust).

## SDK initialization [#sdk-initialization]

### Browser / client-side [#browser--client-side]

Initialize the browser SDK to track page views, click interactions, and frontend exceptions. DOM session replay is opt-in: call `startReplay()` from `useAnalytics()` when you want it.

```tsx check
import { AnalyticsProvider, useAnalytics } from "@obsunified/analytics-sdk/react";

function Root() {
  return (
    <AnalyticsProvider
      collectorUrl="https://obs.my-app.com"
      apiKey="your-public-ingest-key"
      trackPageViews={true}
      captureErrors={true}
    >
      <App />
    </AnalyticsProvider>
  );
}

function ReplayButton() {
  const { startReplay } = useAnalytics();
  return <button onClick={() => startReplay()}>Record this session</button>;
}

declare function App(): null;
```

For non-React hosts:

```ts check
import { installAutoCorrelate, UsageTracker } from "@obsunified/analytics-sdk";

const tracker = new UsageTracker({
  collectorUrl: "https://obs.my-app.com",
  apiKey: "your-public-ingest-key",
});

// Mode A: mints an interaction_id on click/submit/keydown and injects
// `x-obs-interaction` on outbound fetch/XHR. Returns a cleanup function.
const stopAutoCorrelate = installAutoCorrelate();
```

### Backend / server-side [#backend--server-side]

Initialize the standard telemetry exporter pipeline once at application startup (or per request in serverless runtimes). Passing `environment`, `serviceVersion`, `commitSha`, and `configDigest` stamps release lineage on every span for [AutoSRE cohort attribution](/docs/autosre).

```ts check
import { initObservability, recordFeatureFlag } from "@obsunified/telemetry-sdk";

initObservability({
  collectorUrl: "https://obs.my-app.com",
  apiKey: process.env.OBS_INGEST_KEY!,
  serviceName: "checkout-api",
  environment: process.env.OBS_ENVIRONMENT ?? "prod",
  serviceVersion: process.env.OBS_SERVICE_VERSION ?? "1.2.0",
  commitSha: process.env.OBS_COMMIT_SHA,
  configDigest: process.env.OBS_CONFIG_DIGEST,
  flushIntervalMs: 5000,
});

// Stamp feature-flag evaluations onto the active span and cohort context:
recordFeatureFlag("new_checkout_flow", true, { providerName: "launchdarkly" });
```

## Click-to-trace context [#click-to-trace-context]

### Server-side HTTP ingress [#server-side-http-ingress]

Extract `x-obs-interaction`, bind it onto the active trace context, and flush buffered spans/logs/AI calls before serverless isolates terminate. The interaction id must be a 26-character uppercase Crockford-base32 ULID (for example `01JAQ8K3Z9X7M2N4P6Q8R0S1T3`); the browser SDK generates valid ids, and the server SDK silently drops malformed `x-obs-interaction` values.

```ts check
import {
  createRequestSpan,
  flushAICalls,
  flushLogs,
  flushSpans,
  runWithSpan,
  stampInteractionFromRequest,
} from "@obsunified/telemetry-sdk";

declare const req: { method: string; path: string; headers: Headers };

const span = createRequestSpan("my-service", `${req.method} ${req.path}`);
stampInteractionFromRequest(span, req);

try {
  await runWithSpan(span, async () => {
    // Child spans, logs, and feature flags created here inherit the interaction id.
  });
} finally {
  span.end();
  await Promise.all([flushSpans(), flushLogs(), flushAICalls()]);
}
```

### Client-side async continuity [#client-side-async-continuity]

Auto-correlation handles synchronous handlers and shallow `await` chains. For debounces, timers, and state-machine ticks, capture and restore the interaction context.

```ts check
import {
  currentInteractionId,
  withInteractionContext,
} from "@obsunified/analytics-sdk";

const clickId = currentInteractionId();

setTimeout(() => {
  withInteractionContext(clickId!, () => {
    fetch("/api/long-running-task");
  });
}, 300);
```

## AI and LLM span tracking [#ai-and-llm-span-tracking]

### OpenInference-style spans (recommended) [#openinference-style-spans-recommended]

```ts check
import { startLLMSpan, startToolSpan } from "@obsunified/telemetry-sdk";

declare function myLLMApiCall(): Promise<{ text: string; prompt_tokens: number; completion_tokens: number }>;
declare function searchDb(): Promise<unknown>;

const llmSpan = startLLMSpan({
  name: "user-query-completion",
  model: "gpt-4o",
  provider: "openai",
  input: "What is the capital of France?",
});

try {
  const result = await myLLMApiCall();
  llmSpan.setOutput(result.text);
  llmSpan.setTokens({
    prompt: result.prompt_tokens,
    completion: result.completion_tokens,
    total: result.prompt_tokens + result.completion_tokens,
  });
  llmSpan.setCost(0.0035);
} finally {
  llmSpan.end();
}

const toolSpan = startToolSpan({
  name: "pg-vector-search",
  parameters: { query: "paris coordinates" },
});

try {
  const data = await searchDb();
  toolSpan.setOutput(data);
} finally {
  toolSpan.end();
}
```

### Agent Action Graph helpers [#agent-action-graph-helpers]

`startAgentRun(opts, fn)` is async: it opens the run, calls `fn(run)`, and closes the run when `fn` settles (a thrown error marks the run failed and is rethrown). `agentId` and `agentName` are required. Use `run.withAction(...)` (or the standalone `withAction`) to scope an action; `withAction` takes `ActionContextOptions` (`actionId`, `rootActionId`, `causedByActionId`, `interactionId`, `agentRunId`, `actorType`, `actorId`). The autonomy level is set on the run via `autonomyLevel`.

```ts check
import { startAgentRun } from "@obsunified/telemetry-sdk";

await startAgentRun(
  {
    agentId: "triage-agent",
    agentName: "Triage agent",
    goal: "Classify the incoming incident",
    autonomyLevel: "read_only",
  },
  async (run) => {
    await run.withAction({ actorType: "agent", actorId: "triage-agent" }, async () => {
      // Child spans, LLM calls, and tool calls inside this callback link to the action graph.
    });
    run.setOutcome("classified");
  },
);
```

## Cloudflare Workers wrappers [#cloudflare-workers-wrappers]

Import these from `@obsunified/telemetry-sdk/cloudflare` to avoid pulling heavy ambient type dependencies into Node.js environments.

```ts check
import { wrapD1, wrapFetch, wrapR2 } from "@obsunified/telemetry-sdk/cloudflare";

declare const env: {
  DATABASE: Parameters<typeof wrapD1>[0];
  STORAGE_BUCKET: Parameters<typeof wrapR2>[0];
};

const db = wrapD1(env.DATABASE);
const bucket = wrapR2(env.STORAGE_BUCKET, { bucketName: "blobs" });
const telemetryFetch = wrapFetch(globalThis.fetch);
```

## Cross-language mapping [#cross-language-mapping]

| Concept / action   | TypeScript SDK                           | Go SDK                               | Rust SDK                                    |
| ------------------ | ---------------------------------------- | ------------------------------------ | ------------------------------------------- |
| Exporter init      | `initObservability(config)`              | `obs.Init(ctx, config)`              | `obs_unified::init(config)`                 |
| HTTP stamp         | `stampInteractionFromRequest(span, req)` | `obs.StampInteraction(ctx, r)`       | `obs_unified::stamp_interaction(span, req)` |
| LLM tracking span  | `startLLMSpan(options)`                  | `obs.StartLLMSpan(ctx, name, opts)`  | `obs_unified::start_llm_span(name, opts)`   |
| Tool tracking span | `startToolSpan(options)`                 | `obs.StartToolSpan(ctx, name, opts)` | `obs_unified::start_tool_span(name, opts)`  |
| Project id         | `extraHeaders: { "x-project-id": id }`   | `obs.SetProjectID(ctx, id)`          | `obs_unified::set_project_id(id)`           |
| Capture exception  | `annotateErrorSpan(span, error)`         | `obs.AnnotateError(ctx, span, err)`  | `obs_unified::annotate_error(span, err)`    |
