LangChain Tutorial: A Complete Guide to Building LLM Applications in 2025
Make this article actionable
Send the article context into Vife Agent and turn it into a plan, checklist, or draft you can keep working on.
LangChain Tutorial: A Complete Guide to Building LLM Applications in 2025
Building applications with large language models requires more than just API calls. You need chains of operations, memory management, retrieval systems, and robust error handling. LangChain emerged as the framework that handles these complexities, letting you focus on building rather than reinventing infrastructure.
This tutorial takes you from installation through production-ready patterns. You'll learn the core abstractions, build working examples, and understand when LangChain adds value versus when simpler approaches work better. Whether you're prototyping a chatbot, building a document analysis tool, or creating an agent system, you'll have the patterns and code to start immediately.
Quick Answer: What You Need to Know About LangChain
LangChain is a Python and JavaScript framework for building applications powered by language models. It provides:
- Chains: Sequences of operations that transform inputs into outputs
- Agents: Systems that decide which tools to use based on user input
- Memory: Conversation history and context management
- Retrieval: Integration with vector databases for document search
- Tools: Pre-built integrations with APIs, databases, and services
The framework works with OpenAI, Anthropic, Google, and open-source models. You connect components declaratively, test them in isolation, and deploy with standard Python tooling.
Most developers start with simple chains, add retrieval when working with documents, then build agents for complex workflows. The learning curve is moderate—you'll write working code in hours, but mastering production patterns takes weeks of experimentation.
Turn the useful parts into next steps
Vife Agent can convert this guide into a prioritized workflow with tasks, risks, and reusable prompts.
Understanding LangChain's Core Architecture
LangChain organizes around five fundamental abstractions that handle different aspects of LLM applications.
Models and Prompts
Models represent the LLM interface. LangChain supports chat models (conversational) and LLMs (completion-based). You instantiate them with API keys and parameters:
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
# OpenAI model
chat = ChatOpenAI(model="gpt-4", temperature=0.7)
# Anthropic model
claude = ChatAnthropic(model="claude-3-sonnet-20240229")Prompt templates separate your instructions from variable data. This makes prompts reusable and testable:
from langchain.prompts import ChatPromptTemplate
template = ChatPromptTemplate.from_messages([
("system", "You are a technical writer who explains {topic} clearly."),
("user", "{question}")
])
prompt = template.format_messages(
topic="Python programming",
question="How do decorators work?"
)Chains: Composing Operations
Chains connect components into workflows. The simplest chain combines a prompt and model:
from langchain.chains import LLMChain
chain = template | chat
result = chain.invoke({
"topic": "machine learning",
"question": "What is gradient descent?"
})The pipe operator (|) creates a sequence where each component's output feeds the next. More complex chains add parsers, validators, or branching logic.
Memory: Managing Conversation State
Memory systems store conversation history. Buffer memory keeps recent messages:
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
memory = ConversationBufferMemory()
conversation = ConversationChain(
llm=chat,
memory=memory
)
conversation.predict(input="My name is Alice")
conversation.predict(input="What's my name?") # Returns "Alice"Summary memory condenses long conversations. Entity memory tracks specific facts. Choose based on your context window and cost constraints.
Retrievers: Connecting External Knowledge
Retrievers fetch relevant documents from vector stores, databases, or APIs. They power RAG (Retrieval-Augmented Generation) systems:
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
# Split documents
splitter = RecursiveCharacterTextSplitter(chunk_size=1000)
chunks = splitter.split_documents(documents)
# Create vector store
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=OpenAIEmbeddings()
)
# Retrieve relevant chunks
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
relevant_docs = retriever.get_relevant_documents("query text")Agents: Dynamic Decision-Making
Agents choose which tools to use based on user input. They reason through multi-step problems:
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain.tools import Tool
def search_database(query: str) -> str:
# Your database logic
return f"Results for {query}"
tools = [
Tool(
name="DatabaseSearch",
func=search_database,
description="Search the product database"
)
]
agent = create_openai_functions_agent(chat, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools)
result = executor.invoke({"input": "Find products under $50"})Agents iterate until they solve the problem or hit limits you set.
Setting Up Your LangChain Development Environment
Start with a clean Python environment. LangChain requires Python 3.8 or higher.
Installation and Configuration
Install the core library and provider packages:
pip install langchain langchain-openai langchain-anthropic
pip install chromadb # For vector storage
pip install tiktoken # For token countingSet API keys as environment variables:
export OPENAI_API_KEY="your-key-here"
export ANTHROPIC_API_KEY="your-key-here"Or load them from a .env file:
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv("OPENAI_API_KEY")Project Structure
Organize code to separate concerns:
project/
├── chains/ # Chain definitions
├── prompts/ # Prompt templates
├── tools/ # Custom tools
├── data/ # Documents and embeddings
├── config.py # Configuration
└── main.py # Entry pointThis structure scales from prototypes to production systems.
Testing Your Setup
Verify everything works with a minimal example:
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
chat = ChatOpenAI(model="gpt-3.5-turbo")
template = ChatPromptTemplate.from_messages([
("user", "Say hello in {language}")
])
chain = template | chat
result = chain.invoke({"language": "Spanish"})
print(result.content)If this runs without errors, your environment is ready.
Building Your First LangChain Application
Let's build a document Q&A system that answers questions using your own documents. This demonstrates retrieval, chains, and memory.
Step 1: Prepare Your Documents
Load and split documents into chunks:
from langchain.document_loaders import TextLoader, DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# Load documents
loader = DirectoryLoader('./docs', glob="**/*.txt")
documents = loader.load()
# Split into chunks
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n\n", "\n", " ", ""]
)
chunks = splitter.split_documents(documents)Chunk size balances context and retrieval precision. Smaller chunks retrieve more precisely but may lack context. Larger chunks provide context but may include irrelevant information.
Step 2: Create a Vector Store
Embed chunks and store them for retrieval:
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)The vector store persists to disk. Subsequent runs load existing embeddings instead of re-embedding.
Step 3: Build the Retrieval Chain
Connect retrieval to generation:
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
chat = ChatOpenAI(model="gpt-4", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
llm=chat,
chain_type="stuff",
retriever=vectorstore.as_retriever(search_kwargs={"k": 3}),
return_source_documents=True
)
result = qa_chain({"query": "What are the main features?"})
print(result["result"])
print(f"Sources: {len(result['source_documents'])}")The "stuff" chain type inserts all retrieved documents into the prompt. Other types (map_reduce, refine) handle larger document sets.
Step 4: Add Conversation Memory
Make the system conversational:
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="answer"
)
conversational_chain = ConversationalRetrievalChain.from_llm(
llm=chat,
retriever=vectorstore.as_retriever(),
memory=memory,
return_source_documents=True
)
# First question
result1 = conversational_chain({"question": "What is LangChain?"})
# Follow-up uses context
result2 = conversational_chain({"question": "How do I install it?"})Memory tracks the conversation, so follow-up questions understand context.
Advanced Patterns: Agents and Custom Tools
Agents extend beyond simple retrieval by choosing actions dynamically.
Creating Custom Tools
Tools give agents capabilities. Define them as functions with clear descriptions:
from langchain.tools import tool
@tool
def calculate_statistics(data: str) -> str:
"""Calculate mean, median, and standard deviation from comma-separated numbers."""
numbers = [float(x.strip()) for x in data.split(',')]
mean = sum(numbers) / len(numbers)
sorted_nums = sorted(numbers)
median = sorted_nums[len(numbers) // 2]
return f"Mean: {mean:.2f}, Median: {median:.2f}"
@tool
def search_documentation(query: str) -> str:
"""Search technical documentation for relevant information."""
# Your search logic here
return f"Documentation results for: {query}"Descriptions matter—agents use them to decide when to call each tool.
Building an Agent Executor
Combine tools with an agent:
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant with access to tools."),
MessagesPlaceholder(variable_name="chat_history", optional=True),
("user", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad")
])
tools = [calculate_statistics, search_documentation]
agent = create_openai_functions_agent(chat, tools, prompt)
executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
max_iterations=3
)
result = executor.invoke({
"input": "Calculate statistics for these numbers: 10, 20, 30, 40, 50"
})The agent decides which tool to use, calls it, and interprets results.
Agent Decision-Making Patterns
Agents work best for:
- Multi-step reasoning: Breaking complex questions into sub-tasks
- Tool selection: Choosing between multiple data sources or APIs
- Iterative refinement: Adjusting approach based on intermediate results
They struggle with:
- Strict workflows: Use chains when steps are predetermined
- High reliability needs: Agents can make unexpected tool choices
- Cost sensitivity: Multiple LLM calls increase costs
Put This Into Practice With an AI Agent
LangChain excels at building components, but managing conversations, context, and tool orchestration across sessions requires additional infrastructure. This is where dedicated AI agent platforms add value.
An AI agent workspace like Vife handles:
- Persistent memory across conversations without manual state management
- Tool execution with built-in error handling and retry logic
- Multi-agent coordination when tasks require specialized capabilities
- Context management that automatically maintains relevant information
You can prototype with LangChain locally, validate your chains and prompts, then deploy them within an agent system that handles production concerns. The patterns you learn—prompt engineering, retrieval strategies, tool design—transfer directly.
For example, a customer support agent might use LangChain components you built:
- Your retrieval chain for documentation search
- Your custom tools for database queries
- Your prompt templates for consistent responses
The agent workspace provides the conversation interface, memory persistence, and orchestration layer. You focus on the domain logic and LangChain components.
This separation lets you iterate quickly. Test chains in isolation, validate with sample data, then integrate into the agent environment. When you need to update retrieval logic or add tools, you modify LangChain components without touching the agent infrastructure.
Choosing the Right LangChain Components
LangChain offers multiple options for each task. Choose based on your specific requirements.
| Component Type | Options | When to Use |
|---|---|---|
Memory | Buffer, Summary, Entity, Vector | Buffer for short conversations, Summary for long ones, Entity for tracking facts, Vector for semantic search |
Chain Type | Stuff, Map-Reduce, Refine, Map-Rerank | Stuff for small docs, Map-Reduce for parallel processing, Refine for iterative improvement |
Retriever | Vector, BM25, Ensemble, Parent Document | Vector for semantic search, BM25 for keyword matching, Ensemble for both, Parent for context |
Agent Type | OpenAI Functions, ReAct, Structured Chat | Functions for reliability, ReAct for transparency, Structured for complex inputs |
Text Splitter | Recursive, Character, Token, Semantic | Recursive for general use, Token for precise limits, Semantic for meaning-based splits |
Decision Framework
For document Q&A:
- Start with RecursiveCharacterTextSplitter and vector retrieval
- Use "stuff" chain type if documents fit in context window
- Add conversation memory if building a chatbot
- Consider ensemble retriever if keyword matching matters
For agents:
- Use OpenAI Functions agents for production (most reliable)
- Limit to 3-5 tools initially (more tools confuse the agent)
- Set max_iterations to prevent runaway costs
- Add verbose=True during development to see reasoning
For memory:
- Use ConversationBufferMemory for demos and prototypes
- Switch to ConversationSummaryMemory when conversations exceed 10 messages
- Use ConversationEntityMemory when tracking specific facts matters
- Consider external storage (Redis, PostgreSQL) for production
Common LangChain Mistakes and How to Avoid Them
Mistake 1: Ignoring Token Limits
Chains fail when prompts exceed model context windows. Monitor token usage:
from langchain.callbacks import get_openai_callback
with get_openai_callback() as cb:
result = chain.invoke({"input": "query"})
print(f"Tokens used: {cb.total_tokens}")
print(f"Cost: ${cb.total_cost:.4f}")If you hit limits, reduce chunk size, use map-reduce chains, or summarize context.
Mistake 2: Poor Chunk Strategy
Chunking by character count splits mid-sentence or mid-concept. Use semantic splitters or adjust separators:
# Better: Respect document structure
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
separators=["\n## ", "\n### ", "\n\n", "\n", ". ", " ", ""]
)Test retrieval quality with sample queries before committing to a strategy.
Mistake 3: Vague Tool Descriptions
Agents rely on descriptions to choose tools. Be specific:
# Weak
@tool
def get_data(query: str) -> str:
"""Gets data."""
pass
# Strong
@tool
def get_sales_data(date_range: str) -> str:
"""Retrieve sales data for a specific date range.
Input should be format: YYYY-MM-DD to YYYY-MM-DD.
Returns total sales, transaction count, and top products."""
passInclude input format, output format, and when to use the tool.
Mistake 4: No Error Handling
LLMs fail unpredictably. Wrap chains in try-except blocks:
try:
result = chain.invoke({"input": user_query})
except Exception as e:
print(f"Chain failed: {e}")
# Fallback logic
result = {"output": "I encountered an error. Please try rephrasing."}Log errors for debugging. Consider retry logic for transient failures.
Mistake 5: Skipping Evaluation
Test chains with diverse inputs before deploying:
test_cases = [
{"input": "What is X?", "expected_keywords": ["definition", "example"]},
{"input": "How do I Y?", "expected_keywords": ["step", "process"]},
]
for test in test_cases:
result = chain.invoke(test["input"])
for keyword in test["expected_keywords"]:
assert keyword.lower() in result["output"].lower()Build a test suite that covers edge cases, ambiguous queries, and error conditions.
Production Deployment Checklist
Before deploying LangChain applications, verify these items:
Configuration and Security:
- API keys stored in environment variables or secret management
- Rate limiting implemented for external API calls
- Input validation to prevent injection attacks
- Logging configured for debugging and monitoring
- Error handling for all chain invocations
Performance and Cost:
- Token usage monitored and alerted
- Caching implemented for repeated queries
- Vector store indices optimized
- Batch processing for high-volume operations
- Timeout limits set for long-running chains
Quality and Testing:
- Test suite covers common queries and edge cases
- Retrieval quality validated with sample documents
- Agent tool selection tested across scenarios
- Output format validated and parsed correctly
- Fallback responses defined for failures
Monitoring and Maintenance:
- Metrics tracked (latency, success rate, token usage)
- Alerts configured for errors and anomalies
- Vector store backup strategy defined
- Model version pinned (not using "latest")
- Documentation updated with deployment details
Frequently Asked Questions
Q: Should I use LangChain or build with the OpenAI API directly?
Use LangChain when you need chains, retrieval, or agents. For simple completions or chat, direct API calls are simpler and more transparent. LangChain adds value when composing multiple operations or integrating external data.
Q: How do I reduce costs with LangChain?
Use cheaper models (GPT-3.5 instead of GPT-4) for simple tasks. Implement caching for repeated queries. Reduce chunk overlap in retrievers. Set max_tokens limits. Monitor usage with callbacks and optimize high-cost operations.
Q: Can I use LangChain with local/open-source models?
Yes. LangChain supports Hugging Face models, Ollama, LlamaCpp, and others. Replace ChatOpenAI with the appropriate model class. Performance and capabilities vary significantly between models.
Q: How do I debug chains that produce wrong answers?
Enable verbose mode to see intermediate steps. Check retrieved documents for relevance. Validate prompt templates with sample data. Test each component in isolation. Use callbacks to inspect inputs and outputs at each step.
Q: What's the difference between agents and chains?
Chains execute predetermined sequences. Agents decide which tools to use based on input. Use chains when the workflow is fixed. Use agents when the system needs to choose between multiple approaches.
Q: How do I handle conversation context in production?
Store conversation history in a database (PostgreSQL, Redis). Load relevant history when initializing memory. Implement session management to track users. Consider summarizing old messages to manage context window limits.
Q: Can LangChain handle multiple languages?
Yes, but performance depends on the underlying model. GPT-4 handles many languages well. Embeddings models vary in multilingual support. Test retrieval quality in your target languages before deploying.
Moving From Tutorial to Production
LangChain provides the building blocks, but production systems require additional considerations.
Start with clear requirements. Define what success looks like—accuracy thresholds, latency limits, cost budgets. Build the simplest system that meets these requirements. Add complexity only when simpler approaches fail.
Test extensively. Create evaluation datasets with expected outputs. Measure retrieval precision and recall. Validate agent tool selection. Test edge cases and failure modes. Automated testing catches regressions as you iterate.
Monitor in production. Track token usage, latency, error rates, and user satisfaction. Set alerts for anomalies. Review logs regularly to identify improvement opportunities. User feedback reveals issues that testing misses.
Iterate based on data. If retrieval quality is poor, adjust chunk size or try different embeddings. If agents choose wrong tools, improve descriptions or reduce tool count. If costs are high, optimize prompts or use cheaper models for appropriate tasks.
Document your decisions. Record why you chose specific components, what alternatives you tested, and what tradeoffs you made. Future maintainers (including yourself) will thank you.
Conclusion: Your Next Steps With LangChain
You now have the foundation to build LLM applications with LangChain. You understand the core abstractions, have working code examples, and know common pitfalls to avoid.
Start with a focused project. Build a document Q&A system for your domain, create an agent with 2-3 useful tools, or prototype a conversational interface. Keep scope small initially. Validate the approach before expanding.
Join the LangChain community. The framework evolves rapidly—new components, patterns, and integrations appear regularly. Follow the documentation, explore example repositories, and learn from others building similar systems.
When you're ready to move beyond prototypes, consider how your LangChain components fit into a broader agent system. The chains, tools, and prompts you build become reusable modules within a production environment that handles orchestration, memory, and conversation management.
Continue building in Vife Agent where you can deploy your LangChain components within a managed agent workspace, test with real users, and iterate without managing infrastructure. Your tutorial code becomes production-ready faster when the platform handles the operational complexity.