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.
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.