LangChain integration
LangChain (JS and Python) exposes a callback contract that fires for every chain start, LLM call, tool invocation, and agent step. The Spanlens callback handler attaches to that contract once and captures the full execution tree without modifying your chains.
Install (TypeScript)
pnpm add @spanlens/sdk
# plus your existing langchain install:
pnpm add @langchain/core @langchain/openaibashMinimal setup (TypeScript)
import { SpanlensClient } from '@spanlens/sdk'
import { createSpanlensCallbackHandler } from '@spanlens/sdk/langchain'
import { ChatOpenAI } from '@langchain/openai'
import { ChatPromptTemplate } from '@langchain/core/prompts'
const client = new SpanlensClient()
const handler = createSpanlensCallbackHandler({ client })
const model = new ChatOpenAI({ model: 'gpt-4o-mini' })
const prompt = ChatPromptTemplate.fromMessages([
['system', 'You are a helpful assistant.'],
['user', '{question}'],
])
const chain = prompt.pipe(model)
// Attach at invocation time:
const result = await chain.invoke(
{ question: 'What is LLM observability?' },
{ callbacks: [handler] },
)tsInstall (Python)
pip install spanlens langchain langchain-openaibashMinimal setup (Python)
from spanlens import SpanlensClient
from spanlens.langchain import SpanlensCallbackHandler
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
client = SpanlensClient()
handler = SpanlensCallbackHandler(client=client)
model = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant."),
("user", "{question}"),
])
chain = prompt | model
result = chain.invoke(
{"question": "What is LLM observability?"},
config={"callbacks": [handler]},
)pythonWhat gets captured
| LangChain event | Spanlens span | Notes |
|---|---|---|
on_chain_start / on_chain_end | kind="agent_step" | Chain input/output captured as span attributes. |
on_llm_start / on_llm_end | kind="llm" | Model, tokens, cost, response body. Streaming captured. |
on_tool_start / on_tool_end | kind="tool" | Tool name, arguments, return value. |
on_agent_action / on_agent_finish | kind="agent_step" | Agent reasoning step with the tool the agent picked. |
on_chain_error / on_llm_error | span with status="error" | Error message and stack captured for debugging. |
Agents with tools
For LangChain agents, the same handler captures the full reasoning loop: agent action, tool call, tool result, next agent action. The trace renders as a waterfall span tree with the critical path highlighted.
import { AgentExecutor, createOpenAIFunctionsAgent } from 'langchain/agents'
import { DynamicTool } from '@langchain/core/tools'
const tools = [
new DynamicTool({
name: 'search',
description: 'Search the knowledge base.',
func: async (input) => '...',
}),
]
const agent = await createOpenAIFunctionsAgent({ llm: model, tools, prompt })
const executor = new AgentExecutor({ agent, tools })
await executor.invoke(
{ input: 'Find me the latest pricing.' },
{ callbacks: [handler] },
)tsWhere to go next
- LangGraph, native graph integration with critical-path highlighting.
- Agent tracing concepts, span tree structure.
- Agent tracing tutorial, end-to-end RAG example.