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

# Install and instrument

> Install the TypeScript SDK, set an API key, and configure tracing by hand.

<Note>To use an agent for automatic setup, see the [Quickstart](/sdks/typescript/quickstart).</Note>

## Sign up

If you don't have a Braintrust account, sign up for free at [braintrust.dev](https://www.braintrust.dev/signup).

## Install the SDK

Add the Braintrust SDK to your project using your preferred package manager:

<CodeGroup>
  ```bash pnpm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  pnpm add braintrust
  ```

  ```bash npm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  npm install braintrust --save
  ```

  ```bash yarn theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  yarn add braintrust
  ```

  ```bash deno theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  deno add npm:braintrust
  ```
</CodeGroup>

## Set an API key

On the **<Icon icon="settings-2" /> Settings** > [**<Icon icon="key-square" /> API keys**](https://www.braintrust.dev/app/~/configuration/org/api-keys) page,
create an API key. Then, set it as an environment variable:

```bash .env theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
BRAINTRUST_API_KEY="your-api-key"
```

The SDK picks up your API key automatically. When you're done testing locally, remember to set it in production.

<Warning>
  Never put your API key in version control.
</Warning>

## Configure tracing

The way to instrument your application to automatically collect traces depends on the runtime and framework you are using.

<AccordionGroup>
  <Accordion title="Node.js" icon="https://img.logo.dev/nodejs.org?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    Braintrust auto-instrumentation for Node.js uses a startup hook. The hook patches supported AI libraries as your process starts, logging your LLM calls.

    <Info>**Version Requirement:** Node.js 18.19.0+ or 20.6.0+ and above.</Info>

    <Note>If you are using a bundler to build your application, also follow the guide for your specific bundler below. ([Vite](#vite), [Esbuild](#esbuild), [Rollup](#rollup), or [Webpack](#webpack))</Note>

    <Steps>
      <Step title="Initialize the logger">
        Call `initLogger()` once, as soon as possible on application startup, before making any AI calls. The SDK reads `BRAINTRUST_API_KEY` from the environment configured above.

        ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger } from "braintrust";

        initLogger({
          projectName: "My Project",
        });
        ```
      </Step>

      <Step title="Run with the import hook">
        Start your Node.js application with the Braintrust hook:

        ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        node --import braintrust/hook.mjs app.js
        ```
      </Step>
    </Steps>

    After following these steps, calls to your AI provider should be traced.
    For a list of all supported AI providers see [TypeScript SDK integrations](/sdks/typescript/sdk-integrations).
  </Accordion>

  <Accordion title="Cloudflare" icon="https://img.logo.dev/cloudflare.com?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls from your Cloudflare app, wrap your AI provider's SDK with Braintrust. The example below uses OpenAI (for other providers, see [TypeScript SDK integrations](/sdks/typescript/sdk-integrations)).

    <Note>If you are using a bundler to build your application, also follow the guide for your specific bundler below. ([Vite](#vite), [Esbuild](#esbuild), [Rollup](#rollup), or [Webpack](#webpack))</Note>

    <Tabs>
      <Tab title="Cloudflare Workers">
        <Steps>
          <Step title="Set Cloudflare secrets">
            Store your Braintrust API key as Cloudflare secret:

            <CodeGroup>
              ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
              wrangler secret put BRAINTRUST_API_KEY
              ```
            </CodeGroup>
          </Step>

          <Step title="Setting the Node.js compatibility flag">
            Since the Braintrust SDK uses the Node.js `AsyncLocalStorage` API, you need to enable Node.js compatibility in your Wrangler configuration:

            <CodeGroup>
              ```json wrangler.jsonc theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
              {
                "compatibility_flags": ["nodejs_compat"]
              }
              ```

              ```toml wrangler.toml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
              compatibility_flags = ["nodejs_compat"]
              ```
            </CodeGroup>
          </Step>

          <Step title="Initialize the logger and wrap your client">
            Inside `fetch`, initialize the logger with secrets from the `env` binding, wrap your OpenAI client, and pass `logger.flush()` to `ctx.waitUntil()` so buffered logs ship after the response returns.

            ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
            import { initLogger, wrapOpenAI } from "braintrust";
            import OpenAI from "openai";

            interface Env {
              BRAINTRUST_API_KEY: string;
              OPENAI_API_KEY: string;
            }

            export default {
              async fetch(
                request: Request,
                env: Env,
                ctx: ExecutionContext,
              ): Promise<Response> {
                // Set up the braintrust logger
                const logger = initLogger({
                  projectName: "My Project",
                  apiKey: env.BRAINTRUST_API_KEY,
                });

                // Wrap the AI provider client
                const openAIClient = wrapOpenAI(
                  new OpenAI({
                    apiKey: env.OPENAI_API_KEY,
                  }),
                );

                try {
                  const result = await openAIClient.responses.create({
                    model: "gpt-5-mini",
                    input: "What is the capital of France?",
                  });
                } finally {
                  // Flush all tracing data to Braintrust in the background
                  ctx.waitUntil(logger.flush());
                }

                return Response.json(result);
              },
            };
            ```
          </Step>
        </Steps>
      </Tab>

      <Tab title="Cloudflare Pages">
        <Steps>
          <Step title="Set Cloudflare secrets">
            Store your Braintrust API key as Cloudflare secret:

            <CodeGroup>
              ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
              wrangler pages secret put BRAINTRUST_API_KEY
              ```
            </CodeGroup>
          </Step>

          <Step title="Setting the Node.js compatibility flag">
            Since the Braintrust SDK uses the Node.js `AsyncLocalStorage` API, you need to enable Node.js compatibility in your Wrangler configuration:

            <CodeGroup>
              ```json wrangler.jsonc theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
              {
                "compatibility_flags": ["nodejs_compat"]
              }
              ```

              ```toml wrangler.toml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
              compatibility_flags = ["nodejs_compat"]
              ```
            </CodeGroup>
          </Step>

          <Step title="Initialize the logger and wrap your client">
            Inside `onRequest`, initialize the logger with secrets from the `context.env` binding, wrap your OpenAI client, and pass `logger.flush()` to `context.waitUntil()` so buffered logs ship after the response returns.

            ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
            import { initLogger, wrapOpenAI } from "braintrust";
            import OpenAI from "openai";

            interface Env {
              BRAINTRUST_API_KEY: string;
              OPENAI_API_KEY: string;
            }

            export const onRequest: PagesFunction<Env> = async (context) => {
              // Set up the braintrust logger
              const logger = initLogger({
                projectName: "My Project",
                apiKey: context.env.BRAINTRUST_API_KEY,
              });

              // Wrap the AI provider client
              const openAIClient = wrapOpenAI(
                new OpenAI({
                  apiKey: context.env.OPENAI_API_KEY,
                }),
              );

              try {
                const result = await openAIClient.responses.create({
                  model: "gpt-5-mini",
                  input: "What is the capital of France?",
                });
              } finally {
                // Flush all tracing data to Braintrust in the background
                context.waitUntil(logger.flush());
              }

              return Response.json(result);
            };
            ```
          </Step>
        </Steps>
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title="Deno" icon="https://img.logo.dev/deno.com?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls from your Deno app, wrap your AI provider's SDK with Braintrust. The example below uses OpenAI (for other providers, see [TypeScript SDK integrations](/sdks/typescript/sdk-integrations)).

    <Note>If you are using a bundler to build your application, also follow the guide for your specific bundler below. ([Vite](#vite), [Esbuild](#esbuild), [Rollup](#rollup), or [Webpack](#webpack))</Note>

    <Steps>
      <Step title="Initialize the logger and wrap your client">
        Read your `BRAINTRUST_API_KEY` from `Deno.env`, initialize Braintrust, and wrap the provider client before making AI calls.

        ```typescript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger, wrapOpenAI } from "npm:braintrust";
        import OpenAI from "npm:openai";

        const braintrustApiKey = Deno.env.get("BRAINTRUST_API_KEY");

        const logger = initLogger({
          projectName: "My Project",
          apiKey: braintrustApiKey,
        });

        const openAIClient = wrapOpenAI(new OpenAI());

        try {
          const result = await openAIClient.responses.create({
            model: "gpt-5-mini",
            input: "What is the capital of France?",
          });
        } finally {
          await logger.flush();
        }

        console.log(result.output_text);
        ```
      </Step>

      <Step title="Run with Deno permissions">
        Grant environment variable access via `--allow-env` and network access for Braintrust via `--allow-net` and run your application.

        ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        deno run \
          --allow-env=BRAINTRUST_API_KEY \
          --allow-net=www.braintrust.dev,api.braintrust.dev,api-eu.braintrust.dev \
          main.ts
        ```
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="AWS Lambda" icon="https://img.logo.dev/aws.amazon.com?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls from a Node.js Lambda function, initialize Braintrust outside the handler **once**, wrap your AI provider's SDK, and flush before the invocation returns. AWS Lambda does not keep background promises alive after the handler completes, so set `asyncFlush: false` when initializing the logger.

    <Note>If you are using a bundler to build your application, also follow the guide for your specific bundler below. ([Vite](#vite), [Esbuild](#esbuild), [Rollup](#rollup), or [Webpack](#webpack))</Note>

    <Steps>
      <Step title="Initialize the logger and wrap your client">
        Create the logger and provider client at module scope so Lambda can reuse them across warm invocations.

        ```typescript lambda.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger, wrapOpenAI } from "braintrust";
        import OpenAI from "openai";

        const logger = initLogger({
          projectName: "My Project",
          apiKey: process.env.BRAINTRUST_API_KEY,
          asyncFlush: false,
        });

        const openAIClient = wrapOpenAI(new OpenAI());

        export async function handler() {
          try {
            const result = await openAIClient.responses.create({
              model: "gpt-5-mini",
              input: "What is the capital of France?",
            });

            return {
              statusCode: 200,
              headers: { "content-type": "application/json" },
              body: JSON.stringify({
                answer: result.output_text,
              }),
            };
          } finally {
            await logger.flush();
          }
        }
        ```
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="Next.js" icon="https://img.logo.dev/nextjs.org?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls from a Next.js app, wrap your Next.js config and initialize Braintrust in Next's `instrumentation.ts`.

    <Steps>
      <Step title="Configure the Next.js Config">
        Wrap your Next.js Config with `wrapNextjsConfigWithBraintrust`.

        ```typescript next.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { createRequire } from "module";
        import { type NextConfig } from "next";

        import { wrapNextjsConfigWithBraintrust } from "braintrust/next";

        const nextConfig: NextConfig = {};

        export default wrapNextjsConfigWithBraintrust(nextConfig);
        ```
      </Step>

      <Step title="Initialize the logger">
        Create `instrumentation.ts` in the project root, or `src/instrumentation.ts` if your app uses `src/` and initialize the logger.

        ```typescript instrumentation.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger } from "braintrust";

        export function register() {
          if (process.env.NEXT_RUNTIME === "nodejs" || process.env.NEXT_RUNTIME === "edge") {
            initLogger({
              projectName: "My Project",
            });
          }
        }
        ```
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="Nest.js" icon="https://img.logo.dev/nestjs.com?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls from a Nest.js application, initialize Braintrust before Nest creates your application module, then start the Node.js process with the Braintrust hook.

    <Steps>
      <Step title="Initialize the logger">
        Call `initLogger()` before `NestFactory.create()` and adding an import for `braintrust/apply-auto-instrumentation`. This ensures Braintrust is ready before Nest constructs providers that may create AI clients.

        ```typescript src/main.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        // Add the `braintrust/apply-auto-instrumentation` import before any other imports.
        // Import order is important because the Braintrust import can only instrument subsequent imports.
        import "braintrust/apply-auto-instrumentation":

        import { NestFactory } from "@nestjs/core";
        import { initLogger } from "braintrust";

        import { AppModule } from "./app.module";

        initLogger({
          projectName: "My Project",
        });

        async function bootstrap() {
          const app = await NestFactory.create(AppModule);
          await app.listen(process.env.PORT ?? 3000);
        }

        void bootstrap();
        ```
      </Step>

      <Step title="Start Nest with the import hook">
        Update the scripts you use to run Nest so every normal launch path loads `braintrust/hook.mjs`. For development with `nest start`, use `NODE_OPTIONS` so the hook is inherited by the Nest CLI's Node process. For production, pass `--import` to the compiled app directly.

        ```json package.json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        {
          "scripts": {
            "start": "NODE_OPTIONS=\"--import braintrust/hook.mjs\" nest start",
            "start:dev": "NODE_OPTIONS=\"--import braintrust/hook.mjs\" nest start --watch",
            "start:prod": "node --import braintrust/hook.mjs dist/main.js"
          }
        }
        ```
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="Nitro" icon="https://img.logo.dev/nitro.build?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls from a Nitro server, initialize Braintrust when Nitro starts, add the Braintrust Rollup plugin to the Nitro server build, and flush traces from global middleware.

    <Steps>
      <Step title="Instrument the server bundle">
        Add the Braintrust Rollup plugin to `nitro.config.ts`. Nitro builds the server bundle with Rollup, so this instruments supported AI SDK packages during the Nitro build.

        ```typescript nitro.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { braintrustRollupPlugin } from "braintrust/rollup";
        import { defineConfig } from "nitro";

        export default defineConfig({
          rollupConfig: {
            plugins: [braintrustRollupPlugin()],
          },
        });
        ```
      </Step>

      <Step title="Initialize the logger">
        Add a Nitro plugin that initializes Braintrust once when Nitro starts.

        ```typescript plugins/braintrust.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger } from "braintrust";
        import { definePlugin } from "nitro";

        export default definePlugin(() => {
          initLogger({
            projectName: "My Project",
          });
        });
        ```
      </Step>

      <Step title="Add a flush middleware">
        Add a global middleware that runs after each handler calling `flush()` in a `finally` block and pass the promise to `event.waitUntil()`.
        This will make Nitro keep the runtime alive long enough to send buffered traces after the response is ready on runtimes that are supported (like Vercel and Cloudflare).

        ```typescript middleware/braintrust.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { flush } from "braintrust";
        import { defineMiddleware } from "nitro";

        export default defineMiddleware(async (event, next) => {
          try {
            return await next();
          } finally {
            event.waitUntil(flush());
          }
        });
        ```
      </Step>
    </Steps>

    After following these steps, calls to your AI provider should be traced.
    For a list of all supported AI providers see [TypeScript SDK integrations](/sdks/typescript/sdk-integrations).
  </Accordion>

  <Accordion title="Nuxt" icon="https://img.logo.dev/nuxt.com?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls from a Nuxt app, instrument both Nuxt's Vite build and Nitro's server build, then initialize Braintrust from a Nitro plugin.

    <Steps>
      <Step title="Instrument the Nuxt build">
        Nuxt uses Vite for the client build and Rollup through Nitro for the server build. Add both Braintrust plugins to `nuxt.config.ts`.

        ```typescript nuxt.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { braintrustRollupPlugin } from "braintrust/rollup";
        import { braintrustVitePlugin } from "braintrust/vite";

        export default defineNuxtConfig({
          vite: {
            plugins: [braintrustVitePlugin()],
          },
          nitro: {
            rollupConfig: {
              plugins: [braintrustRollupPlugin()],
            },
          },
        });
        ```
      </Step>

      <Step title="Initialize from a Nitro plugin">
        Add a server plugin that initializes Braintrust when Nitro starts and schedules a flush after each response.

        ```typescript server/plugins/braintrust.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger } from "braintrust";

        export default defineNitroPlugin((nitroApp) => {
          initLogger({
            projectName: "My Project",
          });
        });
        ```
      </Step>

      <Step title="Add a flush middleware">
        Add a global middleware that runs on each request calling `flush()` and pass the promise to `event.waitUntil()`.
        This will make Nuxt keep the runtime alive long enough to send buffered traces after the response is ready on runtimes that are supported (like Vercel and Cloudflare).

        ```typescript middleware/braintrust.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { flush } from "braintrust";

        export default defineEventHandler((event) => {
          event.waitUntil(flush());
        });
        ```
      </Step>

      <Step title="Start Nuxt with the import hook">
        Update the scripts you use to run Nuxt so every normal launch path loads `braintrust/hook.mjs`. For development with `nuxt dev`, use `NODE_OPTIONS` so the hook is inherited by the Nuxt CLI's Node process. For production, pass `--import` to the compiled app directly.

        ```json package.json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        {
          "scripts": {
            "dev": "NODE_OPTIONS=\"--import braintrust/hook.mjs\" nuxt dev",
            "preview": "NODE_OPTIONS=\"--import braintrust/hook.mjs\" nuxt preview"
          }
        }
        ```
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="React Router Framework" icon="https://img.logo.dev/reactrouter.com?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls in React Router Framework applications, add the Braintrust Vite plugin to the config, initialize the logger in the server entry, and add a node import hook to your server start.

    <Steps>
      <Step title="Instrument the Vite build">
        Add the Braintrust Vite plugin to `vite.config.ts` alongside the React Router plugin.

        ```typescript vite.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { reactRouter } from "@react-router/dev/vite";
        import { defineConfig } from "vite";

        import { braintrustVitePlugin } from "braintrust/vite";

        export default defineConfig(() => ({
          plugins: [
            braintrustVitePlugin(),
            reactRouter(),
          ],
        }));
        ```
      </Step>

      <Step title="Initialize the logger">
        If your app uses the default hidden server entry, reveal it first:

        ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        npx react-router reveal entry.server
        ```

        Then call `initLogger()` in the module scope before importing or constructing any AI clients.

        ```typescript app/entry.server.tsx theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger } from "braintrust";

        initLogger({
          projectName: "My Project",
        });
        ```
      </Step>

      <Step title="Add the Braintrust loader hook">
        Run your server with the Braintrust import hook:

        ```json package.json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        {
          "scripts": {
            "start": "NODE_OPTIONS=\"--import braintrust/hook.mjs\" react-router-serve ./build/server/index.js"
          }
        }
        ```
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="SvelteKit" icon="https://img.logo.dev/svelte.dev?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls on SvelteKit applications, add the Braintrust Vite plugin and initialize the braintrust logger.

    <Steps>
      <Step title="Instrument the Vite build">
        Add the Braintrust Vite plugin before `sveltekit()` in `vite.config.ts`.

        ```typescript vite.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { sveltekit } from "@sveltejs/kit/vite";
        import { defineConfig } from "vite";

        import { braintrustVitePlugin } from "braintrust/vite";

        export default defineConfig(() => ({
          plugins: [
            braintrustVitePlugin(),
            sveltekit(),
          ],
        }));
        ```
      </Step>

      <Step title="Initialize and flush from server hooks">
        Code in SvelteKit hook modules runs when the app starts. Initialize Braintrust at module scope and flush from `handle`.

        ```typescript src/hooks.server.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { flush, initLogger } from "braintrust";
        import { type Handle } from "@sveltejs/kit";

        initLogger({
          projectName: "My Project",
        });

        export const handle: Handle = async ({ event, resolve }) => {
          try {
            return await resolve(event);
          } finally {
            void flush();
          }
        };
        ```
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="TanStack Start" icon="https://img.logo.dev/tanstack.com?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    To trace LLM calls from TanStack Start, initialize Braintrust in `src/start.ts`, add global request middleware to flush traces, and instrument the Vite build.

    <Steps>
      <Step title="Instrument the Vite build">
        Add the Braintrust Vite plugin:

        ```typescript vite.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { tanstackStart } from "@tanstack/react-start/plugin/vite";
        import viteReact from "@vitejs/plugin-react";
        import { nitro } from "nitro/vite";
        import { defineConfig } from "vite";

        import { braintrustVitePlugin } from "braintrust/vite";

        export default defineConfig(() => ({
          plugins: [
            braintrustVitePlugin(),
            tanstackStart(),
            nitro(),
            viteReact(),
          ],
        }));
        ```
      </Step>

      <Step title="Initialize and flush from global middleware">
        Initialize Braintrust in module scope of a global middleware and flush in a `finally` block.

        ```typescript src/start.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import {
          createCsrfMiddleware,
          createMiddleware,
          createStart,
        } from "@tanstack/react-start";
        import { flush, initLogger } from "braintrust";

        initLogger({
          projectName: "My Project",
        });

        const braintrustMiddleware = createMiddleware().server(
          async ({ next }) => {
            try {
              return await next();
            } finally {
              void flush();
            }
          },
        );

        export const startInstance = createStart(() => ({
          requestMiddleware: [braintrustMiddleware],
        }));
        ```
      </Step>

      <Step title="Add the Braintrust loader hook">
        Run your server with the Braintrust import hook:

        ```json package.json theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        {
          "scripts": {
            "start": "node --import braintrust/hook.mjs .output/server/index.mjs"
          }
        }
        ```
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="Vite" icon="https://img.logo.dev/vite.dev?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    Add the Braintrust Vite plugin to your Vite config. The plugin instruments supported AI packages at build time.

    ```typescript vite.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { defineConfig } from "vite";
    import { braintrustVitePlugin } from "braintrust/vite";

    export default defineConfig({
      plugins: [braintrustVitePlugin()],
    });
    ```
  </Accordion>

  <Accordion title="esbuild" icon="https://img.logo.dev/esbuild.github.io?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    Add the Braintrust esbuild plugin to the `plugins` array in your build script. The plugin runs during bundling and instruments supported AI SDK packages before the bundle is written.

    ```typescript build.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import * as esbuild from "esbuild";
    import { braintrustEsbuildPlugin } from "braintrust/esbuild";

    await esbuild.build({
      entryPoints: ["src/index.ts"],
      bundle: true,
      format: "esm",
      outfile: "dist/index.js",
      plugins: [braintrustEsbuildPlugin()],
    });
    ```
  </Accordion>

  <Accordion title="Webpack" icon="https://img.logo.dev/webpack.js.org?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    Add the Braintrust Webpack plugin to your Webpack config. The plugin instruments supported AI SDK packages at build time.

    ```typescript webpack.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { braintrustWebpackPlugin } from "braintrust/webpack";

    export default {
      plugins: [braintrustWebpackPlugin()],
    };
    ```
  </Accordion>

  <Accordion title="Rollup" icon="https://img.logo.dev/rollupjs.org?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
    Add the Braintrust Rollup plugin to your Rollup config. The plugin instruments supported AI SDK packages during the Rollup build.

    ```typescript rollup.config.ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { braintrustRollupPlugin } from "braintrust/rollup";

    export default {
      input: "src/index.ts",
      output: {
        dir: "dist",
        format: "esm",
      },
      plugins: [braintrustRollupPlugin()],
    };
    ```
  </Accordion>
</AccordionGroup>

Useful setup information:

* If you are manually flushing, make sure to put the `flush()` call into a `finally` block so that the SDK still sends your traces even when the code failed. Braintrust will track failing LLM calls.
* Even if you are bundling your application using a bundler, set up the platform/runtime specific auto-instrumentation like `--import` in addition to the bundler plugins so that if certain dependencies don't get bundled, they will still be instrumented.
* If you are deploying your application on Cloudflare, find a way to call `flush()` as part of `ctx.waitUntil(flush())`, `event.waitUntil(flush())`, or the framework's equivalent request-lifetime primitive.
* For sveltekit when deploying on Vercel, Netlify or cloudflare, you may need to use the platforms `waitUntil` functionality to properly flush events.

## Verify tracing

Run your app and make an AI call. A trace will show up in your [Braintrust Logs](https://www.braintrust.dev/app/~/logs), usually within seconds.

<Check>If traces appear in Braintrust, you've successfully set up the SDK.</Check>

If your traces don't appear in Braintrust, see [Troubleshooting](/sdks/typescript/troubleshooting).

## Next steps

Learn more about using the SDK to observe, evaluate, and improve your AI application:

* [Instrument](/instrument) — trace LLM calls and application logic
* [Observe](/observe) — search and analyze production traces
* [Annotate](/annotate) — label traces and build datasets
* [Evaluate](/evaluate) — measure quality and catch regressions
* [Deploy](/deploy) — ship to production with the AI gateway
