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

# LangGraph

> Trace LangGraph graph execution in Braintrust to debug agent runs, inspect node transitions, evaluate models, and monitor production usage

[LangGraph](https://langchain-ai.github.io/langgraph/) is a library for building stateful, multi-actor applications with LLMs. Braintrust traces LangGraph graph execution, including node transitions and the model calls each node makes.

**TypeScript**

Trace LangGraph graphs built with the `@langchain/langgraph` and `@langchain/core` packages.

## Setup

Install LangGraph alongside Braintrust and the LangChain packages you use.

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

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

## Auto-instrumentation

To trace LangGraph graphs 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/langgraph` v1 or later.

**1. Initialize Braintrust and build your graph**

```javascript title="trace-langgraph-auto.js" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import { END, START, StateGraph, Annotation } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
import { initLogger } from "braintrust";

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

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

const StateAnnotation = Annotation.Root({
  message: Annotation(),
});

const graph = new StateGraph(StateAnnotation)
  .addNode("sayHello", async () => {
    const res = await model.invoke("Say hello");
    return { message: res.content };
  })
  .addNode("sayBye", () => ({ message: "Bye." }))
  .addEdge(START, "sayHello")
  .addEdge("sayHello", "sayBye")
  .addEdge("sayBye", END)
  .compile();

await graph.invoke({});
```

**2. Run with the import hook**

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
node --import braintrust/hook.mjs trace-langgraph-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 and run the compiled file with the import hook, or [run TypeScript directly](https://docs.braintrust.dev/instrument/trace-llm-calls.md#auto-instrumentation) with a TypeScript loader.

> [!NOTE]
>
> If you're using a bundler, see [Trace LLM calls](https://docs.braintrust.dev/instrument/trace-llm-calls.md#auto-instrumentation) for plugin and loader setup.

## Manual instrumentation

To control the LangChain handler yourself, construct a `BraintrustLangChainCallbackHandler` and pass it through the `callbacks` option when you invoke the graph.

```typescript title="trace-langgraph.ts" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import {
  BraintrustLangChainCallbackHandler,
} from "braintrust";
import { END, START, StateGraph, Annotation } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
import { initLogger } from "braintrust";

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

const handler = new BraintrustLangChainCallbackHandler({ logger });

const StateAnnotation = Annotation.Root({
  message: Annotation(),
});

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

async function sayHello(_state: typeof StateAnnotation.State) {
  const res = await model.invoke("Say hello");
  return { message: res.content };
}

function sayBye(_state: typeof StateAnnotation.State) {
  console.log("From the 'sayBye' node: Bye world!");
  return {};
}

async function main() {
  const graphBuilder = new StateGraph(StateAnnotation)
    .addNode("sayHello", sayHello)
    .addNode("sayBye", sayBye)
    .addEdge(START, "sayHello")
    .addEdge("sayHello", "sayBye")
    .addEdge("sayBye", END);

  const helloWorldGraph = graphBuilder.compile();

  await helloWorldGraph.invoke({}, { callbacks: [handler] });
}

main();
```

## What Braintrust traces

Braintrust logs each step of a graph run as a span nested under the graph invocation:

* Graph and node execution spans (chain runs), with each step's inputs, outputs, and LangChain tags.
* Chat model and LLM spans (`ChatOpenAI` and similar), with the input messages or prompts, the serialized model configuration and request parameters, and the full response including generated messages.
* Model name metadata resolved from each model response.
* Token usage metrics (`prompt_tokens`, `completion_tokens`, `tokens`, `prompt_cached_tokens`, cache-creation tokens, and `completion_reasoning_tokens` when the provider reports them).
* Time to first token (`time_to_first_token`) for streaming model calls.
* Tool spans (named for the tool), with the parsed tool input and the tool output.
* Retriever spans, with the query as input and the retrieved documents as output.
* Errors captured on the failing model, chain, tool, or retriever span.

## Resources

* [LangGraph documentation](https://langchain-ai.github.io/langgraph/).
* [LangChain integration](https://docs.braintrust.dev/integrations/sdk-integrations/langchain.md).

## LangGraph Platform SDK

Trace runs dispatched to a deployed [LangGraph Platform](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) server using the `@langchain/langgraph-sdk` package.

### Setup

Install the LangGraph Platform SDK alongside `braintrust`.

```bash pnpm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
pnpm add braintrust @langchain/langgraph-sdk
```

```bash npm theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
npm install braintrust @langchain/langgraph-sdk
```

### Auto-instrumentation

To trace `RunsClient.wait()` and `RunsClient.stream()` calls without modifying your application code, initialize Braintrust normally, then run your app with Braintrust's import hook. Requires `@langchain/langgraph-sdk` v1.9.25 or later.

**1. Initialize Braintrust and call your deployed graph**

```javascript title="trace-langgraph-sdk-auto.js" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import { Client } from "@langchain/langgraph-sdk";
import { initLogger } from "braintrust";

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

const client = new Client({
  apiUrl: process.env.LANGGRAPH_API_URL,
});

const result = await client.runs.wait(null, "agent", {
  input: { messages: [{ role: "user", content: "Say hello" }] },
});
```

**2. Run with the import hook**

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
node --import braintrust/hook.mjs trace-langgraph-sdk-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 and run the compiled file with the import hook, or [run TypeScript directly](https://docs.braintrust.dev/instrument/trace-llm-calls.md#auto-instrumentation) with a TypeScript loader.

> [!NOTE]
>
> If you're using a bundler, see [Trace LLM calls](https://docs.braintrust.dev/instrument/trace-llm-calls.md#auto-instrumentation) for plugin and loader setup.

### Manual instrumentation

To instrument the LangGraph Platform SDK without modifying every call site, wrap your client once with `wrapLangGraphSDK`. All subsequent `runs.wait()` and `runs.stream()` calls on the wrapped client are traced automatically.

```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import { Client } from "@langchain/langgraph-sdk";
import { initLogger, wrapLangGraphSDK } from "braintrust";

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

const raw = new Client({
  apiUrl: process.env.LANGGRAPH_API_URL,
});
const client = wrapLangGraphSDK(raw);

const result = await client.runs.wait(null, "agent", {
  input: { messages: [{ role: "user", content: "Say hello" }] },
});
```

### What Braintrust traces

Braintrust captures:

* Run wait spans (`runs.wait`), with the thread ID, assistant ID, and run options as input, and the final graph state as output.
* Run stream spans (`runs.stream`), with the thread ID, assistant ID, and run options as input. Each streamed event is consumed without individual child spans.
* Errors on any span that fails, including HTTP errors from the LangGraph server.

### Resources

* [LangGraph Platform documentation](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/).
* [`@langchain/langgraph-sdk` on npm](https://www.npmjs.com/package/@langchain/langgraph-sdk).

**Python**

Trace LangGraph graphs built with the `langgraph` and `langchain-core` packages.

## Setup

Install LangGraph alongside Braintrust and the LangChain packages you use.

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

## Auto-instrumentation

To trace LangGraph graphs without modifying your application code, call `braintrust.auto_instrument()` before importing LangGraph, then initialize your logger.

```python title="trace-langgraph-auto.py" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
from typing import TypedDict

import braintrust

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

from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, StateGraph

class GraphState(TypedDict, total=False):
    message: str

def main():
    model = ChatOpenAI(model="gpt-5-mini")

    def say_hello(state: GraphState):
        response = model.invoke("Say hello")
        return {"message": response.content}

    def say_bye(state: GraphState):
        return {"message": f"{state.get('message', '')} Bye."}

    workflow = (
        StateGraph(state_schema=GraphState)
        .add_node("sayHello", say_hello)
        .add_node("sayBye", say_bye)
        .add_edge(START, "sayHello")
        .add_edge("sayHello", "sayBye")
        .add_edge("sayBye", END)
    )

    graph = workflow.compile()
    result = graph.invoke({})
    print(result)

if __name__ == "__main__":
    main()
```

## Manual instrumentation

To control the handler yourself, construct a `BraintrustCallbackHandler` and register it as the global handler with `set_global_handler`.

```python title="trace-langgraph.py" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import asyncio
import os
from typing import TypedDict

from braintrust import init_logger
from braintrust.integrations.langchain import BraintrustCallbackHandler, set_global_handler
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, StateGraph

class GraphState(TypedDict, total=False):
    message: str

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

    handler = BraintrustCallbackHandler()
    set_global_handler(handler)

    model = ChatOpenAI(model="gpt-5-mini")

    def say_hello(state: GraphState):
        response = model.invoke("Say hello")
        return {"message": response.content}

    def say_bye(state: GraphState):
        return {"message": f"{state.get('message', '')} Bye."}

    workflow = (
        StateGraph(state_schema=GraphState)
        .add_node("sayHello", say_hello)
        .add_node("sayBye", say_bye)
        .add_edge(START, "sayHello")
        .add_edge("sayHello", "sayBye")
        .add_edge("sayBye", END)
    )

    graph = workflow.compile()
    result = await graph.ainvoke({})
    print(result)

if __name__ == "__main__":
    asyncio.run(main())
```

## What Braintrust traces

Braintrust logs each step of a graph run as a span nested under the graph invocation:

* Graph and node execution spans (a `LangGraph` root span plus one span per node, each named for the node), with each step's inputs, outputs, and LangChain tags.
* Chat model and LLM spans (`ChatOpenAI` and similar), with the input messages or prompts, the serialized model configuration and request parameters, and the full response including generated messages.
* Model and provider metadata resolved from each model response.
* Token usage metrics (`prompt_tokens`, `completion_tokens`, `total_tokens`, `tokens`, `prompt_cached_tokens`, and cache-creation tokens).
* Time to first token (`time_to_first_token`) for streaming model calls.
* Tool spans (named for the tool), with the tool input and the tool output.
* Retriever spans, with the query as input and the retrieved documents as output.
* Errors captured on the failing model, chain, tool, or retriever span.

## Resources

* [LangGraph documentation](https://langchain-ai.github.io/langgraph/).
* [LangChain integration](https://docs.braintrust.dev/integrations/sdk-integrations/langchain.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.