DEV Community

Santanu Mohanta
Santanu Mohanta

Posted on

LangChain Essentials — The Only Things You Need Before LangGraph

Note: This article was written in July 2026 using LangChain 0.3.x. APIs may change in future versions — check the LangChain docs if something doesn't work.

When I started learning LangChain, I got overwhelmed. There are chains, agents, memory, retrievers, output parsers — dozens of abstractions. Then I realized: most of them are deprecated.

LangGraph (by the same team) has replaced the orchestration layer. But you still need LangChain's core building blocks inside LangGraph nodes. So I figured out the minimum you actually need to learn.

Here's everything, in one file.

The 4 Things That Matter

# Topic Why It Matters for LangGraph
1 LLM Setup You need to talk to a model
2 Prompt Templates + LCEL The LCEL pipe syntax carries over
3 Structured Output Pydantic models replace the old output parsers
4 Tool Calling This is the big one — LangGraph agents are built around the tool-calling loop

Let's walk through each one.


1. LLM Setup

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="llama-3.3-70b-versatile",
    temperature=0.0,
    api_key=os.environ["GROQ_API_KEY"],
    base_url="https://api.groq.com/openai/v1",
)
Enter fullscreen mode Exit fullscreen mode

ChatOpenAI works with any OpenAI-compatible API. Here I'm using Groq for free, fast inference with Llama 3.3.

2. Prompt Templates + LCEL

from langchain_core.prompts import ChatPromptTemplate

template_string = """Translate the text that is delimited by triple backticks \
into a style that is {style}.
text: ```

{text}

Enter fullscreen mode Exit fullscreen mode

"""

prompt_template = ChatPromptTemplate.from_template(template_string)
chain = prompt_template | llm
response = chain.invoke({"style": "formal English", "text": "yo what's up"})```

The pipe (|) syntax is called LCEL (LangChain Expression Language). It replaces the old LLMChain, SequentialChain, etc. Simple and composable.

3. Structured Output

The old way required ResponseSchema, StructuredOutputParser, and injecting format instructions into your prompt. The new way is just Pydantic:

from pydantic import BaseModel, Field

class ReviewInfo(BaseModel):
    """Information extracted from a product review."""
    gift: bool = Field(description="Was the item purchased as a gift?")
    delivery_days: int = Field(description="How many days to arrive? -1 if unknown.")
    price_value: list[str] = Field(description="Sentences about value or price.")

structured_llm = llm.with_structured_output(ReviewInfo, method="function_calling")
result = (prompt | structured_llm).invoke({"text": review})

print(result.gift)           # True  (a real bool, not the string "true")
print(result.delivery_days)  # 2     (a real int)
Enter fullscreen mode Exit fullscreen mode

Who does what:

Step Who
Converting Pydantic → JSON schema LangChain
Understanding schema & producing JSON The LLM
Parsing JSON back into Pydantic obj LangChain

No more format instructions in your prompt. The LLM never sees "return JSON" — it uses function calling under the hood.

4. Tool Calling — The Big One

This is what LangGraph automates. Understanding it manually first makes LangGraph click instantly.

Define tools — just Python functions with the @tool decorator:

from langchain_core.tools import tool

@tool
def get_current_weather(city: str) -> str:
    """Get the current weather for a given city."""
    return {"berlin": "17°C, cloudy"}.get(city.lower(), "No data")

@tool
def get_population(city: str) -> int:
    """Get the approximate population of a city."""
    return {"berlin": 3_700_000}.get(city.lower(), -1)
Enter fullscreen mode Exit fullscreen mode

The @tool decorator transforms these into BaseTool objects. The docstring becomes the description the LLM reads to decide when to call it.

Bind tools and call:

tools = [get_current_weather, get_population]
llm_with_tools = llm.bind_tools(tools)

messages = [HumanMessage("What's the weather and population in Berlin?")]
ai_response = llm_with_tools.invoke(messages)

print(ai_response.tool_calls)
# [{"name": "get_current_weather", "args": {"city": "Berlin"}, "id": "..."},
#  {"name": "get_population", "args": {"city": "Berlin"}, "id": "..."}]
Enter fullscreen mode Exit fullscreen mode

The LLM does not execute the tools. It returns a structured request asking you to run them.

Execute tools and send results back:

tool_map = {t.name: t for t in tools}

messages.append(ai_response)
for tc in ai_response.tool_calls:
    result = tool_map[tc["name"]].invoke(tc["args"])
    messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

final_response = llm_with_tools.invoke(messages)
print(final_response.content)
# "The weather in Berlin is 17°C and cloudy, with a population of 3.7 million."
Enter fullscreen mode Exit fullscreen mode

This loop — LLM decides → you execute → send result back → repeat — is exactly what LangGraph's ToolNode automates.


What to Skip

If you're heading to LangGraph, don't bother learning these legacy LangChain abstractions:

  • LLMChain → replaced by LCEL (prompt | llm)
  • SequentialChain → replaced by LCEL pipes
  • RouterChain → replaced by LangGraph branching
  • ConversationChain → replaced by LangGraph state
  • AgentExecutor → replaced by LangGraph agent loop

How LangChain and LangGraph Relate

LangGraph is not a replacement for LangChain — it builds on top of it:

  • LangChain Core → LLMs, prompts, tools, messages (you still use these)
  • LangGraph → Orchestration layer (controls how those blocks connect and loop)

LangGraph came in early 2024 because LangChain's original agent/chain abstractions were too rigid — hard to customize, no support for cycles or branching, and memory was bolted on rather than built in.


Get the Code

The entire thing is one file: github.com/santanu2908/langchain-essentials

git clone https://github.com/santanu2908/langchain-essentials.git
cd langchain-essentials
uv sync
# add your GROQ_API_KEY to .env
uv run main.py
Enter fullscreen mode Exit fullscreen mode

Next up: LangGraph. If this helped you, follow along — I'll be sharing that journey too.

I'm Santanu Mohanta — connect with me on LinkedIn or check out my projects on GitHub.

Top comments (0)