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/openai
bash

Minimal 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] },
)
ts

Install (Python)

pip install spanlens langchain langchain-openai
bash

Minimal 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]},
)
python

What gets captured

LangChain eventSpanlens spanNotes
on_chain_start / on_chain_endkind="agent_step"Chain input/output captured as span attributes.
on_llm_start / on_llm_endkind="llm"Model, tokens, cost, response body. Streaming captured.
on_tool_start / on_tool_endkind="tool"Tool name, arguments, return value.
on_agent_action / on_agent_finishkind="agent_step"Agent reasoning step with the tool the agent picked.
on_chain_error / on_llm_errorspan 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] },
)
ts

Where to go next