Everything You Need to Know About LangChain
Build powerful LLM applications with chains, agents, memory, and tools — a deep-dive from first principles to production deployment.
What is LangChain?
LangChain is an open-source framework that lets developers build applications powered by large language models (LLMs). Rather than writing raw API calls and stitching together prompts manually, LangChain gives you composable abstractions — chains, agents, memory, tools, and retrievers — that turn complex multi-step AI workflows into clean, maintainable code.
Launched in late 2022 by Harrison Chase, LangChain has grown into the most widely adopted LLM framework, with over 90,000 GitHub stars and active SDKs in Python and JavaScript/TypeScript.
Why Use LangChain?
Without a framework you'd need to manually handle: prompt templating, multi-step reasoning, chat history, document retrieval, tool calling, output parsing, streaming, and retries. LangChain standardises all of this.
Core Architecture
LangChain is built around a simple principle: LCEL — LangChain Expression Language. It uses the pipe operator (|) to compose components. Every component implements the same Runnable interface, so they're interchangeable and streamable.
Installation & Setup
LangChain is split into focused packages. Install only what you need:
# Core framework pip install langchain # OpenAI integration pip install langchain-openai # Anthropic / Claude integration pip install langchain-anthropic # Community integrations (tools, loaders, etc) pip install langchain-community # Vector stores pip install chromadb faiss-cpu pinecone-client # Document loaders pip install pypdf unstructured
LLMChain and ConversationChain. Use LCEL syntax instead — it's faster, streamable, and easier to debug.LCEL — LangChain Expression Language
LCEL is the core building paradigm. Every component is a Runnable — it can be invoked, streamed, batched, or piped.
from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser # 1. Define the prompt template prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant."), ("human", "{question}"), ]) # 2. Initialise the model model = ChatOpenAI(model="gpt-4o", temperature=0) # 3. Build the chain with the pipe operator (LCEL) chain = prompt | model | StrOutputParser() # 4. Invoke response = chain.invoke({"question": "What is LangChain?"}) print(response)
Streaming Responses
for chunk in chain.stream({"question": "Explain LCEL in 3 bullets"}): print(chunk, end="", flush=True)
Prompt Templates
Prompt templates separate your instructions from the input data, making them reusable and testable.
from langchain_core.prompts import ( ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, FewShotChatMessagePromptTemplate, ) # ── Simple chat prompt ── chat_prompt = ChatPromptTemplate.from_messages([ ("system", "You are a {role}. Respond in {language}."), ("human", "{input}"), ]) # ── Few-shot prompt ── examples = [ {"input": "happy", "output": "sad"}, {"input": "tall", "output": "short"}, ] example_prompt = ChatPromptTemplate.from_messages([ ("human", "Antonym of {input}?"), ("ai", "{output}"), ]) few_shot = FewShotChatMessagePromptTemplate( examples=examples, example_prompt=example_prompt )
Model Integrations
LangChain wraps any LLM behind a unified interface. Switch providers by changing one import.
| Provider | Package | Chat Models | Embeddings | Local |
|---|---|---|---|---|
| OpenAI | langchain-openai | ✓ | ✓ | ✗ |
| Anthropic | langchain-anthropic | ✓ | ✗ | ✗ |
| Google (Gemini) | langchain-google-genai | ✓ | ✓ | ✗ |
| Ollama | langchain-community | ✓ | ✓ | ✓ |
| HuggingFace | langchain-huggingface | ✓ | ✓ | ✓ |
| Cohere | langchain-cohere | ✓ | ✓ | ✗ |
Conversation Memory
Memory lets your chain remember previous turns. In LCEL, you manage history explicitly using RunnableWithMessageHistory.
from langchain_community.chat_message_histories import ChatMessageHistory from langchain_core.runnables.history import RunnableWithMessageHistory from langchain_core.prompts import MessagesPlaceholder store = {} # session_id → ChatMessageHistory def get_session_history(session_id): if session_id not in store: store[session_id] = ChatMessageHistory() return store[session_id] prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant."), MessagesPlaceholder("history"), ("human", "{input}"), ]) chain = prompt | ChatOpenAI() | StrOutputParser() with_memory = RunnableWithMessageHistory( chain, get_session_history, input_messages_key="input", history_messages_key="history", ) with_memory.invoke( {"input": "My name is Alice."}, config={"configurable": {"session_id": "abc-123"}} )
Retrieval-Augmented Generation (RAG)
RAG is the most popular LangChain pattern: ingest documents, embed them into a vector store, and retrieve relevant chunks at query time to ground the model's answer.
- LoadUse a Document Loader (PDFLoader, WebBaseLoader, NotionLoader…) to bring in raw text.
- SplitUse a Text Splitter to break documents into overlapping chunks.
- EmbedConvert chunks into dense vector representations using an Embeddings model.
- StorePersist vectors in a vector database (Chroma, Pinecone, FAISS…).
- RetrieveAt query time, embed the user's question and find the top-k similar chunks.
- GeneratePass retrieved chunks + question into the LLM to produce a grounded answer.
from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma from langchain_core.runnables import RunnablePassthrough # 1. Load loader = PyPDFLoader("handbook.pdf") docs = loader.load() # 2. Split splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200 ) chunks = splitter.split_documents(docs) # 3 + 4. Embed & Store vectorstore = Chroma.from_documents( chunks, embedding=OpenAIEmbeddings() ) # 5. Retriever retriever = vectorstore.as_retriever(search_kwargs={"k": 4}) # 6. RAG chain rag_prompt = ChatPromptTemplate.from_template(""" Answer using only the context below. Context: {context} Question: {question} """) rag_chain = ( {"context": retriever, "question": RunnablePassthrough()} | rag_prompt | ChatOpenAI(model="gpt-4o") | StrOutputParser() ) print(rag_chain.invoke("What is the refund policy?"))
Agents & Tools
Agents let the LLM reason about which tool to call and in what order, rather than following a fixed chain. This enables truly dynamic, multi-step task execution.
from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain_community.tools import DuckDuckGoSearchRun from langchain_core.tools import tool # Define a custom tool with the @tool decorator @tool def calculator(expression: str) -> str: """Evaluate a maths expression. Input: '2 + 2 * 10'""" return str(eval(expression)) tools = [DuckDuckGoSearchRun(), calculator] agent_prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful research assistant."), ("human", "{input}"), MessagesPlaceholder("agent_scratchpad"), ]) llm = ChatOpenAI(model="gpt-4o", temperature=0) agent = create_tool_calling_agent(llm, tools, agent_prompt) executor = AgentExecutor(agent=agent, tools=tools, verbose=True) executor.invoke({ "input": "Search for today's Bitcoin price and multiply it by 3.14" })
Output Parsers
Output parsers transform the raw model response into structured Python objects.
from langchain_core.output_parsers import JsonOutputParser from langchain_core.pydantic_v1 import BaseModel, Field class Movie(BaseModel): title: str = Field(description="Movie title") year: int = Field(description="Release year") genres: list[str] = Field(description="List of genres") parser = JsonOutputParser(pydantic_object=Movie) chain = ( ChatPromptTemplate.from_template( "Return info about the movie '{name}'.\n{format_instructions}" ).partial(format_instructions=parser.get_format_instructions()) | ChatOpenAI() | parser ) result = chain.invoke({"name": "Inception"}) # → Movie(title='Inception', year=2010, genres=['sci-fi','thriller'])
LangSmith — Observability & Debugging
LangSmith traces every step of your chain — inputs, outputs, latency, token usage, and costs. It's essential for debugging and evaluation in production.
# Set environment variables to enable tracing export LANGCHAIN_TRACING_V2="true" export LANGCHAIN_API_KEY="ls_..." export LANGCHAIN_PROJECT="my-app"
That's it — once these vars are set, every chain/agent call is automatically traced and visible at smith.langchain.com.
LangChain.js
The JavaScript/TypeScript SDK has feature parity with the Python version and is ideal for Next.js, Node, or Vercel edge deployments.
import { ChatOpenAI } from "@langchain/openai"; import { ChatPromptTemplate } from "@langchain/core/prompts"; import { StringOutputParser } from "@langchain/core/output_parsers"; const prompt = ChatPromptTemplate.fromMessages([ ["system", "You are a helpful assistant."], ["human", "{question}"], ]); const chain = prompt .pipe(new ChatOpenAI({ model: "gpt-4o" })) .pipe(new StringOutputParser()); const answer = await chain.invoke({ question: "What is LangChain?" }); console.log(answer);
Best Practices & Production Tips
1. Always use LCEL over legacy chains
The old LLMChain and ConversationalRetrievalChain are deprecated. LCEL is faster, supports streaming natively, and is easier to test.
2. Cache expensive LLM calls
from langchain.globals import set_llm_cache from langchain_community.cache import SQLiteCache set_llm_cache(SQLiteCache(database_path=".langchain.db"))
3. Use async for high-throughput applications
import asyncio results = await chain.abatch([ {"question": "Q1"}, {"question": "Q2"}, {"question": "Q3"}, ])
4. Evaluate with LangSmith datasets
Create evaluation datasets in LangSmith and run evaluate() to benchmark your chain against ground truth answers before deploying changes.
5. Prefer LangGraph for complex agents
If your agent needs loops, conditional branching, multiple specialized sub-agents, or human-in-the-loop approval, use LangGraph — it gives you explicit state management and is production-battle-tested.
The LangChain Ecosystem
| Package | Purpose |
|---|---|
langchain-core | Base abstractions (Runnable, prompts, messages) |
langchain | Chains, agents, memory, text splitters |
langchain-community | Third-party integrations (100+ tools, loaders) |
langchain-openai | OpenAI chat + embeddings |
langchain-anthropic | Claude models |
| langgraph | Stateful multi-agent orchestration graphs |
| langserve | Deploy chains as REST APIs (FastAPI-based) |
| langsmith | Tracing, evaluation, dataset management |

0 Comments