LangChain Tutorial (Python): adding observability for intermediate developers
This tutorial shows you how to add observability to a LangChain Python app so you can see prompts, tool calls, model outputs, latency, and failures in one place. You need this when your chain works in dev but becomes hard to debug once real users, retries, and branching logic are involved.
What You'll Need
- •Python 3.10+
- •A LangChain app using
langchainandlangchain-openai - •An OpenAI API key set as
OPENAI_API_KEY - •A LangSmith account and API key set as
LANGSMITH_API_KEY - •Optional but recommended:
- •
LANGSMITH_TRACING=true - •
LANGSMITH_PROJECT=<your-project-name>
- •
- •Packages:
- •
langchain - •
langchain-openai - •
langsmith
- •
Step-by-Step
- •Install the packages and set your environment variables.
LangSmith is the observability layer here: it captures traces from your LangChain run so you can inspect each step after execution.
pip install langchain langchain-openai langsmith
export OPENAI_API_KEY="your-openai-key"
export LANGSMITH_API_KEY="your-langsmith-key"
export LANGSMITH_TRACING="true"
export LANGSMITH_PROJECT="langchain-observability-tutorial"
- •Build a minimal chain that we can instrument.
Use a prompt template plus a chat model so you have a real chain with a clear input/output path to trace.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "You are a concise assistant."),
("human", "Explain {topic} in one paragraph.")
])
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
chain = prompt | llm
result = chain.invoke({"topic": "observability in LangChain"})
print(result.content)
- •Turn on tracing explicitly in code for local runs and scripts.
Environment variables are enough in many cases, but setting tracing in code makes the behavior obvious and keeps the script self-contained.
import os
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_PROJECT"] = "langchain-observability-tutorial"
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "You are a concise assistant."),
("human", "Summarize {topic} for an engineer.")
])
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
chain = prompt | llm
response = chain.invoke({"topic": "trace visibility"})
print(response.content)
- •Add custom metadata so traces are useful in production.
Tags and metadata let you filter runs by environment, tenant, feature flag, or request type when you start collecting lots of traces.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful support assistant."),
("human", "Draft a reply to: {message}")
])
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
chain = prompt | llm
response = chain.invoke(
{"message": "I was charged twice for my subscription."},
config={
"tags": ["support", "billing", "prod"],
"metadata": {"customer_tier": "gold", "ticket_source": "email"}
}
)
print(response.content)
- •Instrument intermediate steps with a custom runnable function.
This is where observability becomes useful for debugging business logic, not just model calls: you can trace preprocessing, validation, or routing decisions.
from langchain_core.runnables import RunnableLambda
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
def normalize_message(inputs: dict) -> dict:
text = inputs["message"].strip()
return {"message": text[:500]}
prompt = ChatPromptTemplate.from_messages([
("system", "You are a support agent."),
("human", "{message}")
])
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
pipeline = RunnableLambda(normalize_message) | prompt | llm
output = pipeline.invoke({"message": " Please cancel my plan immediately. "})
print(output.content)
Testing It
Run one of the scripts above from your terminal and confirm you get a normal model response printed locally. Then open your LangSmith project and check that the run appears with the prompt, model call, timing information, tags, and metadata attached.
If you used the custom runnable example, verify that the preprocessing step shows up as its own span in the trace tree. If something fails, LangSmith should show whether the issue came from input formatting, the prompt layer, or the LLM call itself.
Next Steps
- •Add tools and inspect tool-call traces end to end.
- •Learn how to attach callbacks for custom logging or metrics.
- •Split traces by environment and tenant using tags and metadata conventions.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit