> ## 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](/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.

[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](/docs/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](/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 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](/docs/integrations/agent-frameworks/langgraph) and [Deep Agents](/docs/integrations/agent-frameworks/deepagents).

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

  * [Deep Agents integration](/docs/integrations/agent-frameworks/deepagents)
  * [LangGraph integration](/docs/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>
