LangChain — Building LLM Applications
What is LangChain?
Section titled “What is LangChain?”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).
pip install langchain langchain-openai# ornpm install langchain @langchain/openaiCore Concepts
Section titled “Core Concepts”LLMs and Chat Models
Section titled “LLMs and Chat Models”The foundation — a wrapper around any LLM provider:
from langchain_openai import ChatOpenAIfrom 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)Prompt Templates
Section titled “Prompt Templates”Reusable, parameterised prompts:
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([ ("system", "You are a {role}. Answer concisely."), ("human", "{question}")])
# Format the promptmessages = prompt.format_messages( role="senior software architect", question="What is the difference between CQRS and Event Sourcing?")Chains — The LCEL Pipe Syntax
Section titled “Chains — The LCEL Pipe Syntax”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().
Memory
Section titled “Memory”Persisting conversation history:
from langchain_core.chat_history import BaseChatMessageHistoryfrom langchain_core.runnables.history import RunnableWithMessageHistoryfrom 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 and Agents
Section titled “Tools and Agents”Defining Tools
Section titled “Defining Tools”Tools are functions the LLM can call to take actions or look up information:
from langchain_core.tools import tool
@tooldef 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"
@tooldef 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}"ReAct Agent
Section titled “ReAct Agent”The classic Reasoning + Acting agent loop:
from langchain.agents import create_react_agent, AgentExecutorfrom langchain import hub
tools = [get_stock_price, search_docs]
# Pull a standard ReAct prompt from LangChain Hubprompt = 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 firstAction: search_docs("investment policy")Observation: Found 3 documents...Thought: Now I need the stock priceAction: get_stock_price("AAPL")Observation: AAPL: $142.50Thought: I have everything I needFinal Answer: The current price of AAPL is $142.50. Per the investment policy...RAG — Retrieval Augmented Generation
Section titled “RAG — Retrieval Augmented Generation”The most common LangChain use case — answering questions from your own documents:
from langchain_community.document_loaders import WebBaseLoaderfrom langchain_text_splitters import RecursiveCharacterTextSplitterfrom langchain_openai import OpenAIEmbeddingsfrom langchain_community.vectorstores import FAISSfrom langchain_core.runnables import RunnablePassthrough
# 1. Load documentsloader = WebBaseLoader("https://docs.yourcompany.com/api-guide")docs = loader.load()
# 2. Split into chunkssplitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)chunks = splitter.split_documents(docs)
# 3. Embed and storeembeddings = OpenAIEmbeddings()vectorstore = FAISS.from_documents(chunks, embeddings)retriever = vectorstore.as_retriever()
# 4. Build RAG chainrag_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?")Streaming
Section titled “Streaming”LangChain supports streaming responses for better UX:
for chunk in chain.stream({"role": "architect", "question": "Explain microservices"}): print(chunk, end="", flush=True)LangSmith — Observability
Section titled “LangSmith — Observability”LangSmith is LangChain’s companion platform for tracing, debugging, and evaluating LLM applications:
import osos.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 tracedresult = chain.invoke({"question": "..."})Every invocation shows: input, output, token usage, latency, and the full execution trace — invaluable for debugging complex agent loops.
When to Use LangChain
Section titled “When to Use LangChain”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.