Three names, one company, three different jobs. A common source of confusion is treating them as three versions of the same thing.
LangChain, LangGraph and LangSmith are three separate products from LangChain Inc. LangChain is an open-source agent framework: a quick way to build an agent from a model, some tools and a prompt. LangGraph is an open-source runtime for stateful, long-running agents: it adds saved state, pauses for human approval and recovery from failures. LangSmith is a hosted platform (self-hosting is an Enterprise option) for tracing, evaluating and deploying agents, and it also works with agents that were built with neither library.
If you only remember one line from this guide, make it this: LangChain builds it, LangGraph runs it, LangSmith shows you whether it works. A caveat from LangChain's own team: the lines between a framework, a runtime and a harness are blurry, so treat this as a mental model, not a law.
Five questions builders ask (quick answers)
- What is each one, in one line? LangChain is the framework you build an agent with. LangGraph is the runtime that gives it saved state, human approval steps and crash recovery. LangSmith is the platform for tracing, testing and deploying it.
- Do I need all three? No. LangGraph can be used without LangChain, and LangSmith works with many frameworks, including ones that have nothing to do with LangChain Inc.
- Which should I start with? Start with LangChain's
create_agentfor a standard tool-using agent. Because LangChain agents already run on LangGraph, you can drop down to LangGraph later without switching libraries. - When should I use none of them? When one model call, or a few lines of direct code against a provider's API (Application Programming Interface), does the job. Anthropic's own guidance on building agents (December 2024) is to start there and to understand any framework's code before you rely on it.
- What changed in version 1.0? Both libraries were announced as 1.0 on 22 October 2025.
create_agentreplaced the oldercreate_react_agent, legacy chains and retrievers moved to a package calledlangchain-classic, and the team committed to no breaking changes before 2.0.
The 30-second version: a standard agent with a few tools? Use LangChain's create_agent. Runs that must pause for a person, survive a restart or follow strict branches? Add LangGraph. Need to see what the agent did, or prove a change helped? Add LangSmith, with either.
A scene you will recognise
This is an illustrative scenario, not a real company. Picture a six-person engineering team at a fintech in Hyderabad. They are building an assistant that reads refund requests, looks up the order and decides whether to approve. An engineer follows a tutorial written before LangChain 1.0 and several of the imports fail, because those pieces moved to a package called langchain-classic. They fix that, and the demo works.
Then the head of operations says: any refund above a threshold needs a manager's approval, and the manager may answer tomorrow. The team has no way to pause a run for a day and resume it exactly where it stopped, so they bolt on a queue and a database table. Two weeks later a customer disputes a refund and nobody can show what the agent saw or why it decided what it did.
Each gap has a name. The first is the framework (LangChain, used with current APIs). The second is the runtime (LangGraph: saved state and an approval pause). The third is the platform (LangSmith: traces and evaluations). The rest of this guide shows which layer solves which problem, so you reach for the right one the first time.
The question the team now asks is the one most people ask first: should we have started with LangGraph? The answer is less costly than it sounds, because LangChain's agents already run on LangGraph. There is no rewrite, only a decision about when to take more control.
The map: four names, three jobs
| Product | What it is | Layer | Package | Reach for it when |
|---|---|---|---|---|
| LangChain | Open-source (MIT, the Massachusetts Institute of Technology licence) agent framework: models, tools, prompt, middleware | Framework | langchain | You want a working tool-using agent quickly |
| LangGraph | Open-source (MIT licence) orchestration framework and runtime for stateful, long-running agents | Runtime | langgraph | You need explicit control flow, saved state, human approval or recovery after failure |
| Deep Agents | A batteries-included agent harness built on LangChain and LangGraph, with a virtual filesystem, subagents and optional planning | Harness | deepagents | The task is long, multi-step and needs planning and context management out of the box |
| LangSmith | Hosted platform for tracing, evaluation, prompt work and deployment; free plan for solo users, self-hosting on the Enterprise plan | Platform | langsmith | You need to see what the agent did, test changes, or deploy and monitor it |
The relationships matter more than the names. LangChain's agents are built on top of LangGraph, so LangChain agents can use LangGraph's persistence and approval features, though you still supply a checkpointer and a database. LangGraph can run on its own. Deep Agents sits on top of both. LangSmith sits beside all of them as the place you observe and evaluate, and it is not limited to code written with LangChain products.
Treat the layer column as a guide, not a taxonomy. LangChain's own vocabulary has shifted: its earlier writing calls LangChain a framework and Deep Agents a harness, and its current overview describes create_agent itself as a minimal harness.
LangChain: the framework
LangChain's agent framework is now built around one function, create_agent. You give it a model, a list of tools (plain Python functions) and a system prompt, and it returns an agent that loops: the model decides whether to call a tool, the tool runs, the result goes back to the model, and so on until it has an answer. LangChain also gives you a standard interface across model providers, so switching providers is often a small change, although model features and settings still differ.
What version 1.0 changed
create_agentis the standard entry point. It replacescreate_react_agentfromlanggraph.prebuilt, which is deprecated. On the versions tested for this guide (LangGraph 1.2), pieces such asToolNodeandtools_conditionstill import fromlanggraph.prebuiltwithout a warning, so check the docs for your pinned version before assuming something has moved.- Middleware lets you hook into the agent loop to change behaviour without rewriting it: approvals, retries, limits, summarisation and redaction.
- Structured output now runs inside the main loop, which removes an extra model call.
- Standard content blocks: messages expose a
.content_blocksproperty so reasoning traces, citations and tool calls look the same across providers. - A smaller namespace: legacy chains, retrievers and similar pieces moved to
langchain-classic. Python 3.10 or newer was required at 1.0. - A stability promise: the team committed to no breaking changes before 2.0. Behaviour defaults have still moved between releases (the recursion limit below is an example), so pin your versions.
A first agent, with limits
This example was run on LangChain 1.4 with a stand-in model. Replace the model placeholder with your provider and model name, using the form your provider integration expects.
from langchain.agents import create_agent
from langchain.agents.middleware import ModelCallLimitMiddleware, ToolCallLimitMiddleware
def get_order_status(order_id: str) -> str:
"""Look up the status of an order."""
return "shipped" # call your order system here
agent = create_agent(
model="provider:model-name",
tools=[get_order_status],
system_prompt="You help support staff. Use tools for facts. Never guess.",
middleware=[
ModelCallLimitMiddleware(run_limit=8), # stop runaway loops
ToolCallLimitMiddleware(run_limit=5), # cap tool use per run
],
)
result = agent.invoke({"messages": [{"role": "user", "content": "Where is order 4172?"}]})
Built-in middleware worth knowing
- Human-in-the-loop: pause for a person to approve, edit or reject a tool call. It needs a checkpointer, which saves the run so it can resume.
- Model and tool call limits: cap calls per run or per conversation thread.
- Model retry, tool retry and model fallback: retry with backoff, or switch to another model when one fails.
- Summarization and context editing: keep a long conversation inside the context window.
- PII (Personally Identifiable Information) detection: redact or mask personal data before it travels further.
- Tool error handling: turn a tool exception into a message the model can react to, instead of crashing the run.
Best practices for LangChain
- Start with
create_agentand add middleware only as a problem appears. Resist building a custom loop first. - Write tools like an interface for a new colleague. A clear name, a one-line docstring that says when to use it, typed arguments, and a return value the model can read.
- Set limits from day one. A model-call limit and a tool-call limit cost two lines and reduce the chance of a runaway bill. Know the defaults: the model-call limit ends the run, while the tool-call limit blocks further calls but lets the run continue, so choose the exit behaviour you want.
- Pin your versions and read the docs for the version you installed. Older tutorials use imports that have moved.
- Keep the prompt visible. Whatever sits between you and the model, you should be able to read the exact prompt that was sent. A trace (see the LangSmith section) makes that easy.
- Do not import from
langchain-classicin new code. It exists so old code keeps working.
When LangChain is the wrong tool
If the job is one prompt in and one answer out, call the provider's API directly. A framework earns its place when you have tools, a loop, several providers or cross-cutting behaviour such as retries and approvals. Anthropic's December 2024 guidance on building agents makes the same point: start with plain API calls, and if you adopt a framework, make sure you understand what it does underneath, because extra layers can hide the prompts and responses you need to debug. Frameworks have costs of their own: more to learn, and an API that changed shape between the pre-1.0 releases and 1.0, which is exactly what the scene above dramatises.
LangGraph: the runtime
LangGraph describes your agent as a graph. That sounds abstract until you see how little there is to it: three ideas.
- State: a shared record of what is known so far, defined by a typed schema. Each field can have a reducer, a rule for merging an update into the existing value (replace it, or append to a list).
- Nodes: ordinary Python functions that read the state and return an update.
- Edges: the rules for which node runs next, either fixed or conditional.
You then compile() the graph, optionally with a checkpointer, and run it. The key design point is that deterministic steps (check a rule, call an API) and model-driven steps live in the same graph, so you decide exactly where the model is allowed to decide.
Why teams reach for it: persistence and human approval
Give the compiled graph a checkpointer and every step's state is saved under a thread (identified by a thread_id you choose). That one feature enables four things: conversation continuity, pausing for a human, recovery after a failure, and "time travel" back to an earlier step. Three checkpointers matter: an in-memory one (state is lost when the process restarts, so use it for tests), a SQLite one for local development, and a PostgreSQL one that the docs recommend for production (you call its setup step once to create its tables).
Human approval uses the interrupt() function. A node calls it, the run pauses and the state is saved, and the run continues when you call the graph again with the same thread_id and a Command(resume=...). The resume value becomes the return value of interrupt().
A worked example: the refund graph
This runs as written on LangGraph 1.2. Refunds above 2,000 pause for a human. Smaller ones go straight through. The step that issues the refund is its own node after the interrupt, for a reason explained below.
from typing import TypedDict
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import END, START, StateGraph
from langgraph.types import Command, interrupt
class RefundState(TypedDict):
order_id: str
amount: int
decision: str
def check_policy(state: RefundState) -> dict:
# Deterministic step: plain code, no model involved
return {"decision": "needs_approval" if state["amount"] > 2000 else "auto_approved"}
def after_policy(state: RefundState) -> str:
return "ask_human" if state["decision"] == "needs_approval" else "issue_refund"
def ask_human(state: RefundState) -> dict:
answer = interrupt(
{"question": "Approve this refund?", "order": state["order_id"], "amount": state["amount"]}
)
return {"decision": "approved" if answer == "yes" else "rejected"}
def after_human(state: RefundState) -> str:
return "issue_refund" if state["decision"] == "approved" else "stop"
def issue_refund(state: RefundState) -> dict:
# The side effect lives in its own node, AFTER the interrupt.
# In real code, send an idempotency key (for example the order id) to the payment
# provider so a repeated call cannot pay twice.
print(f"refund issued for order {state['order_id']}")
return {}
builder = StateGraph(RefundState)
builder.add_node("check_policy", check_policy)
builder.add_node("ask_human", ask_human)
builder.add_node("issue_refund", issue_refund)
builder.add_edge(START, "check_policy")
builder.add_conditional_edges(
"check_policy", after_policy, {"ask_human": "ask_human", "issue_refund": "issue_refund"}
)
builder.add_conditional_edges("ask_human", after_human, {"issue_refund": "issue_refund", "stop": END})
builder.add_edge("issue_refund", END)
graph = builder.compile(checkpointer=InMemorySaver()) # use a PostgreSQL checkpointer in production
config = {"configurable": {"thread_id": "refund-4172"}}
paused = graph.invoke({"order_id": "4172", "amount": 4500, "decision": ""}, config)
print(paused["__interrupt__"]) # the question waiting for a person
done = graph.invoke(Command(resume="yes"), config) # same thread_id resumes the run
print(done["decision"]) # approved
Run with a human answering "yes", the graph prints the refund and ends as approved. With "no" it ends as rejected and the refund node never runs. With an amount of 500 it never pauses at all.
The rules the docs warn about (and the example obeys)
- The node restarts from the top when it resumes. Any code before the
interrupt()call runs again, so a side effect placed before it can happen twice. Put side effects after the interrupt or in a separate node, and make them safe to repeat. - Do not wrap
interrupt()in a bare try/except. The pause works by raising an exception. A broad handler swallows it, the run carries on as if nobody had been asked, and a handler that defaults to "yes" approves the refund automatically. - Keep interrupts in a stable order within a node, because resume values are matched to interrupts by position.
- Pass plain, serialisable values to
interrupt(), not functions or objects.
Other LangGraph features to know
- Conditional edges and parallel branches: several outgoing edges run their targets in parallel in the next step.
Senddispatches work to a node with its own state, which suits "do this for each item" patterns where the number of items is not known in advance.Commandlets a node update state and choose the next node in one return value.- Recursion limit: a cap on the number of steps in one run. The default has changed between releases (the docs give about ten thousand for current ones, and older pins may differ), so set it explicitly to a number that suits your task, as a top-level key in the config, and expect a
GraphRecursionErrorwhen it is reached. - Streaming and memory: stream progress to a user while the run goes on, and use a store for long-term memory that spans threads.
Best practices for LangGraph
- Make the deterministic parts plain nodes. Policy checks, validation and API calls do not need a model. A node that is a plain function can be tested like any other function.
- Keep the state small and typed. Store identifiers and decisions, not whole documents. Use a reducer where updates should accumulate.
- Use a durable checkpointer outside tests. The in-memory one forgets everything on a restart, which defeats the point.
- Choose thread ids on purpose. One thread per conversation, per case or per refund request, so a resume finds the right run.
- Put side effects after approvals and make them idempotent (safe to run twice).
- Set a recursion limit and call limits for any graph that contains a loop, and set a budget alert with your model provider.
- Draw the graph before you code it. If you cannot sketch the nodes and edges on paper, the control flow is not decided yet.
When LangGraph is the wrong tool
If a standard tool-using agent does the job, create_agent already gives you the LangGraph runtime without writing the graph. For approvals, if you gate by tool name (every call to issue_refund needs a yes), LangChain's human-in-the-loop middleware with a checkpointer may be all you need. Reach for a graph when approval depends on deterministic policy such as the amount, or sits inside a larger flow, and remember that an agent made with create_agent can itself be used as a node inside a LangGraph workflow. Also note that the library is not a hosted server: running it in production means providing your own hosting and a database for checkpoints, or using LangSmith Deployment. If you only need a straight line of three model calls, a few lines of ordinary code are clearer than a graph. LangGraph pays off when the control flow itself is a product requirement: approvals, branches, retries, parallel work, or runs that outlive a single request.
LangSmith: the platform
LangSmith answers the question the Hyderabad team could not: what did the agent see, and what did it do? It has three jobs that build on each other.
1. Observability: see every run
Tracing records each model call, tool call and decision of a run as a tree you can open. For an app built with LangChain or LangGraph you turn it on with environment variables and no code changes:
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=YOUR_API_KEY
The exact variables depend on your workspace. The current Cloud quickstart also uses an agent ID and environment, project-based and self-hosted workspaces use LANGSMITH_PROJECT instead, and accounts outside the US need LANGSMITH_ENDPOINT. Follow the quickstart for your workspace.
For your own functions, wrap them with the traceable decorator from the langsmith package, and LangChain calls inside them appear as child steps. In Python, traces are sent from a background thread so they do not block your app. In serverless environments, flush them before the function exits, or traces can go missing. Beyond individual traces, LangSmith offers threads (whole conversations), dashboards, alerts, and ways to collect user feedback and have reviewers annotate outputs.
Keep customer data out of traces. LangSmith provides LANGSMITH_HIDE_INPUTS and LANGSMITH_HIDE_OUTPUTS, per-client hide_inputs and hide_outputs functions, and an anonymizer (create_anonymizer, in langsmith.anonymizer) that masks patterns such as phone numbers. The docs say this masking happens in your application, before data reaches LangSmith. If traces will hold customer data, decide what may enter them (see the India notes below).
2. Evaluation: know whether a change helped
LangSmith's evaluation model has a small vocabulary:
- Dataset: a collection of test cases. Example: one input, with an optional reference output that only the evaluators see.
- Experiment: the results of running one version of your app on a dataset, so you can compare versions.
- Evaluators come in several kinds, including human review, code (deterministic checks), LLM (Large Language Model) as judge, where a model scores the output against criteria, and pairwise, which of two outputs is better.
| Offline evaluation | Online evaluation | |
|---|---|---|
| Runs on | A dataset of examples | Real production traces |
| Reference answers | Available | Not available |
| Used for | Pre-release benchmarking, regression tests, CI (Continuous Integration) checks | Monitoring, spotting anomalies, collecting feedback |
The practical loop is: online monitoring surfaces a failure, you add it to the dataset as a test case, offline evaluation checks your fix, and online evaluation confirms it helped in production. LangSmith's guidance for a first dataset is modest: start with 10 to 20 well-chosen examples and grow it from real failures. Two cautions from the same docs: scores from a model acting as judge need careful human review, and in CI you should pin a dataset version so that edits to the dataset do not silently change your pipeline. A fuller guide to writing evaluations is coming in this series.
3. Deployment and prompt work
LangSmith also covers prompt engineering and deployment, with a tool for inspecting and debugging agents called LangSmith Studio and a managed way to deploy agents called LangSmith Deployment, which the pricing page lists from the Plus plan upward and not on the free plan. You do not have to use them: LangGraph is an open-source library, so you can host it yourself, with your own database for checkpoints. The platform also keeps adding features (for example, an engine that detects recurring issues in traces), so check the current docs.
Not tied to LangChain, and not free of cost
- Framework-neutral: LangSmith documents integrations with OpenAI, Anthropic, CrewAI, the Vercel AI SDK (Software Development Kit) and Pydantic AI, among others, and has its own SDK for code of your own.
- Plans: as of November 2026 the pricing page lists a free Developer plan for solo users, a per-seat Plus plan for teams, and an Enterprise plan with self-hosted and hybrid options. Billing combines per-seat pricing with metered usage such as traces, so check the current pricing page before you plan a budget.
- Retention: base traces are kept for 14 days and extended traces for 180 days, at an extra fee. A dispute that arrives after three weeks needs extended retention or an export you keep yourself.
- Alternatives exist: tracing and evaluation can also be done with other tools, including open-source ones such as Langfuse and Arize Phoenix. The
langsmithSDK is MIT licensed, while the hosted platform is a commercial product.
Best practices for LangSmith
- Turn tracing on in development on day one. It is a low-effort way to see what your agent is doing, and setup is a few environment variables.
- Name projects and tag runs by environment and version, so you can compare a release with the one before it.
- Build the first dataset by hand from real cases, then add production failures. A person should write the reference answers, and real cases should be anonymised before they enter a dataset, because datasets and experiments are hosted data too.
- Match the evaluator to the question. Use code checks where a rule can decide, a model judge for fuzzy qualities, and humans to calibrate the judge.
- Use reference-free evaluators online (they need no right answer) and reference-based ones offline.
- Run evaluations in CI against a pinned dataset version, and fail the build when a metric drops below the baseline.
- Decide what is allowed into a trace. Prompts and tool results can contain personal data. Mask it before it leaves your application with the hide-inputs, hide-outputs or anonymizer options, or choose a hosting option that fits your data rules.
The fourth name: Deep Agents
You will also meet Deep Agents. It is an opinionated harness (a ready-made working environment) built on LangChain and LangGraph, with a virtual filesystem for managing context, subagents for isolated subtasks, optional task planning (opt in, since version 0.7) and persistent memory in AGENTS.md files. It needs Python 3.11 or newer. LangChain's docs suggest it for complex, multi-step work that needs planning, and suggest create_agent or a custom LangGraph workflow when you do not need those built-in capabilities. The docs also mention a hosted option, Managed Deep Agents, which raises the same hosted-data questions as any hosted service. If the word harness is new, our guide to loop engineering covers the loops that these harnesses run.
How they fit together, and which you need
| Your situation | Use | Why |
|---|---|---|
| One prompt in, one answer out | Direct provider API call | A framework adds nothing you need |
| A standard agent with a few tools | LangChain create_agent | A quick route, and it runs on LangGraph already |
| Runs must pause for a person, survive restarts or follow strict branches | LangGraph | Saved state, interrupts and explicit control flow |
| Approval gated by tool name (every call to one tool needs a yes) | LangChain human-in-the-loop middleware, with a checkpointer | No custom graph needed |
| A long, multi-step job needing planning, files and subagents | Deep Agents | The harness is already built |
| You need to see what happened, or prove a change helped | LangSmith, with any of the above | Traces and evaluations |
| An agent built on another framework | LangSmith tracing only | It works with many frameworks |
| Question | LangChain | LangGraph | LangSmith |
|---|---|---|---|
| Main job | Build an agent quickly | Control and run it reliably | Observe, test and deploy it |
| You work with | Models, tools, middleware | State, nodes, edges | Traces, datasets, experiments |
| Pause for human approval | Human-in-the-loop middleware | interrupt() and Command(resume=...) | Not applicable: annotation queues review runs after the fact and do not pause an agent |
| Saved state | Through LangGraph (create_agent accepts a checkpointer) | Checkpointers and threads | Not applicable to tracing and evaluation |
| Needs the others? | Runs on LangGraph underneath | No, it works without the langchain package (it still installs the small langchain-core base) | No, works with many frameworks |
| Open source? | Yes, MIT licence | Yes, MIT licence | Hosted product with a free plan; the SDK is MIT licensed; self-hosting on Enterprise |
What else exists, and when to skip all of this
These three products are one set of choices among several, and a fair guide should say so. The examples below come from LangChain's own writing on the topic and from general knowledge. This is not a ranking, and none of these tools was benchmarked for this guide.
| Category | Examples | Worth knowing |
|---|---|---|
| Agent frameworks | The Vercel AI SDK (Software Development Kit), CrewAI, the OpenAI Agents SDK, Google's Agent Development Kit, LlamaIndex | Same job as LangChain: abstractions for models, tools and agent loops |
| Durable execution engines | Temporal, Inngest | Play a role similar to LangGraph's runtime: runs that survive failures and wait for events |
| Harnesses | Deep Agents, the Claude Agent SDK | Batteries-included working environments for long-running agents |
| Tracing and evaluation | Langfuse and Arize Phoenix (open source), plus the observability tools of your cloud or model provider | An alternative or a complement to LangSmith |
| No framework | Direct calls to a model provider's API | Often enough for a single call or a short, fixed sequence |
How to choose without picking by popularity: start from your team's language and stack, list the capabilities you actually need (pause and resume, tracing, evaluation), and favour the option whose underlying code you can read and debug.
Libraries and packages
| Need | Install | Notes |
|---|---|---|
| The framework | pip install -U langchain | Add a provider with an extra such as langchain[openai] |
| The runtime | pip install -U langgraph | uv add langgraph works too |
| A production checkpointer | pip install langgraph-checkpoint-postgres | Provides the PostgreSQL saver; call its setup step once. The in-memory saver is for tests; a SQLite saver (langgraph-checkpoint-sqlite) is for local work |
| Tracing and evaluation SDK | pip install langsmith | Provides traceable; also reads the LANGSMITH_* environment variables |
| The harness | deepagents | Built on LangChain and LangGraph; needs Python 3.11 or newer |
| Old code only | langchain-classic | Legacy chains and retrievers; not for new code |
The examples in this guide are Python. LangChain, LangGraph and LangSmith also have JavaScript and TypeScript versions.
Old pattern, current pattern
| If a tutorial or a coding agent produces this | Use this instead |
|---|---|
create_react_agent from langgraph.prebuilt | create_agent from langchain.agents |
ToolNode, tools_condition and other pieces of langgraph.prebuilt | Still importable from langgraph.prebuilt on the versions tested here; check the docs for your pinned version |
Legacy chain and retriever classes from the main langchain package | Rebuild with create_agent or LangGraph where an agent is what you need, or install langchain-classic to keep old code running. A simple prompt, model and parser pipeline does not need create_agent. |
A worked use case: the refund assistant, layer by layer
| Step | Layer | How |
|---|---|---|
| Read the request and look up the order | LangChain | A create_agent with an order-lookup tool, plus call limits |
| Check the refund against policy | LangGraph | A plain code node, so a rule decides and not a model |
| Ask a manager above a threshold | LangGraph | interrupt(), with a durable checkpointer and one thread per refund |
| Issue the refund | LangGraph | A separate node after the approval, safe to repeat |
| Show what happened to a disputing customer | LangSmith | Tracing on, with one project per environment |
| Know a prompt change did not break approvals | LangSmith | A dataset of real refund cases, evaluated in CI |
Brief your coding agent properly
Coding agents often write an older LangChain than the one you have installed, so the brief has a job beyond describing the product: it must steer the agent to the current APIs and make "done" checkable. Standing rules belong in the project's instruction file (see our guide to Claude Code markdown files), and the task can look like this:
Build a refund-approval assistant for our support team.
Libraries: LangChain 1.x, LangGraph 1.x, LangSmith. Python 3.12.
Before writing code, inspect the installed packages (signatures and
docstrings) and the documentation for the versions pinned in
pyproject.toml. Do not copy pre-1.0 examples. Do not use create_react_agent
and do not import from langchain-classic.
Design:
- A create_agent with an order-lookup tool, a model-call limit and a
tool-call limit.
- A LangGraph graph around it: policy check as a plain code node; refunds
over the threshold in config/policy.yaml pause with interrupt() for a
manager; the refund is issued in a separate node AFTER the approval.
- The call to the payment provider must be idempotent: send an idempotency
key derived from the order id, and add a test that a repeated call cannot
pay twice.
- Checkpointer: in-memory for tests; the PostgreSQL checkpointer otherwise
(call its setup once). One thread_id per refund request.
- Never wrap interrupt() in try/except.
- Set the recursion limit explicitly (25 is plenty for this graph).
- LangSmith tracing on. Mask customer names, phone numbers and card details
before they leave the application, using LangSmith's hide-inputs,
hide-outputs or anonymizer options. Read every key from an environment
variable and never commit one.
- Send data only to the model and tracing services named in README.md.
Evaluation first:
1. A person supplies evals/cases.jsonl (about 20 refund requests,
anonymised before they reach any hosted service, each with the expected
decision and whether a human approval was required) and
evals/holdout.jsonl, which you never see. Never edit either file. If
cases.jsonl does not exist, stop and ask for it. Do not invent cases.
2. Build `make eval`: runs the cases, uploads results as a LangSmith
experiment, and reports decision accuracy and the share of runs that
paused when they should have.
Done means: `make eval` meets the thresholds in evals/thresholds.json (set
by a person, never lowered by you), tests pass, a test proves a rejected
refund never reaches the refund node, and every run has a trace.
Three lines in that brief earn their place. "Inspect the installed packages and read the documentation for the pinned versions" stops the agent writing code against the library it remembers. "Send data only to the services named" keeps customer information out of places you did not choose. And a person supplies the evaluation cases, because an agent left to invent its own cases tends to write easy ones and then mark its own homework. We cover the same trap in the RAG (Retrieval-Augmented Generation) architectures guide.
What not to do
- Do not start with a framework when a direct API call will do. Add LangChain when you have tools and a loop.
- Do not build a LangGraph graph for a straight line. A graph is for branches, pauses and retries.
- Do not ship with the in-memory checkpointer. A restart erases every paused run.
- Do not put a side effect before an interrupt. It will run again on resume.
- Do not catch the interrupt. A broad try/except swallows the pause, and a handler that defaults to yes approves automatically.
- Do not copy code from a pre-1.0 tutorial without checking it against the current docs.
- Do not skip tracing. Without it, "why did the agent do that?" has no answer.
- Do not trust a model judge you have never checked. Compare its scores with human labels first.
- Do not send personal data to a hosted service by default. Decide what may leave your systems.
When something is wrong: symptom, cause, fix
| Symptom | Likely cause | First fix to try |
|---|---|---|
| Imports fail in a tutorial's code | The tutorial predates 1.0; pieces moved to langchain-classic | Port to create_agent, or install langchain-classic for old code only |
| A refund was issued twice after a resume | A side effect sits before the interrupt() in the same node | Move it to a node after the approval and make it idempotent |
| Paused runs vanish after a deploy | In-memory checkpointer | Use the PostgreSQL checkpointer |
| Approval prompts never appear | A try/except around interrupt() swallowed the pause, so the run carried on without a human | Remove the broad handler |
| A run loops and the bill climbs | No limits on calls or steps | Add call-limit middleware and a recursion limit |
| "Why did it do that?" cannot be answered | No tracing | Set LANGSMITH_TRACING and LANGSMITH_API_KEY |
| A dispute arrives after three weeks and the trace is gone | Base trace retention is 14 days | Use extended retention for runs you may need, or export what you must keep |
| Traces missing from a serverless function | The background sender had not finished when the function exited | Flush before exit, as the docs describe |
| Offline scores are good but users complain | The dataset does not reflect production | Turn on online evaluation and add real failures to the dataset |
If you are building in India: what changes in your design
| Situation | Why it matters | What to do |
|---|---|---|
| Traces contain customer data | The DPDP (Digital Personal Data Protection) Act, 2023 is being phased in, and it and your sector regulator affect what you may send to a hosted service and where it is processed. Check the current status. | Mask personal data before it leaves your application (the hide-inputs, hide-outputs and anonymizer options), decide what is allowed into a trace, and confirm the specifics with your legal team. The docs mention region-specific endpoints and self-hosted or hybrid options on the Enterprise plan, so ask about data location. |
| A small team owns everything | There may be no platform team to add observability later | Switch tracing on first. It takes minutes and every later decision can use it. |
| Approvals follow Indian business hours and cross time zones | A manager may answer hours or days later | Use LangGraph's pause and resume with a durable checkpointer, instead of holding a request open. |
Where to go next
This guide is the map of the three products. If you are new to agents themselves, start with What Are AI Agents?. If your agent retrieves documents, read the RAG architectures guide. Upcoming posts in this series go deeper on building with LangGraph, on writing evaluations, and on the libraries to brief a coding agent with.
Your next step: switch on tracing for the agent closest to launch and read its last ten runs. Whatever surprises you tells you which layer to add next.
One question to take back to your team this week: if a customer disputed what your agent did yesterday, could you pull up the recorded trace and show them why? 👇
Frequently asked questions
What is the difference between LangChain and LangGraph?
LangChain is the framework for building an agent quickly from a model, tools and a prompt. LangGraph is the lower-level runtime underneath it, which models the agent as a graph and adds saved state, pauses for human approval and recovery from failures. LangChain's agents are built on LangGraph, so you can start with LangChain and drop down to LangGraph when you need more control.
Is LangGraph part of LangChain?
They are separate libraries from the same company. LangChain's agents run on LangGraph, but LangGraph can be used on its own without the langchain package, although it still installs the small langchain-core base.
What is LangSmith used for?
LangSmith is a platform for tracing what an agent did, evaluating changes against datasets, working on prompts and deploying agents. It records each model call and tool call, supports several kinds of evaluator, including human, code, model-judge and pairwise, and runs both offline on datasets and online on production traces.
Do I need LangChain to use LangSmith?
No. LangSmith documents integrations with several other frameworks and providers, including OpenAI, Anthropic, CrewAI, the Vercel AI SDK and Pydantic AI, and it has an SDK for tracing your own code.
Is LangChain still worth learning after version 1.0?
Version 1.0 narrowed LangChain to a focused agent framework built around create_agent and middleware, moved legacy code to langchain-classic, and promised no breaking changes before 2.0. It suits agents with tools and a loop. For a single model call, using the provider's API directly is simpler.
How do I add human approval to an agent?
In LangGraph, call interrupt() inside a node, compile the graph with a checkpointer, and resume later with Command(resume=...) on the same thread id. In LangChain, human-in-the-loop middleware pauses for a person to approve, edit or reject a tool call, and it also needs a checkpointer. Keep side effects after the pause and make them safe to repeat.
What is Deep Agents?
Deep Agents is an agent harness from LangChain, built on LangChain and LangGraph, with planning, a virtual filesystem for context, subagents and persistent memory. It is aimed at long, multi-step tasks.
Is LangSmith free?
As of November 2026 the pricing page lists a free Developer plan for solo users. Teams use the per-seat Plus plan, and Enterprise adds custom terms with self-hosted and hybrid options. Base traces are kept for 14 days unless you pay for extended retention, and managed deployment starts at the Plus plan. Check the current pricing page, because usage is metered.
Which libraries should I tell my coding agent to use?
Name the versions, tell the agent to inspect the installed packages and read the documentation for those versions, and tell it to use create_agent from langchain.agents and LangGraph's current API, not create_react_agent or langchain-classic in new code. Add the PostgreSQL checkpointer package and the LangSmith SDK to the list.
How do I test an agent built with these tools?
Write plain tests for deterministic nodes and tools, then build a dataset of real cases in LangSmith and run it as an experiment in your CI pipeline against a pinned dataset version. Add online evaluators on production traces, and calibrate any model judge against human labels.
What are the alternatives to LangChain?
Other agent frameworks include the Vercel AI SDK, CrewAI, the OpenAI Agents SDK, Google's Agent Development Kit and LlamaIndex. Durable execution engines such as Temporal and Inngest play a role similar to LangGraph's runtime, and open-source tools such as Langfuse and Arize Phoenix offer tracing and evaluation. Calling a model provider's API directly is also a valid choice for simple jobs.
Learn to build this with us
To follow this series as each post publishes, join the Garage Labs community. If you want to build these systems with live guidance, RAG, agent frameworks, harnesses, loops and evaluations are core topics in the Applied AI Practitioner Program, taught through live sessions and build labs. See the programme page for the schedule and details.
Sources and further reading
- LangChain, LangChain overview and LangGraph overview (documentation)
- LangChain, LangChain and LangGraph agent frameworks reach v1.0 (22 October 2025)
- LangChain, Agent frameworks, runtimes and harnesses, oh my
- LangChain, LangSmith evaluation concepts and LangGraph interrupts (documentation)
- Anthropic, Building effective agents (19 December 2024)