All articles
October 19, 2025 7 min read

The LangChain ecosystem in four layers: core, langgraph, create_agent, deepagents

LangChain confuses people because it isn't one library — it's a stack of abstraction layers, from raw building blocks you control completely up to a harness you just point at a goal. Here's the map.

Written forEngineering
LangChainFrameworksArchitecture

Most confusion about LangChain comes from treating it as one thing. It isn't — it's a family of packages stacked by abstraction, and each layer trades control for convenience. Once you see it as layers (the overview post on LangChain gives the wider context), the question stops being 'should I use LangChain?' and becomes the more useful 'which layer should I work at?'.

▲ more convenience, less codedeepagents · harnesscreate_agent · agentlanggraph · orchestrationlangchain-core · building blocks▼ more control, closer to the metal
Control at the bottom, convenience at the top: langchain-core building blocks, langgraph orchestration, create_agent for a prebuilt loop, and deepagents as a full harness.

Layer 1 — langchain-core: the building blocks

At the bottom you control everything. langchain-core gives you the primitives and you write the loop by hand: a chat model as one interface to every provider (invoke and stream), typed message objects instead of raw role dicts, the @tool decorator that turns a function's docstring and type hints into a schema, and structured output as Pydantic models via with_structured_output. The agent loop, if you want one, is yours to write — bind the tools, read the tool calls off the response, run them, and append a ToolMessage.

langchain-core: you own the loop
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI

@tool
def get_weather(city: str) -> str:
    """Return the weather for a city."""
    return lookup(city)

model = ChatOpenAI(model='gpt-4o').bind_tools([get_weather])
ai = model.invoke(messages)      # ai.tool_calls holds any requested calls
# you execute each call and append a ToolMessage by hand, then loop

Layer 2 — langgraph: orchestration

One layer up, you control the flow but not the primitives. langgraph models the app as a StateGraph — nodes, edges, and checkpoints — so you get explicit, durable, stateful control over how the steps run (the LangGraph posts, including the internals deep-dive, cover this properly). You reach for it when a straight loop isn't enough: branching, cycles, parallelism, and resumable runs.

Layer 3 — create_agent: the agent loop, prebuilt

Higher still, you supply a model, tools, and a system prompt, and the agent loop arrives prebuilt in one function call — much like the OpenAI Agents SDK. Notably, create_agent returns the same compiled langgraph graph you would have wired by hand a layer down, so you haven't left the ecosystem, you've just stopped writing the plumbing. It comes batteries-included: memory (a checkpointer and thread_id), structured output (response_format returns your Pydantic object), middleware (your hooks inside the loop), and MCP for tools.

create_agent: the loop in one call
from langchain.agents import create_agent

agent = create_agent(
    model='openai:gpt-4o',
    tools=[get_weather],
    system_prompt='You are a concise, helpful assistant.',
)
agent.invoke({'messages': [{'role': 'user', 'content': 'weather in Paris?'}]})
# under the hood this is a compiled LangGraph graph

Layer 4 — deepagents: the harness

At the top you supply intent and little else. deepagents adds a harness for harder, longer tasks — planning, sub-agents, and a virtual filesystem — on top of the agent loop. It's the most convenience and the least control: you describe the goal and let the framework decide how to decompose and pursue it.

Which layer should you work at?

  • langchain-core — for full control, learning how the loop really works, or a bespoke agent you want to see every part of.
  • langgraph — when you need explicit, stateful, resumable control over a non-trivial flow.
  • create_agent — when you want a standard, production-ready agent fast, without wiring the loop yourself.
  • deepagents — for complex, open-ended tasks where planning and sub-agents earn their keep.

The discipline is the same least-agency principle from elsewhere on this blog: climb only as high as the task forces you to. Every layer up is less code and less control — a trade to make on purpose, not by default.

LangChain isn't a library you adopt — it's a ladder you climb. The skill is stopping at the rung where the plumbing it saves you is worth the control you hand over.
Building something with LLMs?
I help teams ship GenAI that’s reliable and cost-efficient.
Let’s talk