> ## 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.

# OpenRouter

> Trace OpenRouter SDK calls in Braintrust to debug prompts, evaluate models, and monitor production usage

If you are a coding agent, prefer the Braintrust [`bt` CLI](/docs/reference/cli/quickstart) for repeatable, scriptable work: running evals, instrumenting code, querying logs, syncing data, managing functions, and configuring coding agents. Use the MCP server for reasoning over Braintrust data in conversation, and for capabilities the CLI doesn't cover, such as monitor views, alerts, and authoring evaluators, preprocessors, and facets.

[OpenRouter](https://openrouter.ai/) lets you call models from many providers through a single API. Braintrust traces OpenRouter SDK calls, including streaming chat completions, embeddings, and the Responses API.

<View title="TypeScript" icon="https://img.logo.dev/typescriptlang.org?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
  <Tip>
    If you're using OpenRouter's agent toolkit package (`@openrouter/agent`), see [OpenRouter Agent](/docs/integrations/agent-frameworks/openrouter-agent).
  </Tip>

  <h2 id="setup-typescript">
    Setup
  </h2>

  Install the Braintrust and `@openrouter/sdk` packages, then set your API keys.

  <Steps>
    <Step title="Install packages">
      <CodeGroup>
        ```bash pnpm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        pnpm add braintrust @openrouter/sdk
        ```

        ```bash npm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        npm install braintrust @openrouter/sdk
        ```
      </CodeGroup>
    </Step>

    <Step title="Set environment variables">
      ```bash title=".env" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      OPENROUTER_API_KEY=<your-openrouter-api-key>
      BRAINTRUST_API_KEY=<your-braintrust-api-key>

      # If you are self-hosting Braintrust, set the URL of your hosted dataplane
      # BRAINTRUST_API_URL=<your-braintrust-api-url>
      ```
    </Step>
  </Steps>

  <h2 id="auto-instrumentation-typescript">
    Auto-instrumentation
  </h2>

  To trace OpenRouter SDK calls without modifying your application code, initialize Braintrust normally, then run your app with Braintrust's import hook to patch the OpenRouter SDK at runtime.

  <Steps>
    <Step title="Initialize Braintrust and call OpenRouter">
      <CodeGroup>
        ```javascript title="app.js" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger } from "braintrust";
        import { OpenRouter } from "@openrouter/sdk";

        initLogger({
          projectName: "My Project",
          apiKey: process.env.BRAINTRUST_API_KEY,
        });

        const client = new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY });

        const response = await client.chat.send({
          chatRequest: {
            model: "openai/gpt-5-mini",
            messages: [{ role: "user", content: "What is observability?" }],
          },
        });
        ```
      </CodeGroup>
    </Step>

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

      The auto-instrumentation example uses plain JavaScript so `node --import` can run the file directly. The Braintrust APIs work the same in TypeScript projects — compile your TypeScript to JavaScript, then run the compiled file with the import hook.

      <Note>
        If you're using a bundler, see [Trace LLM calls](/docs/instrument/trace-llm-calls#auto-instrumentation) for plugin and loader setup.
      </Note>
    </Step>
  </Steps>

  <h2 id="manual-instrumentation-typescript">
    Manual instrumentation
  </h2>

  To trace OpenRouter clients manually, wrap them yourself with `wrapOpenRouter`. Use this when you want to instrument specific clients individually rather than all of them globally.

  <CodeGroup>
    ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { initLogger, wrapOpenRouter } from "braintrust";
    import { OpenRouter } from "@openrouter/sdk";

    initLogger({
      projectName: "My Project",
      apiKey: process.env.BRAINTRUST_API_KEY,
    });

    const client = wrapOpenRouter(
      new OpenRouter({ apiKey: process.env.OPENROUTER_API_KEY }),
    );

    const response = await client.chat.send({
      chatRequest: {
        model: "openai/gpt-5-mini",
        messages: [{ role: "user", content: "What is observability?" }],
      },
    });
    ```
  </CodeGroup>

  <h2 id="what-traced-typescript">
    What Braintrust traces
  </h2>

  Braintrust instruments the `@openrouter/sdk` client and creates an LLM-typed span per call:

  * Chat completion spans (`openrouter.chat.send`), capturing messages as input, request parameters as metadata, and the response choices plus token usage as output. Streaming responses are aggregated (including reasoning and tool calls) and record first-token timing.
  * Embedding spans (`openrouter.embeddings.generate`), capturing input texts as input and the first embedding's vector length as output.
  * Rerank spans (`openrouter.rerank.rerank`), capturing the query and documents as input, document count and request parameters as metadata, and results as a list of `{ index, relevance_score }` items.
  * Response spans (`openrouter.beta.responses.send`), capturing input and request parameters as metadata and the response output plus token usage as output, including streaming.
  * Request metadata (model and provider parsed from the OpenRouter `provider/model` ID) and token usage metrics (prompt, completion, and total).

  <h2 id="resources-typescript">
    Resources
  </h2>

  * [OpenRouter TypeScript SDK](https://www.npmjs.com/package/@openrouter/sdk)
  * [OpenRouter API reference](https://openrouter.ai/docs)
</View>

<View title="Python" icon="https://img.logo.dev/python.org?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
  <h2 id="setup-python">
    Setup
  </h2>

  Install the Braintrust and OpenRouter packages, then set your API keys.

  <Steps>
    <Step title="Install packages">
      ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      pip install braintrust openrouter
      ```
    </Step>

    <Step title="Set environment variables">
      ```bash title=".env" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      OPENROUTER_API_KEY=<your-openrouter-api-key>
      BRAINTRUST_API_KEY=<your-braintrust-api-key>
      ```
    </Step>
  </Steps>

  <h2 id="auto-instrumentation-python">
    Auto-instrumentation
  </h2>

  To trace OpenRouter SDK calls without modifying your application code, call `braintrust.auto_instrument()` before creating your OpenRouter client.

  <CodeGroup>
    ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import os

    import braintrust

    braintrust.auto_instrument()
    braintrust.init_logger(project="My Project")

    from openrouter import OpenRouter

    client = OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"])

    response = client.chat.send(
        model="openai/gpt-5-mini",
        messages=[{"role": "user", "content": "What is observability?"}],
    )
    ```
  </CodeGroup>

  <h2 id="manual-instrumentation-python">
    Manual instrumentation
  </h2>

  To trace OpenRouter clients manually, wrap them yourself with `wrap_openrouter()`. Use this when you want to instrument specific clients individually rather than all of them globally.

  <CodeGroup>
    ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import os

    from braintrust import init_logger, wrap_openrouter
    from openrouter import OpenRouter

    init_logger(project="My Project")

    client = wrap_openrouter(OpenRouter(api_key=os.environ["OPENROUTER_API_KEY"]))

    response = client.beta.responses.send(
        model="openai/gpt-5-mini",
        input="Summarize tracing in one sentence.",
    )

    # Response shape varies; adjust indexing for your model and request.
    print(response.output[1].content[0].text)
    ```
  </CodeGroup>

  <h3 id="openai-compatible-python">
    OpenAI-compatible endpoint
  </h3>

  If your app already uses the OpenAI Python SDK with OpenRouter's OpenAI-compatible endpoint, keep that setup and use `wrap_openai()`.

  <CodeGroup>
    ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import os

    from braintrust import init_logger, wrap_openai
    from openai import OpenAI

    init_logger(project="My Project")

    client = wrap_openai(
        OpenAI(
            base_url="https://openrouter.ai/api/v1",
            api_key=os.environ["OPENROUTER_API_KEY"],
        )
    )

    response = client.responses.create(
        model="openai/gpt-5-mini",
        input="Explain routing in one sentence.",
    )

    print(response.output_text)
    ```
  </CodeGroup>

  <h2 id="what-traced-python">
    What Braintrust traces
  </h2>

  Braintrust patches the `openrouter` client and creates an LLM-typed span per call:

  * Chat completion spans (`openrouter.chat.send`), capturing messages as input, request parameters as metadata, and the response choices plus token usage as output. Streaming responses are aggregated and record first-token timing. Covers sync (`chat.send()`) and async (`chat.send_async()`) calls.
  * Embedding spans (`openrouter.embeddings.generate`), capturing input texts as input and the embedding count plus the first embedding's vector length as output. Covers sync and async calls.
  * Response spans (`openrouter.beta.responses.send`), capturing input and request parameters as metadata and the response output plus token usage as output, including streaming. Covers sync and async calls.
  * Request metadata (model and provider parsed from the OpenRouter `provider/model` ID, plus provider routing) and response metadata (response ID and service tier) when present.
  * Token usage metrics (prompt, completion, and total, plus prompt, completion, and cost detail breakdowns when reported).
  * Errors captured on every call.

  <h2 id="resources-python">
    Resources
  </h2>

  * [OpenRouter Python SDK](https://pypi.org/project/openrouter/)
  * [OpenRouter API reference](https://openrouter.ai/docs)
  * [OpenAI integration](/docs/integrations/ai-providers/openai)
</View>
