LangChain is a framework for building applications with LLMs. It provides abstractions for chains, memory, agents, and retrieval — so you don't have to wire everything up from scratch.
This guide gets you productive with LangChain quickly. All examples use LangChain v0.3 syntax.
Installation
pip install langchain langchain-anthropic langchain-community chromadb
export ANTHROPIC_API_KEY="your-key-here"
Core Concept: Chains
A chain is a sequence of steps: prompt → LLM → output parser.
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
llm = ChatAnthropic(model="claude-sonnet-4-6")
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant."),
("human", "{question}"),
])
chain = prompt | llm | StrOutputParser()
response = chain.invoke({"question": "What is LangChain?"})
print(response)
The | operator connects components into a chain (LCEL — LangChain Expression Language).
Adding Memory
from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import MessagesPlaceholder
memory = ConversationBufferMemory(return_messages=True)
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant."),
MessagesPlaceholder(variable_name="history"),
("human", "{input}"),
])
chain = prompt | llm | StrOutputParser()
def chat(user_input: str) -> str:
history = memory.load_memory_variables({})["history"]
response = chain.invoke({"input": user_input, "history": history})
memory.save_context({"input": user_input}, {"output": response})
return response
print(chat("My name is Alex."))
print(chat("What's my name?")) # → Alex
RAG with LangChain
from langchain_community.document_loaders import WebBaseLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA
loader = WebBaseLoader("https://kalyna.pro/what-is-model-context-protocol-mcp/")
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
vectorstore = Chroma.from_documents(chunks, embeddings)
qa = RetrievalQA.from_chain_type(
llm=llm,
retriever=vectorstore.as_retriever(search_kwargs={"k": 5}),
)
answer = qa.invoke("What is MCP and why does it matter?")
print(answer["result"])
Agents
Agents let the LLM decide which tools to call.
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain.tools import tool
from langchain_core.prompts import MessagesPlaceholder
import requests
@tool
def get_weather(city: str) -> str:
"""Get current weather for a city."""
r = requests.get(f"https://wttr.in/{city}?format=3")
return r.text
@tool
def calculate(expression: str) -> str:
"""Evaluate a math expression safely."""
try:
return str(eval(expression, {"__builtins__": {}}, {}))
except Exception as e:
return f"Error: {e}"
tools = [get_weather, calculate]
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant with access to tools."),
MessagesPlaceholder("chat_history", optional=True),
("human", "{input}"),
MessagesPlaceholder("agent_scratchpad"),
])
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({"input": "What's the weather in Kyiv and what is 15% of 340?"})
print(result["output"])
Structured Output
from pydantic import BaseModel
class Article(BaseModel):
title: str
summary: str
tags: list[str]
structured_llm = llm.with_structured_output(Article)
result = structured_llm.invoke("Summarize RAG for a developer audience.")
print(result.title)
print(result.tags)
When to Use LangChain vs Raw API
| Use Case | LangChain | Raw API |
|---|---|---|
| Quick prototype | Fast to build | Slower |
| Complex multi-step chains | Built-in abstractions | Manual wiring |
| Simple single-turn calls | Overkill | Simpler |
| Custom control flow | Limited | Full control |
| Production reliability | Needs testing | More predictable |
LangChain shines for prototyping and standard patterns (RAG, agents, memory). For production apps, consider using the raw API with LangChain's components selectively.
Originally published at kalyna.pro
Top comments (0)