Skip to main content
← Back to Blog
2026-02-22 · 9 min readAI AgentsPythonUpdated Oct 03, 2026

What Is LangChain? When to Use It and When to Write Your Own Code

A practical guide to LangChain as it stands in late 2026: what the framework does, what moved to langchain-classic in 1.0, how create_agent and checkpointers work, and how to decide between LangChain, LangGraph and a small amount of your own code.

Avnish Yadav
Avnish Yadav
Developer & Automation Builder
18 views
What Is LangChain? When to Use It and When to Write Your Own Code

LangChain is an open-source framework for building applications on top of large language models. In its current form (the 1.x line) it is mostly two things: a standard interface for talking to models from different providers, and a small, configurable agent harness called create_agent that runs a model in a loop with your tools. Underneath, that agent runs on LangGraph, which gives it persistence, streaming and human-in-the-loop support.

The question most developers actually have is not "what is it" but "should I use it, or should I write the twenty lines myself?" This guide answers both. Nothing here is a benchmark or a story about a project; it is what the official documentation says today (checked on October 3, 2026) and the rules of thumb I would apply when choosing.

What LangChain is today

The LangChain overview page sums the design up as "Agent = Model + Harness". The model is whichever chat model you pick. The harness is create_agent: it sends the conversation to the model, runs any tool the model asks for, feeds the result back, and stops when the model gives a final answer.

Around that core you get:

  • A standard model interface. init_chat_model takes a model name, or a "provider:model" string such as "openai:o1", and returns a chat model with the same invoke, stream and batch methods whatever the provider. Timeouts, retries (max_retries, default 6), temperature and max_tokens are ordinary parameters.
  • Tools. Plain Python functions with a docstring and type hints can be passed straight to create_agent.
  • Middleware. Hooks such as before_model, after_model, wrap_model_call and wrap_tool_call let you change what happens around each model or tool call. Built-in middleware covers jobs like summarising long conversations.
  • Integrations. Provider packages (langchain-openai, langchain-anthropic and many more) for models, embeddings, vector stores and caches.

LangGraph sits one level lower. If you need an explicit graph of steps, branches and loops, you write it in LangGraph directly. If a model-plus-tools loop is enough, create_agent builds that graph for you.

What changed in LangChain 1.0

If you learned LangChain from older tutorials, a lot of what you saw has moved. According to the v1 migration guide:

  • Legacy chains (LLMChain, ConversationChain and friends), the old retrievers, the indexing API, the hub module and the langchain-community re-exports now live in a separate package, langchain-classic.
  • The legacy memory classes went with them. Short-term memory is now LangGraph state saved by a checkpointer and keyed by a thread_id.
  • create_react_agent from langgraph.prebuilt is deprecated in favour of from langchain.agents import create_agent, and its prompt= argument is now system_prompt=.
  • pre_model_hook, post_model_hook and state_modifier are replaced by middleware.
  • Every LangChain package now needs Python 3.10 or newer.

So code that imports ConversationTokenBufferMemory, ConversationChain or AgentExecutor from langchain is old code. It can keep running on langchain-classic, but I would not start anything new on it.

A minimal LangChain agent with memory

Here is the shape of a current agent, close to the examples in the docs. Install the package with the provider extra you need (for example pip install -U langchain "langchain[openai]"), then:

from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver

def get_order_status(order_id: str) -> str:
    """Look up the shipping status of one order by its ID."""
    # Replace with a real lookup (database, ERP, Salesforce).
    return f"Order {order_id} has shipped."

agent = create_agent(
    model="openai:gpt-5.5",
    tools=[get_order_status],
    system_prompt="You are a support assistant. Use tools for order data; never guess.",
    checkpointer=InMemorySaver(),
)

config = {"configurable": {"thread_id": "customer-42"}}
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Where is order A-1001?"}]},
    config,
)
print(result["messages"][-1].content)

Three things to notice. The tool is a normal function; its docstring becomes the description the model sees. The checkpointer stores the conversation, and the thread_id decides which conversation you are continuing, so a second invoke with the same thread_id remembers the first. And InMemorySaver is for development only: the memory guide switches to PostgresSaver from langgraph-checkpoint-postgres for production. I cover that and the other production concerns in Best practices for deploying LangChain apps to production.

If you want to see what is happening inside, set LANGSMITH_TRACING=true and LANGSMITH_API_KEY in the environment and every model call, tool call and its inputs and outputs show up as a trace in LangSmith.

What you would have to write yourself

The honest comparison is not "LangChain versus one API call". One API call is always simpler without a framework. The comparison is LangChain versus everything an agent needs once it leaves a notebook:

  • The tool loop. Parse the model's tool calls, run the functions, send results back with the right message types, stop after a step limit.
  • Conversation state. Store messages per user or session, load them on the next request, trim or summarise them before they outgrow the context window.
  • Streaming. Send tokens and tool progress to the client as they arrive instead of after the whole run.
  • Provider differences. Each SDK has its own message format, tool-call format and error types.
  • Tracing. Some way to see the exact prompt, tool arguments and output of a failing run.

None of these is hard on its own. Writing them all, testing them and keeping them current as providers change their APIs is where the time goes. That is the work LangChain and LangGraph take off your plate. If you want to see what the loop looks like without a framework, Building AI agents from scratch walks through it in plain Python.

When I would use LangChain

My rule of thumb: reach for LangChain when two or more of these are true.

  • The model needs to call tools and decide what to do next, not just answer once.
  • Conversations span several turns and have to survive restarts or run on more than one server.
  • You want to try more than one model provider, or keep the option to switch.
  • You need streaming, human approval steps, or long-running work that can resume.
  • You want tracing and evaluation from day one without wiring them yourself.

In those cases the framework replaces code you would otherwise write and maintain, and create_agent is a small enough surface that you can still read what it does.

When I would write my own code

Skip the framework when the job is narrow:

  • One call, one answer. Classify an email, summarise a document, extract fields into JSON. The provider's SDK and a schema for structured output are enough.
  • A fixed pipeline. If the steps never change (fetch, prompt, validate, save), a few functions are clearer than any abstraction.
  • An existing codebase with strong conventions. If you already have your own retry, logging and state handling, adding a second set can make things harder to follow.
  • A team that will not learn the framework. A dependency nobody understands is a liability when it breaks.

There is also a middle path, and it is where I end up most often: use init_chat_model and LangSmith tracing even in a hand-written pipeline, and only adopt create_agent or LangGraph when the logic genuinely becomes an agent. You can also expose existing functions as tools without restructuring them. Extending LangChain with custom tools covers that pattern.

LangChain, LangGraph or neither

A short decision guide:

  1. Single model call or fixed pipeline: provider SDK, or init_chat_model if you want provider portability.
  2. Model plus tools in a loop: LangChain create_agent, with middleware for anything you need to change around model or tool calls.
  3. Explicit multi-step workflow with branches, parallel steps, or several agents: LangGraph directly.
  4. Retrieval-heavy document search as the main job: compare LangChain with a retrieval-focused library first; LangChain vs LlamaIndex vs a vanilla stack goes through that choice.

Whatever you pick, pin your package versions and read the release notes before upgrading. The 1.0 move to langchain-classic is a good example of why: tutorials from a year ago no longer match the current imports.

Common mistakes to avoid

  • Copying pre-1.0 tutorials. If a snippet imports LLMChain, ConversationChain, AgentExecutor or a memory class from langchain, look for the current equivalent in the docs before using it.
  • Keeping memory in a global variable. In a web server that can leak one user's conversation into another's. Use a checkpointer and a per-user thread_id.
  • Skipping timeouts. Set timeout and max_retries on the model so a slow provider does not hang a request forever.
  • Debugging without traces. Turn on tracing before the first bug, not after. Debugging LangChain with callbacks shows what you can see at each step.
  • Treating the framework as the product. The value is in your tools, prompts and data. Keep those in plain, testable functions so you could move them if you ever had to.

Frequently asked questions

What is LangChain used for?

Building applications on top of language models: agents that call tools, chat assistants with memory, retrieval over your documents, and pipelines that need to work with more than one model provider. The core pieces are a standard model interface and the create_agent harness, which runs on LangGraph.

Is LangChain still relevant in 2026?

Yes, but it looks different from older tutorials. LangChain 1.x is a smaller library centred on create_agent, middleware and the standard model interface, with legacy chains and memory moved to langchain-classic. Check the version a tutorial was written for before copying it.

What is the difference between LangChain and LangGraph?

LangGraph is the lower-level runtime for stateful, multi-step workflows: graphs, persistence, streaming and human-in-the-loop. LangChain's agents are built on top of it. Use create_agent when a model-plus-tools loop is enough, and LangGraph directly when you need to control every step.

Where did ConversationChain and AgentExecutor go?

They moved to the langchain-classic package in LangChain 1.0. The replacement for agents is create_agent from langchain.agents, and the replacement for memory classes is a LangGraph checkpointer with a thread_id.

Should I use LangChain for a simple chatbot?

If it only answers questions in a single call with no tools and no stored history, the provider SDK is simpler. Once you need tools, per-user history that survives restarts, or streaming of tool progress, LangChain starts to save you real work.

Does LangChain add latency?

Any layer adds some overhead, but the model call usually dominates the time of a request. Do not trust anyone's general number, including mine; trace your own requests in LangSmith or your logging and look at where the time actually goes.

Sources

Verified against the sources below on October 3, 2026. Products and docs change often: check the linked sources if something looks different.

  1. LangChain overview
  2. LangChain v1 migration guide
  3. LangChain: Models (init_chat_model)
  4. LangChain: Short-term memory
  5. LangChain: Streaming
  6. LangGraph: Persistence
  7. LangSmith: Trace with LangChain
Share
Discussion

Comments

Loading comments...

Add a comment

Comments are reviewed before they appear.