Skip to content

LangChain — Building LLM Applications

LangChain is an open-source framework for building applications powered by large language models. It provides composable building blocks — chains, prompts, memory, tools, and agents — so you can build reliable, production-ready LLM applications without reinventing the same plumbing every time.

LangChain is available in Python and JavaScript/TypeScript, and integrates with all major LLM providers (OpenAI, Anthropic, Google, Mistral, Ollama, and more).

Terminal window
pip install langchain langchain-openai
# or
npm install langchain @langchain/openai

The foundation — a wrapper around any LLM provider:

from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
llm = ChatOpenAI(model="gpt-4o")
claude = ChatAnthropic(model="claude-sonnet-4-6")
response = llm.invoke("Explain dependency injection in one sentence.")
print(response.content)

Reusable, parameterised prompts:

from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
("system", "You are a {role}. Answer concisely."),
("human", "{question}")
])
# Format the prompt
messages = prompt.format_messages(
role="senior software architect",
question="What is the difference between CQRS and Event Sourcing?"
)

LangChain Expression Language (LCEL) chains components together with |:

from langchain_core.output_parsers import StrOutputParser
chain = prompt | llm | StrOutputParser()
result = chain.invoke({
"role": "senior software architect",
"question": "What is the difference between CQRS and Event Sourcing?"
})
print(result)

Chains are lazy — they build a computation graph and execute when you call .invoke(), .stream(), or .batch().

Persisting conversation history:

from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_community.chat_message_histories import ChatMessageHistory
store = {}
def get_session_history(session_id: str) -> BaseChatMessageHistory:
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant."),
("placeholder", "{chat_history}"),
("human", "{input}"),
])
chain = prompt | llm | StrOutputParser()
with_history = RunnableWithMessageHistory(
chain,
get_session_history,
input_messages_key="input",
history_messages_key="chat_history",
)
with_history.invoke(
{"input": "My name is Banky."},
config={"configurable": {"session_id": "user-1"}}
)
with_history.invoke(
{"input": "What is my name?"}, # AI will remember "Banky"
config={"configurable": {"session_id": "user-1"}}
)

Tools are functions the LLM can call to take actions or look up information:

from langchain_core.tools import tool
@tool
def get_stock_price(ticker: str) -> str:
"""Get the current stock price for a ticker symbol."""
# In production, call a real stock API
return f"{ticker}: $142.50"
@tool
def search_docs(query: str) -> str:
"""Search the internal knowledge base for relevant documents."""
# In production, call your vector store or search API
return f"Found 3 documents matching: {query}"

The classic Reasoning + Acting agent loop:

from langchain.agents import create_react_agent, AgentExecutor
from langchain import hub
tools = [get_stock_price, search_docs]
# Pull a standard ReAct prompt from LangChain Hub
prompt = hub.pull("hwchase17/react")
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({
"input": "What is the current price of AAPL? Check the docs for our investment policy first."
})

The agent loop:

Thought: I need to check the investment policy first
Action: search_docs("investment policy")
Observation: Found 3 documents...
Thought: Now I need the stock price
Action: get_stock_price("AAPL")
Observation: AAPL: $142.50
Thought: I have everything I need
Final Answer: The current price of AAPL is $142.50. Per the investment policy...

The most common LangChain use case — answering questions from your own documents:

from langchain_community.document_loaders import WebBaseLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_core.runnables import RunnablePassthrough
# 1. Load documents
loader = WebBaseLoader("https://docs.yourcompany.com/api-guide")
docs = loader.load()
# 2. Split into chunks
splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = splitter.split_documents(docs)
# 3. Embed and store
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_documents(chunks, embeddings)
retriever = vectorstore.as_retriever()
# 4. Build RAG chain
rag_prompt = ChatPromptTemplate.from_template("""
Answer the question based on the context below. If you don't know, say so.
Context: {context}
Question: {question}
""")
rag_chain = (
{"context": retriever, "question": RunnablePassthrough()}
| rag_prompt
| llm
| StrOutputParser()
)
result = rag_chain.invoke("How do I authenticate with the API?")

LangChain supports streaming responses for better UX:

for chunk in chain.stream({"role": "architect", "question": "Explain microservices"}):
print(chunk, end="", flush=True)

LangSmith is LangChain’s companion platform for tracing, debugging, and evaluating LLM applications:

import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your_langsmith_key"
os.environ["LANGCHAIN_PROJECT"] = "my-app"
# Now every chain/agent invocation is automatically traced
result = chain.invoke({"question": "..."})

Every invocation shows: input, output, token usage, latency, and the full execution trace — invaluable for debugging complex agent loops.


Good fit:

  • Building RAG applications over your own documents
  • Orchestrating multi-step LLM workflows
  • Switching between LLM providers without rewriting code
  • Rapid prototyping of agent-based features

Consider alternatives:

  • Simple single-prompt calls — use the provider SDK directly (OpenAI, Anthropic) — no framework needed
  • Complex multi-agent graphs — consider LangGraph (built on top of LangChain)
  • High-performance production systems — LangChain adds overhead; raw SDK may be faster

See also: LangGraph for stateful, graph-based multi-agent orchestration.