AI Engineering Curriculum
Phase 2: Single AI Agent Development·6 min read

Module 2.5

The LangChain Ecosystem

What is LangChain?

LangChain is an open-source framework for building applications powered by language models. It gives you a standard set of building blocks — models, prompts, tools, chains, agents, retrievers — that work the same way regardless of which LLM provider you're using underneath.

Think of it as the plumbing layer. You still write the logic. LangChain handles the wiring between your code and the models, databases, and APIs it needs to talk to.

It's not a replacement for the Anthropic SDK. It's an abstraction on top of it — and every other SDK. When you use LangChain, you're writing to one interface that works with Claude, GPT-4o, Gemini, Llama, and dozens of others.


Real-World Use Cases

Before diving into how LangChain works, it helps to see what people actually build with it. These are concrete production examples — not hypotheticals.

Customer support agents. A company connects LangChain to their product documentation, past support tickets, and FAQ database. When a user asks a question, the agent retrieves the relevant docs and drafts an answer. If it can't find an answer with high confidence, it escalates to a human. Companies like Klarna and Boston Consulting Group run this pattern at scale.

Internal knowledge bases. An employee asks "What's our policy on contractor NDAs?" in plain English. LangChain retrieves the relevant HR policy chunks, generates a clear answer, and cites the source document. No more digging through Confluence or SharePoint. This is one of the most common enterprise deployments.

Research and report generation. An analyst asks for a competitive analysis on three companies. LangChain searches the web, pulls financial data, summarizes each source, and produces a structured report with citations — in minutes instead of hours. Cisco Outshift used a similar setup to take CI/CD pipeline setup from a week to under an hour.

RAG over codebases. A developer asks "How does the authentication module work?" LangChain searches the codebase semantically, finds the relevant files and functions, and explains how they connect — without the developer having to know where to look first.

Document processing pipelines. Load 500 PDFs, extract structured data from each (dates, names, amounts, clauses), and write results to a database. LangChain handles the document loading, chunking, extraction, and output in a repeatable pipeline.

The pattern across all of these: LangChain is the glue that connects a language model to external data sources and tools, and packages the agent loop so you don't have to rebuild it each time.


Why LangChain Exists

When you used the Anthropic SDK in Module 2.1, you wrote code that only talks to Claude. If you ever wanted to swap to GPT-4o or Gemini — different company, different SDK, different response format — you'd rewrite significant chunks of your code.

LangChain solves this by sitting in between your code and every LLM provider. It provides a single, standardized interface that works the same way regardless of which model is underneath. Swap Claude for GPT-4o by changing one string.

The key mental model: LangChain is a toolkit. The Anthropic SDK is a screwdriver for one specific brand of screw. LangChain is a multi-tool that works with any brand.


The Three-Layer Ecosystem

LangChain is the component library and high-level agent abstraction — chat models, tools, document loaders, retrievers, and create_agent(). What you reach for to build something quickly.

LangGraph is the orchestration engine underneath LangChain agents. When you need precise control over agent flow — branching, loops, human approval, persistent state — you use LangGraph directly. Covered in Module 2.6.

LangSmith is the observability platform. It records every LLM call, every tool invocation, every intermediate step — and lets you see it all visually. You can't debug complex agents without it.

LangChain builds the car. LangGraph designs the road system. LangSmith puts a camera on every corner.


The Standard Model Interface

Python
from langchain.chat_models import init_chat_model model = init_chat_model("claude-opus-4-6") # Same methods on every model, every provider response = model.invoke("What is an embedding?") for chunk in model.stream("Explain RAG step by step"): print(chunk.text, end="", flush=True) responses = model.batch(["Question 1", "Question 2", "Question 3"])

To switch from Claude to GPT-4o: change one string. Your code doesn't change at all.

Structured output works the same way across providers:

Python
from pydantic import BaseModel, Field class ResearchSummary(BaseModel): topic: str = Field(description="The topic researched") key_findings: list[str] = Field(description="Top 3-5 findings") confidence: float = Field(description="Confidence score 0-1") structured_model = model.with_structured_output(ResearchSummary) result = structured_model.invoke("Summarize what you know about RAG") # Returns: ResearchSummary(topic="RAG", key_findings=[...], confidence=0.9)

LCEL — The Pipe Operator

LCEL (LangChain Expression Language) is how you compose components together. The | operator chains Runnables — and everything in LangChain is a Runnable.

Python
from langchain_core.prompts import PromptTemplate from langchain_core.output_parsers import StrOutputParser chain = PromptTemplate.from_template("Explain {topic} in one sentence.") | model | StrOutputParser() result = chain.invoke({"topic": "vector embeddings"})

Every chain automatically supports all invocation methods — .invoke(), .stream(), .batch(), .ainvoke() — for free.

RunnableParallel runs multiple branches simultaneously:

Python
from langchain_core.runnables import RunnableParallel, RunnablePassthrough retrieval = RunnableParallel({ "context": retriever, # fetch relevant docs "question": RunnablePassthrough() # pass question unchanged }) rag_chain = retrieval | prompt | model | StrOutputParser()

RunnableLambda wraps any Python function as a chain step:

Python
from langchain_core.runnables import RunnableLambda chain = prompt | model | StrOutputParser() | RunnableLambda(lambda t: t.strip().lower())

Gotcha: streaming only works end-to-end if every step in the chain supports streaming. One non-streaming step breaks streaming for the whole chain.


Tools

Python
from langchain.tools import tool @tool def search_docs(query: str, max_results: int = 5) -> str: """Search the internal knowledge base for relevant documents. Use when the user asks about company policies, product specs, or procedures.""" return results

For complex inputs with validation:

Python
from pydantic import BaseModel, Field from typing import Literal class SearchInput(BaseModel): query: str = Field(description="Search query string") domain: Literal["docs", "code", "issues"] = Field(default="docs") @tool(args_schema=SearchInput) def advanced_search(query: str, domain: str = "docs") -> str: """Search with domain filtering.""" return results

ToolRuntime — hidden parameter giving tools access to agent state (never shown to the model):

Python
from langchain.tools import tool, ToolRuntime @tool def get_user_preferences(runtime: ToolRuntime) -> str: """Get the current user's saved preferences.""" return str(runtime.state.get("user_preferences", {}))

runtime and config are reserved parameter names — using them for anything else silently breaks tool execution.


Agents with create_agent()

The whole ReAct loop in under 10 lines:

Python
from langchain.agents import create_agent agent = create_agent( model="claude-opus-4-6", tools=[search_docs, get_weather], system_prompt="You are a helpful assistant. Be concise and cite your sources." ) result = agent.invoke({ "messages": [{"role": "user", "content": "What's the weather in Tokyo?"}] })

Middleware — intercept agent behavior without touching core logic:

Python
from langchain.agents.middleware import wrap_model_call, ModelRequest @wrap_model_call def smart_routing(request: ModelRequest, handler): # Cheap model for early turns, powerful model when conversation gets complex if len(request.state["messages"]) > 10: return handler(request.override(model=powerful_model)) return handler(request.override(model=cheap_model)) agent = create_agent(model=cheap_model, tools=tools, middleware=[smart_routing])

Streaming:

Python
for chunk in agent.stream( {"messages": [{"role": "user", "content": "Research the latest on RAG"}]}, stream_mode="values" ): msg = chunk["messages"][-1] if msg.content: print(f"Agent: {msg.content}") elif hasattr(msg, "tool_calls") and msg.tool_calls: print(f"→ Calling: {[tc['name'] for tc in msg.tool_calls]}")

LangSmith — Observability from Day One

Setup is 3 environment variables:

Bash
export LANGSMITH_TRACING=true export LANGSMITH_API_KEY="lsv2_..." export LANGSMITH_PROJECT="my-project"

Every LangChain and LangGraph run is now automatically traced — no code changes. In the UI you see the full execution tree: every LLM call with inputs/outputs, every tool call, latency per step, token counts, cost.

For code outside LangChain:

Python
from langsmith import traceable @traceable def my_rag_pipeline(question: str) -> str: docs = retrieve(question) return generate_answer(question, docs)

Why from day one: agent failures are almost impossible to diagnose without a trace. A trace turns "the agent gave a wrong answer" into "the retriever returned irrelevant chunks on turn 3." You can't fix what you can't see.

Note: the older LANGCHAIN_TRACING_V2=true still works but is deprecated. Use LANGSMITH_TRACING=true.


Where Things Go Wrong

Version fragmentation. LangChain 0.x → 1.x had breaking API changes. All python.langchain.com URLs now redirect to docs.langchain.com. Old tutorials may not work. Pin your version in production.

Pre-bound models break structured output. Don't call .bind_tools() on a model you're passing to create_agent() with response_format= — they're incompatible.

Tool names with spaces. Provider APIs reject non-snake_case tool names. Always use underscores.

Custom agent state must be TypedDict. As of LangChain 1.0, Pydantic models and dataclasses are not supported for agent state schemas.


Sources