> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bryel.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Browser (client-side)

> Trace an AI agent that runs in the browser, with a write-only key locked to your domains.

`@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.

<Note>If your model calls run on a server (Next.js route handlers, server actions), use [`@bryel/vercel`](/frameworks/vercel) instead — it adds nothing to your client bundle.</Note>

<Steps>
  <Step title="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.
  </Step>

  <Step title="Install">
    <CodeGroup>
      ```bash bun theme={"theme":{"light":"github-light","dark":"github-dark"}}
      bun add @bryel/browser
      ```

      ```bash npm theme={"theme":{"light":"github-light","dark":"github-dark"}}
      npm i @bryel/browser
      ```

      ```bash pnpm theme={"theme":{"light":"github-light","dark":"github-dark"}}
      pnpm add @bryel/browser
      ```

      ```bash yarn theme={"theme":{"light":"github-light","dark":"github-dark"}}
      yarn add @bryel/browser
      ```
    </CodeGroup>
  </Step>

  <Step title="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.

    ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
    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,
    });
    ```
  </Step>

  <Step title="Verify">
    Run a call, then open the trace explorer — the model, tokens, cost, and tool calls appear, exactly as with the server SDK.
  </Step>
</Steps>

## 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`:

```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
import { registerBryelBrowser } from "@bryel/browser";

registerBryelBrowser({ apiKey: "bkp_…", serviceName: "studio-agent" });
// then: experimental_telemetry: { isEnabled: true }
```

<Warning>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.</Warning>

For all options, see the [`@bryel/browser` reference](/api-reference/browser).
