Skip to content
LangChain Guide — Building LLM Applications with Chains and Agents

LangChain Guide — Building LLM Applications with Chains and Agents

DodaTech Updated Jun 7, 2026 8 min read

LangChain is a framework for developing applications powered by large language models, providing modular components for chains, agents, memory, retrieval, and tool integration.

What You’ll Learn

  • Building chains that combine LLM calls with other processing steps
  • Creating agents that dynamically choose tools to accomplish tasks
  • Implementing conversational memory and document retrieval (RAG)
  • Using vector stores for semantic search and document QA

Why LangChain Matters

Raw LLM APIs are powerful but limited. LangChain provides the scaffolding to build multi-step applications: chatbots with memory, document QA systems, automated research agents, and more. DodaTech’s Durga Antivirus Pro uses LangChain chains to orchestrate multi-stage threat analysis — first classifying a file, then searching threat databases, then generating a report. Doda Browser uses LangChain agents with web search tools for smart research assistance.

    flowchart LR
    A["LLM\nOpenAI/Claude"] --> B["LangChain\nFramework"]
    B --> C["Chains\nSequential Steps"]
    B --> D["Agents\nDynamic Tools"]
    B --> E["Memory\nConversation"]
    B --> F["RAG\nRetrieval"]
    F --> G["Vector Store\nChroma/Pinecone"]
    F --> H["Document\nLoaders"]
    style B fill:#dbeafe,stroke:#2563eb
  

Setting Up LangChain

Install LangChain with your chosen LLM provider.

from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

llm = ChatOpenAI(model="gpt-4")
response = llm.invoke([HumanMessage(content="What is LangChain?")])
print(response.content)

Expected output:

LangChain is a framework for developing applications powered by language models. It provides modular components for chains, agents, memory, and retrieval, allowing developers to build complex LLM workflows with minimal boilerplate.

Building Chains

Chains let you combine multiple steps. A simple chain takes input, passes it through a prompt template, calls the LLM, and parses the output.

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_template(
    "Explain {concept} in simple terms with a real-world analogy."
)
chain = prompt | llm | StrOutputParser()

result = chain.invoke({"concept": "RAG (retrieval augmented generation)"})
print(result)

Expected output:

RAG is like a student taking an open-book exam. Instead of relying only on what they remember (the LLM's training data), they can look up specific information in the textbook (your documents) to give more accurate, up-to-date answers. The LLM retrieves relevant passages from your knowledge base before generating each response.

Chains use LangChain’s pipe (|) operator, similar to Unix pipes. Each component transforms data and passes it to the next. This pattern is used in Durga Antivirus Pro’s threat report pipeline: raw file -> classification chain -> database lookup -> formatted report.

Conversational Memory

Memory lets your LLM remember previous interactions. LangChain provides several memory types.

from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain

memory = ConversationBufferMemory()
conversation = ConversationChain(llm=llm, memory=memory)

print(conversation.predict(input="Hi, I'm learning LangChain."))
print(conversation.predict(input="What was my name?"))

Expected output:

Hello! Welcome to LangChain. I'd be happy to help you learn about building LLM applications. What would you like to know?
You mentioned you're learning LangChain, but you didn't share your name yet. What would you like me to call you?

Agents and Tools

Agents decide which tools to use based on the task. Define tools and let the agent plan its approach.

from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain.tools import tool
from langchain_core.prompts import ChatPromptTemplate

@tool
def search_knowledge_base(query: str) -> str:
    """Search the internal knowledge base for documentation."""
    return f"Results for '{query}': LangChain supports Python and JavaScript."

tools = [search_knowledge_base]
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant with access to tools."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

agent = create_tool_calling_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

result = agent_executor.invoke({"input": "What languages does LangChain support?"})
print(result["output"])

Expected output:

LangChain supports both Python and JavaScript. You can use it with various LLM providers including OpenAI, Anthropic, and open-source models.

RAG — Retrieval Augmented Generation

RAG combines document retrieval with LLM generation. Load documents, split them, embed them into a vector store, then retrieve relevant chunks for each query.

from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA

loader = TextLoader("threat_report.txt")
documents = loader.load()

text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
docs = text_splitter.split_documents(documents)

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = Chroma.from_documents(docs, embeddings)

qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=vectorstore.as_retriever(search_kwargs={"k": 3})
)

result = qa_chain.invoke({"query": "What indicators of compromise were found?"})
print(result["result"])

Expected output (varies based on document content):

Based on the threat report, three indicators of compromise were identified:
1. Suspicious outbound connection to 203.0.113.42 on port 4444
2. File hash a1b2c3d4e5f6 matching known Cobalt Strike beacon
3. Unusual registry modification at HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

Each indicator should be investigated using the incident response playbook.

Durga Antivirus Pro uses this exact pattern: security reports are loaded into a vector store, and analysts query the system using natural language to find relevant threat intelligence.

Document Loaders and Splitters

LangChain supports 100+ document loaders for PDFs, web pages, databases, and more.

from langchain_community.document_loaders import WebBaseLoader

loader = WebBaseLoader("https://docs.anthropic.com/en/docs/intro-to-claude")
docs = loader.load()

splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = splitter.split_documents(docs)
print(f"Loaded {len(docs)} document(s), split into {len(chunks)} chunks")

Expected output:

Loaded 1 document(s), split into 24 chunks

Common Errors

1. OpenAI API Key Not Set

LangChain reads OPENAI_API_KEY from the environment. Missing it causes an AuthenticationError. Set it before initializing any ChatOpenAI instance.

2. Vector Store Persistence Issues

Chroma saves to disk by default. If the directory is not writable or you run multiple processes, you may get PermissionError. Use a unique persist directory per process.

3. Chain Input Mismatch

Prompt templates with specific variables (e.g., {concept}) must receive all required keys in the input dict. Missing keys silently produce empty substitutions.

4. Agent Loop Exceeding Max Iterations

Agents may get stuck in a reasoning loop. Set max_iterations and max_execution_time on AgentExecutor to prevent runaway costs.

5. Memory Bloating Long Conversations

ConversationBufferMemory grows indefinitely. Use ConversationSummaryMemory or ConversationTokenBufferMemory to manage context window limits.

6. Retriever Returning Irrelevant Documents

If your vector store returns unrelated chunks, adjust chunk_size, chunk_overlap, or increase k and add a re-ranker step.

7. Deprecation Warnings

LangChain evolves rapidly. Pin versions in requirements.txt and migrate incrementally. The langchain-community package contains integrations that may move to separate packages.

Practice Questions

  1. What does the pipe (|) operator do in LangChain expression language?
  2. How does an agent differ from a chain?
  3. What is RAG and why is it important for LLM applications?
  4. Which memory type should you use for long conversations?
  5. How do you control how many documents a retriever returns?

Answers:

  1. It composes components — the output of one component becomes the input to the next, creating a processing pipeline similar to Unix pipes.
  2. A chain follows a fixed sequence of steps. An agent dynamically decides which tools to call based on the input, allowing flexible multi-step reasoning.
  3. RAG (Retrieval Augmented Generation) retrieves relevant documents from a knowledge base and includes them in the LLM prompt. This grounds responses in factual data and reduces hallucination.
  4. ConversationSummaryMemory or ConversationTokenBufferMemory — they summarize or truncate older messages to stay within context limits.
  5. Set search_kwargs={"k": N} on the retriever. Higher values provide more context but increase token usage and potential noise.

Challenge: DodaZIP needs a smart assistant that answers questions about compression formats. Build a RAG system that loads documentation from multiple formats (PDF, web pages, text files), chunks them, stores them in Chroma, and answers user questions with source citations.

Mini Project: Research Assistant Agent

Build an agent that researches topics using web search and knowledge base tools:

from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain.tools import tool
from langchain_core.prompts import ChatPromptTemplate
import json

@tool
def search_web(query: str) -> str:
    """Search the web for information."""
    return f"Search results for '{query}': [simulated results]"

@tool
def calculate(expression: str) -> str:
    """Evaluate a mathematical expression."""
    return str(eval(expression))

llm = ChatOpenAI(model="gpt-4", temperature=0)
tools = [search_web, calculate]
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a research assistant. Use tools to find information."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

query = "What is the current population of Python programming users worldwide? Also calculate 15% of that number."
result = executor.invoke({"input": query})
print(result["output"])

Try it: Run the agent with different research queries. Add more tools like a code interpreter or a database connector to expand its capabilities.

FAQ

What is the difference between LangChain and an LLM SDK?
An LLM SDK (like openai or anthropic) provides direct access to the model’s API. LangChain is a higher-level framework that adds chains, agents, memory, retrieval, and integrations. You can use LangChain with any LLM provider through its unified interface.
Should I use LangChain or build from scratch?
Use LangChain for rapid prototyping and standard patterns (RAG, agents, memory). Build from scratch when you need fine-grained control, minimal dependencies, or the application logic is simple enough that LangChain adds unnecessary complexity.
Does LangChain support streaming?
Yes. Use .stream() instead of .invoke() on chains and agents. LangChain’s streaming works with OpenAI and Anthropic streaming APIs, yielding tokens as they arrive from the model.
What vector stores does LangChain support?
LangChain supports Chroma (local, open-source), Pinecone (managed), Weaviate, Qdrant, Milvus, FAISS, and 30+ others. Choose Chroma for development and Pinecone or Weaviate for production at scale.
How do I handle API keys securely in LangChain?
Use environment variables. LangChain’s provider classes automatically read standard environment variables (OPENAI_API_KEY, ANTHROPIC_API_KEY). For production, use a secrets manager like AWS Secrets Manager or HashiCorp Vault.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro