LangChain

Trace LangChain and LangGraph in Python and TypeScript.

LangChain and LangGraph are captured automatically — LLM calls, chains, tools, and retrievers all become spans, including LangGraph node boundaries and tool loops. A run self-roots, so just instrumenting renders a complete trace with no extra wrapper.

Prerequisites

pip install -U "neatlogs[langchain]" langchain-openai

Usage

import os
import neatlogs

neatlogs.init(
    api_key=os.environ["NEATLOGS_API_KEY"],
    workflow_name="langchain-demo",
    instrumentations=["langchain"],
)

# Import LangChain AFTER init() so it's patched.
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o")

print(llm.invoke("In one sentence, what is LangChain?").content)

neatlogs.flush()
neatlogs.shutdown()

The instrumented run opens a WORKFLOW root automatically — even a bare llm.invoke() renders on its own. To group several calls (or your own @span functions) under one trace, wrap the entry point with a root; see Grouping calls into one trace.

For LangGraph, use the same setup — instrumentations=["langchain"] in Python (it captures graph execution), and the langchainHandler() callback in TypeScript. Pass instrumentations=["langgraph"] only if you need LangGraph-specific node/edge spans on top of the LLM spans.

Python note: for most LangGraph apps, "langchain" is all you need — it captures calls through langchain_openai, langchain_anthropic, etc. automatically.

TypeScript / LangGraph note: attach langchainHandler() to the model/LLM call (e.g. inside the LLM node), not to graph.invoke(). Passing it at the graph level can produce duplicate, noisy chain spans.

On this page