LangChain Tutorial: A Complete Guide to Building LLM Applications in 2025

15 min read

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.

Open in Agent

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.

Mid-read shortcut

Turn the useful parts into next steps

Vife Agent can convert this guide into a prioritized workflow with tasks, risks, and reusable prompts.

Create a brief

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:

python
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:

python
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:

python
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:

python
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:

python
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:

python
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:

bash
pip install langchain langchain-openai langchain-anthropic pip install chromadb # For vector storage pip install tiktoken # For token counting

Set API keys as environment variables:

bash
export OPENAI_API_KEY="your-key-here" export ANTHROPIC_API_KEY="your-key-here"

Or load them from a .env file:

python
from dotenv import load_dotenv import os load_dotenv() api_key = os.getenv("OPENAI_API_KEY")

Project Structure

Organize code to separate concerns:

text
project/ ├── chains/ # Chain definitions ├── prompts/ # Prompt templates ├── tools/ # Custom tools ├── data/ # Documents and embeddings ├── config.py # Configuration └── main.py # Entry point

This structure scales from prototypes to production systems.

Testing Your Setup

Verify everything works with a minimal example:

python
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:

python
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:

python
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:

python
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:

python
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:

python
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:

python
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 TypeOptionsWhen 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:

python
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:

python
# 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:

python
# 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.""" pass

Include input format, output format, and when to use the tool.

Mistake 4: No Error Handling

LLMs fail unpredictably. Wrap chains in try-except blocks:

python
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:

python
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.