LangChain Integration

Updated on Aug 14, 2026

Use this integration when your LangChain application is implemented in Python or TypeScript.

Setup

  1. Install SDK
bash
pip install progress-observability

Install the langchain package, not only langchain-core. Framework instrumentation activates only when the langchain (or langgraph) distribution is installed. On -core alone the app runs and LLM spans arrive, but chain structure is never emitted — silently.

  1. Instrument your app
python
Observability.instrument(
    app_name=os.getenv("OBSERVABILITY_APP_NAME"),
    api_key=os.getenv("OBSERVABILITY_API_KEY")
)
  1. Complete example
python
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain.agents import create_agent
from progress.observability import Observability

load_dotenv()

# LLM INSTRUMENTATION
Observability.instrument(
    app_name=os.getenv("OBSERVABILITY_APP_NAME"),
    api_key=os.getenv("OBSERVABILITY_API_KEY")
)

model = ChatOpenAI(
  api_key=os.getenv("OPENAI_API_KEY"),
  model="gpt-4o-mini"
)

@tool
def get_weather(location: str) -> str:
  """Get the weather for a given location."""
  return f"The weather in {location} is cloudy with a high of 15°C."

agent = create_agent(
  model=model,
  tools=[get_weather],
  system_prompt="You are a helpful AI assistant."
)

try:
  result = agent.invoke({
    "messages": [
      {"role": "user", "content": "What's the weather in Paris?"}
    ]
  })
finally:
  Observability.shutdown()
  1. Install SDK
bash
npm install @progress/observability
  1. Instrument your app
TS
import '@progress/observability/register/hooks';
import { Observability } from '@progress/observability';
await Observability.instrument({
 appName: process.env.OBSERVABILITY_APP_NAME,
 apiKey: process.env.OBSERVABILITY_API_KEY
});
  1. Complete example

In ESM, import LangChain modules dynamically, after instrument() — static imports load LangChain before instrumentation is ready and can bypass it.

TS
// bootstrap.ts — run with: tsx bootstrap.ts
import '@progress/observability/register/hooks';
import 'dotenv/config';

import { z } from 'zod';
import { Observability } from '@progress/observability';

await Observability.instrument({
 appName: process.env.OBSERVABILITY_APP_NAME ?? 'my-langchain-app',
 apiKey: process.env.OBSERVABILITY_API_KEY,
});

try {
 // LangChain imports AFTER instrument()
 const { ChatOpenAI } = await import('@langchain/openai');
 const { tool } = await import('@langchain/core/tools');
 const { createReactAgent } = await import('@langchain/langgraph/prebuilt');
 const { HumanMessage } = await import('@langchain/core/messages');

 const model = new ChatOpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  model: process.env.OPENAI_MODEL ?? 'gpt-4o-mini',
 });

 const getWeather = tool(
  async ({ location }: { location: string }) =>
   `The weather in ${location} is cloudy with a high of 15°C.`,
  {
   name: 'get_weather',
   description: 'Get the weather for a given location.',
   schema: z.object({ location: z.string() }),
  }
 );

 const agent = createReactAgent({
  llm: model,
  tools: [getWeather],
  prompt: 'You are a helpful AI assistant.',
 });

 const result = await agent.invoke({
  messages: [new HumanMessage("What's the weather in Paris?")],
 });

 console.log(result.messages[result.messages.length - 1].content);
} finally {
 await Observability.shutdown();
}

Troubleshooting

Separate spans instead of a unified trace tree

We recommend using LangChain version 1.0.0 or later. With older versions, traces may appear as separate spans rather than a unified tree.

If upgrading is not an option, you can work around this by blocking the built-in OpenAI/Azure OpenAI auto-instrumentation via blockInstruments. The LangChain callback handler already captures LLM calls with the correct parent context, model name, and provider, so blocking these instrumentations prevents duplicate orphaned spans:

TS
import { Observability, ObservabilityInstruments } from '@progress/observability';

await Observability.instrument({
 appName: process.env.OBSERVABILITY_APP_NAME,
 apiKey: process.env.OBSERVABILITY_API_KEY,
 blockInstruments: new Set([
  ObservabilityInstruments.AZURE_OPENAI,
  ObservabilityInstruments.OPENAI,
 ]),
});
In this article
Setup
Not finding the help you need?
Contact Support