Skip to main content
@bryel/browser traces AI-SDK calls that run in the browser — when your agent issues model calls from client code rather than a server. It ships the same OpenInference spans as the server SDK, batched and non-blocking, with no app-boot cost.
If your model calls run on a server (Next.js route handlers, server actions), use @bryel/vercel instead — it adds nothing to your client bundle.
1

Create a browser key

In the dashboard, open Settings → API keys → Browser key and list the origins your app runs on (e.g. https://app.example.com). You get a publishable bkp_… key: write-only and locked to those origins, so it is safe to ship in client code.
2

Install

bun add @bryel/browser
3

Create a tracer and pass it per call

Build the tracer where you trace — not at app boot — and hand it to the AI SDK. Spans flush in the background.
import { createBryelTracer } from "@bryel/browser";
import { streamText } from "ai";

const tracer = createBryelTracer({ apiKey: "bkp_…", serviceName: "studio-agent" });

await streamText({
  model,
  experimental_telemetry: { isEnabled: true, tracer, metadata: { sessionId, userId } },
  prompt,
});
4

Verify

Run a call, then open the trace explorer — the model, tokens, cost, and tool calls appear, exactly as with the server SDK.

Why it won’t slow your app

  • No app-boot cost. With createBryelTracer you build the tracer only where you trace; nothing runs at startup, and the package lazy-imports.
  • Non-blocking. Spans batch and POST in the background, off your request path — calls never wait on export, and export failures are swallowed (never thrown into your app).
  • ~21 KB gzipped, all-in. Lazy-load it so it stays off your critical boot path.

Excluding traffic

Capture is per call. Gate isEnabled on your own logic to skip a cohort — e.g. isEnabled: tier !== "enterprise" — and those calls emit no spans at all; their data never leaves the browser.

Global registration (optional)

If your app has no other OpenTelemetry setup, register a global provider and drop the tracer:
import { registerBryelBrowser } from "@bryel/browser";

registerBryelBrowser({ apiKey: "bkp_…", serviceName: "studio-agent" });
// then: experimental_telemetry: { isEnabled: true }
Use a publishable bkp_ key in the browser — never a secret bk_ key. A browser bundle is public; bkp_ keys are write-only and origin-locked, bk_ keys are not.
For all options, see the @bryel/browser reference.