LangGraph for Express
Adds instrumentation for the LangGraph SDK. (default)
Requires SDK version 11.0.0 or higher. On earlier versions, see the Agent Tracing setup for your SDK.
Import name: Sentry.langGraphIntegration
This integration is enabled by default when tracing is enabled. If you'd like to modify your default integrations, read this.
The langGraphIntegration adds instrumentation for @langchain/langgraph to capture agent tracing gen_ai spans, recording model, token usage, latency, and (when enabled) inputs and outputs.
Sentry.init({
dsn: "___PUBLIC_DSN___",
// Tracing must be enabled for agent tracing to work
tracesSampleRate: 1.0,
integrations: [Sentry.langGraphIntegration()],
});
Sentry.init({
dsn: "___PUBLIC_DSN___",
// Tracing must be enabled for agent tracing to work
tracesSampleRate: 1.0,
integrations: [Sentry.langGraphIntegration()],
});
By default, tracing support is added to the following LangGraph operations:
- Agent Creation (
gen_ai.create_agent) - Captures spans when compiling a StateGraph into an executable agent - Agent Invocation (
gen_ai.invoke_agent) - Captures spans for agent execution viainvoke() - Classifier Evaluations (
gen_ai.decide) - Captures spans forTypeSafeClassifiercalls in graph nodes
Available since: v11.7.0
When a graph node calls a TypeSafeClassifier from @langchain/typesafe, the LangChain integration records the call as a gen_ai.decide span. The span is a child of the graph's invoke_agent span and records the graph name as the agent name. No additional setup is needed.
import { Annotation, END, START, StateGraph } from "@langchain/langgraph";
import { TypeSafeClassifier } from "@langchain/typesafe";
const classifier = new TypeSafeClassifier({
questions: {
urgent: { type: "noul", instructions: "Is this urgent?" },
},
});
const State = Annotation.Root({
ticket: Annotation(),
urgent: Annotation(),
});
const graph = new StateGraph(State)
.addNode("triage", async (state) => {
const result = await classifier.invoke(state.ticket);
return { urgent: result.nouls.urgent.noul };
})
.addEdge(START, "triage")
.addEdge("triage", END)
.compile({ name: "triage_graph" });
await graph.invoke({ ticket: "My payouts have been failing for 3 days." });
import { Annotation, END, START, StateGraph } from "@langchain/langgraph";
import { TypeSafeClassifier } from "@langchain/typesafe";
const classifier = new TypeSafeClassifier({
questions: {
urgent: { type: "noul", instructions: "Is this urgent?" },
},
});
const State = Annotation.Root({
ticket: Annotation(),
urgent: Annotation(),
});
const graph = new StateGraph(State)
.addNode("triage", async (state) => {
const result = await classifier.invoke(state.ticket);
return { urgent: result.nouls.urgent.noul };
})
.addEdge(START, "triage")
.addEdge("triage", END)
.compile({ name: "triage_graph" });
await graph.invoke({ ticket: "My payouts have been failing for 3 days." });
The evaluation state, questions, and answers follow the LangChain integration's recordInputs and recordOutputs options.
@langchain/langgraph:>=0.2.0 <2.0.0
Type: boolean (optional)
Records inputs to LangGraph operations (such as messages and state data passed to the graph).
Defaults to true if dataCollection.genAI.inputs is true, which is the default.
Type: boolean (optional)
Records outputs from LangGraph operations (such as generated responses, agent outputs, and final state).
Defaults to true if dataCollection.genAI.outputs is true, which is the default.
Sentry.init({
dsn: "___PUBLIC_DSN___",
tracesSampleRate: 1.0,
integrations: [
Sentry.langGraphIntegration({
recordInputs: false,
recordOutputs: false,
}),
],
});
Sentry.init({
dsn: "___PUBLIC_DSN___",
tracesSampleRate: 1.0,
integrations: [
Sentry.langGraphIntegration({
recordInputs: false,
recordOutputs: false,
}),
],
});
Import names: Sentry.instrumentStateGraph, Sentry.instrumentCreateReactAgent
If your application does not use automatic instrumentation, wrap your agent after setting up Sentry. Two helpers are available, depending on how you build your agent:
instrumentStateGraph: for graphs you build yourself withStateGraph. Call it on the graph before calling.compile().instrumentCreateReactAgent: for LangGraph's prebuiltcreateReactAgent. Wrap the factory, then use the wrapped version exactly likecreateReactAgent. This also captures the model and wraps tools, so you getexecute_toolspans as well.
Both accept the same recordInputs and recordOutputs options as the integration.
Instrumenting a StateGraph:
import { ChatOpenAI } from "@langchain/openai";
import {
StateGraph,
MessagesAnnotation,
START,
END,
} from "@langchain/langgraph";
import { SystemMessage, HumanMessage } from "@langchain/core/messages";
// Create LLM call
const llm = new ChatOpenAI({
modelName: "gpt-4o",
apiKey: "your-api-key",
});
async function callLLM(state) {
const response = await llm.invoke(state.messages);
return {
messages: [...state.messages, response],
};
}
// Create the agent
const agent = new StateGraph(MessagesAnnotation)
.addNode("agent", callLLM)
.addEdge(START, "agent")
.addEdge("agent", END);
// Instrument the graph before compiling
Sentry.instrumentStateGraph(agent, {
recordInputs: false,
recordOutputs: false,
});
const graph = agent.compile({ name: "my_agent" });
// Invoke the agent
const result = await graph.invoke({
messages: [
new SystemMessage("You are a helpful assistant."),
new HumanMessage("Hello!"),
],
});
import { ChatOpenAI } from "@langchain/openai";
import {
StateGraph,
MessagesAnnotation,
START,
END,
} from "@langchain/langgraph";
import { SystemMessage, HumanMessage } from "@langchain/core/messages";
// Create LLM call
const llm = new ChatOpenAI({
modelName: "gpt-4o",
apiKey: "your-api-key",
});
async function callLLM(state) {
const response = await llm.invoke(state.messages);
return {
messages: [...state.messages, response],
};
}
// Create the agent
const agent = new StateGraph(MessagesAnnotation)
.addNode("agent", callLLM)
.addEdge(START, "agent")
.addEdge("agent", END);
// Instrument the graph before compiling
Sentry.instrumentStateGraph(agent, {
recordInputs: false,
recordOutputs: false,
});
const graph = agent.compile({ name: "my_agent" });
// Invoke the agent
const result = await graph.invoke({
messages: [
new SystemMessage("You are a helpful assistant."),
new HumanMessage("Hello!"),
],
});
Instrumenting a prebuilt createReactAgent:
import { createReactAgent } from "@langchain/langgraph/prebuilt";
// Instrument createReactAgent, then use the wrapped version in its place
const instrumentedCreateReactAgent =
Sentry.instrumentCreateReactAgent(createReactAgent);
const agent = instrumentedCreateReactAgent({ llm, tools });
import { createReactAgent } from "@langchain/langgraph/prebuilt";
// Instrument createReactAgent, then use the wrapped version in its place
const instrumentedCreateReactAgent =
Sentry.instrumentCreateReactAgent(createReactAgent);
const agent = instrumentedCreateReactAgent({ llm, tools });
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").