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

# LangChain

> Trace LangChain applications in Braintrust to debug prompts, evaluate models, and monitor production usage

If you are a coding agent, prefer the Braintrust [`bt` CLI](/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, such as ad-hoc lookups and exploration from your IDE.

[LangChain](https://www.langchain.com/) is a framework for developing applications powered by language models. Braintrust traces LangChain applications from your code.

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

  Install Braintrust alongside the LangChain JS packages.

  <CodeGroup>
    ```bash pnpm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    pnpm add braintrust @braintrust/langchain-js @langchain/core@^1 @langchain/openai@^1
    ```

    ```bash npm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    npm install braintrust @braintrust/langchain-js @langchain/core@^1 @langchain/openai@^1
    ```
  </CodeGroup>

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

  To trace LangChain calls without modifying your application code, initialize Braintrust normally, then run your app with Braintrust's import hook to patch `@langchain/core` at runtime. Requires `@langchain/core` v0.3.42 or later. The same hook traces [LangGraph](/integrations/agent-frameworks/langgraph) graphs, which run through the LangChain callback path.

  <Steps>
    <Step title="Initialize Braintrust and call LangChain">
      <CodeGroup>
        ```javascript title="trace-langchain-auto.js" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import { initLogger } from "braintrust";
        import { ChatOpenAI } from "@langchain/openai";

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

        const model = new ChatOpenAI({ model: "gpt-5-mini" });

        const response = await model.invoke("What is the capital of France?");
        console.log(response.content);
        ```
      </CodeGroup>
    </Step>

    <Step title="Run with the import hook">
      ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
      node --import braintrust/hook.mjs trace-langchain-auto.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](/instrument/trace-llm-calls#auto-instrumentation) for plugin and loader setup.
      </Note>
    </Step>
  </Steps>

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

  To trace LangChain calls manually, attach `BraintrustCallbackHandler` to each call's `callbacks` option yourself.

  <CodeGroup>
    ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    import { BraintrustCallbackHandler } from "@braintrust/langchain-js";
    import { ChatOpenAI } from "@langchain/openai";
    import { initLogger } from "braintrust";

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

    const handler = new BraintrustCallbackHandler();

    async function main() {
      const model = new ChatOpenAI({ modelName: "gpt-5-mini" });

      await model.invoke("What is the capital of France?", {
        callbacks: [handler],
      });
    }

    main();
    ```
  </CodeGroup>

  Run it:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  npx ts-node trace-langchain.ts
  ```

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

  Braintrust captures:

  * LLM and chat model calls, chains, agents, tools, and retrievers as separate spans, with inputs and outputs preserved
  * Token usage on LLM spans (`prompt_tokens`, `completion_tokens`, `total_tokens`, `prompt_cached_tokens`, `prompt_cache_creation_tokens`)
  * `time_to_first_token` on streaming responses, captured on the first new-token callback
  * Model name and serialized invocation parameters in span metadata
  * Errors from any callback captured on the span

  <h2 id="tracing-resources-typescript">
    Tracing resources
  </h2>

  * [LangChain JS documentation](https://js.langchain.com/docs/introduction/)
  * [`@braintrust/langchain-js` on npm](https://www.npmjs.com/package/@braintrust/langchain-js)
</View>

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

  Install Braintrust alongside the LangChain Python packages.

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  pip install braintrust langchain-core langchain-openai
  ```

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

  To trace LangChain calls without modifying your application code, call `braintrust.auto_instrument()` before importing LangChain.

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

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

    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI

    prompt = ChatPromptTemplate.from_template("What is 1 + {number}?")
    model = ChatOpenAI(model="gpt-5-mini")
    chain = prompt | model

    response = chain.invoke({"number": "2"})
    print(response.content)
    ```
  </CodeGroup>

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

  To register the callback handler yourself instead of using auto-instrumentation, configure `BraintrustCallbackHandler` and pass it to `set_global_handler`.

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

    from braintrust import init_logger
    from braintrust.integrations.langchain import BraintrustCallbackHandler, set_global_handler
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_openai import ChatOpenAI


    async def main():
        init_logger(project="My Project", api_key=os.environ["BRAINTRUST_API_KEY"])

        handler = BraintrustCallbackHandler()
        set_global_handler(handler)

        prompt = ChatPromptTemplate.from_template("What is 1 + {number}?")
        model = ChatOpenAI(model="gpt-5-mini")
        chain = prompt | model

        response = await chain.ainvoke({"number": "2"})
        print(response.content)


    if __name__ == "__main__":
        asyncio.run(main())
    ```
  </CodeGroup>

  Run it:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  python trace-langchain.py
  ```

  The same callback handler also works with [LangGraph](/integrations/agent-frameworks/langgraph).

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

  Braintrust captures:

  * LLM and chat model calls, chains, agents, tools, and retrievers as separate spans, with inputs and outputs preserved
  * Token usage on LLM spans (`prompt_tokens`, `completion_tokens`, `total_tokens`, `tokens`, `prompt_cached_tokens`)
  * Anthropic prompt cache creation tokens, broken out by TTL as `prompt_cache_creation_5m_tokens` and `prompt_cache_creation_1h_tokens` when available, or `prompt_cache_creation_tokens` otherwise
  * `time_to_first_token` on streaming responses, captured on the first new-token callback
  * Model name and serialized invocation parameters in span metadata
  * Errors from any callback captured on the span

  <h2 id="tracing-resources-python">
    Tracing resources
  </h2>

  * [LangGraph integration](/integrations/agent-frameworks/langgraph)
  * [LangChain callback documentation](https://python.langchain.com/docs/how_to/#callbacks)
  * [LangChain official documentation](https://python.langchain.com/docs/introduction/)
</View>

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

  Install the Braintrust Go SDK alongside LangChainGo.

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  go get github.com/braintrustdata/braintrust-sdk-go
  go get github.com/braintrustdata/braintrust-sdk-go/trace/contrib/langchaingo
  go get github.com/tmc/langchaingo
  ```

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

  To trace LangChainGo calls, create a `tracelangchaingo.NewHandlerWithOptions` callback handler and pass it as a callback option on your LLM.

  <CodeGroup>
    ```go Go theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
    package main

    import (
    	"context"
    	"fmt"
    	"log"

    	"github.com/tmc/langchaingo/llms"
    	"github.com/tmc/langchaingo/llms/openai"
    	"go.opentelemetry.io/otel"
    	"go.opentelemetry.io/otel/sdk/trace"

    	"github.com/braintrustdata/braintrust-sdk-go"
    	tracelangchaingo "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/langchaingo"
    )

    func main() {
    	// Initialize Braintrust tracing with blocking login
    	tp := trace.NewTracerProvider()
    	defer tp.Shutdown(context.Background())
    	otel.SetTracerProvider(tp)

    	bt, err := braintrust.New(tp,
    		braintrust.WithProject("My Project"),
    		braintrust.WithBlockingLogin(true),
    	)
    	if err != nil {
    		log.Fatal(err)
    	}

    	// Create the Braintrust callback handler
    	handler := tracelangchaingo.NewHandlerWithOptions(tracelangchaingo.HandlerOptions{
    		Model:          "gpt-5-mini",
    		Provider:       "openai",
    		TracerProvider: tp,
    	})

    	// Create LangChainGo LLM with the callback handler
    	llm, err := openai.New(openai.WithCallback(handler))
    	if err != nil {
    		log.Fatal(err)
    	}

    	// Create a root span to group operations
    	tracer := otel.Tracer("langchain-example")
    	ctx, rootSpan := tracer.Start(context.Background(), "trace-langchain")
    	defer rootSpan.End()

    	// Use LangChainGo as normal - all calls will be logged to Braintrust
    	messages := []llms.MessageContent{
    		llms.TextParts(llms.ChatMessageTypeHuman, "What is the capital of France?"),
    	}
    	resp, err := llm.GenerateContent(ctx, messages)
    	if err != nil {
    		log.Fatal(err)
    	}
    	if len(resp.Choices) > 0 {
    		fmt.Printf("Answer: %s\n", resp.Choices[0].Content)
    	}

    	// Print the permalink to view traces
    	fmt.Printf("\nView traces: %s\n", bt.Permalink(rootSpan))
    }
    ```
  </CodeGroup>

  Run it:

  ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  go run trace-langchain.go
  ```

  <h3 id="tracing-embeddings-go">
    Tracing embeddings
  </h3>

  LangChainGo's callback system does not fire for embedding calls, so the standard `tracelangchaingo.NewHandlerWithOptions` handler used above does not cover embeddings. To trace embeddings, explicitly wrap your embedder with `tracelangchaingo.WrapEmbedder`. The wrapped value implements `embeddings.Embedder` and is a drop-in replacement for the original — `EmbedDocuments` and `EmbedQuery` calls are captured as LLM spans.

  ```go #skip-compile theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
  import (
  	"github.com/tmc/langchaingo/embeddings"
  	"github.com/tmc/langchaingo/llms/openai"

  	tracelangchaingo "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/langchaingo"
  )

  llm, err := openai.New()
  if err != nil {
  	log.Fatal(err)
  }

  inner, err := embeddings.NewEmbedder(llm)
  if err != nil {
  	log.Fatal(err)
  }

  embedder := tracelangchaingo.WrapEmbedder(inner,
  	tracelangchaingo.WithEmbedderTracerProvider(tp),
  	tracelangchaingo.WithEmbedderProvider("openai"),
  	tracelangchaingo.WithEmbedderModel("text-embedding-ada-002"),
  )

  vectors, err := embedder.EmbedDocuments(ctx, []string{"hello", "world"})
  ```

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

  Braintrust captures:

  * LLM `GenerateContent` calls, chains, tools, agents, and retrievers as separate spans, with inputs converted to OpenAI-format messages and outputs in OpenAI-format choices (role, content, finish\_reason)
  * Streaming output reconstructed by accumulating chunks delivered through `HandleStreamingFunc`
  * Token usage on LLM spans (`prompt_tokens`, `completion_tokens`, `tokens`, `prompt_cached_tokens`, `prompt_cache_creation_tokens`)
  * Reasoning content, function calls, tool calls, and stop reasons in LLM output
  * Embedding calls via `WrapEmbedder`: input texts, embedding count, and embedding dimensions
  * Errors from any handler captured on the span

  <h2 id="tracing-resources-go">
    Tracing resources
  </h2>

  * [LangChainGo documentation](https://github.com/tmc/langchaingo)
  * [Go SDK example](https://github.com/braintrustdata/braintrust-sdk-go/tree/main/examples/langchaingo)
</View>
