Documentation Index
Fetch the complete documentation index at: https://mintlify.com/getsentry/sentry-javascript/llms.txt
Use this file to discover all available pages before exploring further.
The LangGraph integration automatically instruments LangGraph applications, capturing agent creation, invocation, and state management.
Installation
The integration is enabled by default in Node.js:
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: 'your-dsn',
// langGraphIntegration is included by default
});
Basic Usage
Just use LangGraph normally:
import { StateGraph } from '@langchain/langgraph';
import { ChatOpenAI } from '@langchain/openai';
const model = new ChatOpenAI();
// Define graph
const workflow = new StateGraph({
channels: {
messages: {
value: (left, right) => left.concat(right),
default: () => [],
},
},
});
workflow.addNode('agent', async (state) => {
const response = await model.invoke(state.messages);
return { messages: [response] };
});
workflow.addEdge('__start__', 'agent');
workflow.addEdge('agent', '__end__');
// Automatically instrumented
const app = workflow.compile();
const result = await app.invoke({
messages: [{ role: 'user', content: 'Hello!' }],
});
Configuration
Default Behavior
By default, inputs and outputs are not captured:
Sentry.init({
dsn: 'your-dsn',
sendDefaultPii: false, // Default: no inputs/outputs
});
Global Setting
LangGraph Only
Enable for all AI integrations:Sentry.init({
dsn: 'your-dsn',
sendDefaultPii: true, // Captures all inputs/outputs
});
Enable only for LangGraph:Sentry.init({
dsn: 'your-dsn',
sendDefaultPii: false,
integrations: [
Sentry.langGraphIntegration({
recordInputs: true,
recordOutputs: true,
}),
],
});
Integration Options
recordInputs
boolean
default:"sendDefaultPii"
Capture input messages from graph state
recordOutputs
boolean
default:"sendDefaultPii"
Capture output messages and responses
Captured Operations
The integration captures two main operations:
Agent Creation
const workflow = new StateGraph({...});
// ... add nodes and edges
// Creates: gen_ai.create_agent span
const app = workflow.compile();
Captured Data:
- Agent name
- Available tools
- Graph configuration
Agent Invocation
// Creates: gen_ai.invoke_agent span
const result = await app.invoke({ messages: [...] });
Captured Data:
- Input messages (if
recordInputs: true)
- Output messages (if
recordOutputs: true)
- Tool calls made during execution
- Graph state transitions
Practical Examples
Simple Agent
import * as Sentry from '@sentry/node';
import { StateGraph } from '@langchain/langgraph';
import { ChatOpenAI } from '@langchain/openai';
const model = new ChatOpenAI({ modelName: 'gpt-4' });
const workflow = new StateGraph({
channels: {
messages: {
value: (left, right) => left.concat(right),
default: () => [],
},
},
});
workflow.addNode('assistant', async (state) => {
const response = await model.invoke(state.messages);
return { messages: [response] };
});
workflow.addEdge('__start__', 'assistant');
workflow.addEdge('assistant', '__end__');
const app = workflow.compile();
// Automatically tracked
const result = await app.invoke({
messages: [{ role: 'user', content: 'What is AI?' }],
});
import { StateGraph } from '@langchain/langgraph';
import { ChatOpenAI } from '@langchain/openai';
import { DynamicTool } from '@langchain/core/tools';
const model = new ChatOpenAI({ modelName: 'gpt-4' });
const tools = [
new DynamicTool({
name: 'search',
description: 'Search the web',
func: async (query) => {
return `Search results for: ${query}`;
},
}),
new DynamicTool({
name: 'calculator',
description: 'Perform calculations',
func: async (expression) => {
return eval(expression).toString();
},
}),
];
const workflow = new StateGraph({
channels: {
messages: { value: (l, r) => l.concat(r), default: () => [] },
toolCalls: { value: null },
},
});
// Agent node - decides whether to use tools
workflow.addNode('agent', async (state) => {
const response = await model.invoke(state.messages, {
tools: tools.map(t => ({
name: t.name,
description: t.description,
})),
});
return {
messages: [response],
toolCalls: response.tool_calls || [],
};
});
// Tool execution node
workflow.addNode('tools', async (state) => {
const results = [];
for (const toolCall of state.toolCalls) {
const tool = tools.find(t => t.name === toolCall.name);
if (tool) {
const result = await tool.func(toolCall.args);
results.push({
role: 'tool',
content: result,
tool_call_id: toolCall.id,
});
}
}
return { messages: results };
});
// Conditional edge - use tools if needed
workflow.addConditionalEdges(
'agent',
(state) => (state.toolCalls?.length > 0 ? 'tools' : '__end__'),
{
tools: 'tools',
__end__: '__end__',
}
);
workflow.addEdge('__start__', 'agent');
workflow.addEdge('tools', 'agent');
const app = workflow.compile();
// Tool usage automatically tracked
const result = await app.invoke({
messages: [{ role: 'user', content: 'What is 15 * 23?' }],
});
Multi-Agent System
import { StateGraph } from '@langchain/langgraph';
import { ChatOpenAI } from '@langchain/openai';
const researcher = new ChatOpenAI({ modelName: 'gpt-4' });
const writer = new ChatOpenAI({ modelName: 'gpt-4' });
const editor = new ChatOpenAI({ modelName: 'gpt-4' });
const workflow = new StateGraph({
channels: {
topic: { value: null },
research: { value: null },
draft: { value: null },
final: { value: null },
},
});
// Research agent
workflow.addNode('research', async (state) => {
const response = await researcher.invoke(
`Research the topic: ${state.topic}`
);
return { research: response.content };
});
// Writer agent
workflow.addNode('write', async (state) => {
const response = await writer.invoke(
`Write an article based on this research:\n${state.research}`
);
return { draft: response.content };
});
// Editor agent
workflow.addNode('edit', async (state) => {
const response = await editor.invoke(
`Edit and improve this article:\n${state.draft}`
);
return { final: response.content };
});
workflow.addEdge('__start__', 'research');
workflow.addEdge('research', 'write');
workflow.addEdge('write', 'edit');
workflow.addEdge('edit', '__end__');
const app = workflow.compile();
// Full multi-agent workflow tracked
const result = await app.invoke({
topic: 'The future of artificial intelligence',
});
Stateful Conversation
import { StateGraph } from '@langchain/langgraph';
import { ChatOpenAI } from '@langchain/openai';
import { MemorySaver } from '@langchain/langgraph';
const model = new ChatOpenAI();
const workflow = new StateGraph({
channels: {
messages: {
value: (left, right) => left.concat(right),
default: () => [],
},
},
});
workflow.addNode('chat', async (state) => {
const response = await model.invoke(state.messages);
return { messages: [response] };
});
workflow.addEdge('__start__', 'chat');
workflow.addEdge('chat', '__end__');
// Compile with memory
const checkpointer = new MemorySaver();
const app = workflow.compile({ checkpointer });
// Conversation with state
const config = { configurable: { thread_id: 'conversation-1' } };
// First message
await app.invoke(
{ messages: [{ role: 'user', content: 'My name is Alice' }] },
config
);
// Second message - remembers context
await app.invoke(
{ messages: [{ role: 'user', content: 'What is my name?' }] },
config
);
// Response: "Your name is Alice"
Captured Span Attributes
When recordInputs and recordOutputs are enabled:
{
// Agent creation
'gen_ai.agent.name': 'my_agent',
'gen_ai.agent.tools': ['search', 'calculator'],
// Agent invocation
'gen_ai.operation.name': 'invoke_agent',
'gen_ai.prompt.0.role': 'user',
'gen_ai.prompt.0.content': 'What is 2+2?',
'gen_ai.completion.0.role': 'assistant',
'gen_ai.completion.0.content': '2+2 equals 4',
// Tool usage
'gen_ai.tool_calls': [
{ name: 'calculator', args: '2+2', result: '4' }
],
}
Viewing LangGraph Data
LangGraph operations appear as spans:
Transaction: POST /api/agent
├─ gen_ai.create_agent
│ └─ Duration: 5ms
├─ gen_ai.invoke_agent
│ ├─ langchain.llm.start (GPT-4)
│ │ └─ Duration: 2.1s
│ ├─ langchain.tool.start (calculator)
│ │ └─ Duration: 15ms
│ └─ Duration: 2.5s
└─ Total: 2.5s
- Agent Execution Time: Track workflow performance
- Tool Performance: Monitor tool call latency
- State Transitions: Identify bottlenecks
- Error Rates: Track failures in agent execution
Source Code
The LangGraph integration is implemented in:
packages/node/src/integrations/tracing/langgraph/index.ts:11
Best Practices
Use descriptive node names for better observability in traces.
Add Custom Context
workflow.addNode('agent', async (state) => {
return await Sentry.startSpan(
{
name: 'Agent Decision',
attributes: {
'agent.state_size': JSON.stringify(state).length,
'agent.message_count': state.messages.length,
},
},
async () => {
const response = await model.invoke(state.messages);
return { messages: [response] };
}
);
});
Troubleshooting
Spans Not Appearing
Ensure tracing is enabled:
Sentry.init({
dsn: 'your-dsn',
tracesSampleRate: 1.0,
});
Enable output recording to capture tool calls:
Sentry.langGraphIntegration({
recordOutputs: true,
});