AI Stack Lab — LangGraph, LangChain & the AI Ecosystem

Two posters, rebuilt as a clickable lab · every panel, table cell and diagram opens a detailed explanation with runnable code
This is the poster rebuilt as live HTML. Click any panel or diagram to open a detailed explanation: what it does, why it is built that way, working code you can paste, how to run it locally and on AWS, and the failure modes to watch for.

LANGGRAPH — VISUAL TUTORIAL

Build stateful, multi-actor AI agents as graphs
What is LangGraph?

LangGraph is a library for building stateful, multi-actor applications with LLMs using graphs.

  • Explicit control flow
  • Cycles and conditional logic
  • Durable execution & persistence
  • Human-in-the-loop
  • Streaming & observability
Details →
Key concepts
GraphA set of nodes (steps) connected by edges.
StateShared data passed across nodes (TypedDict / Pydantic).
NodeA function or LLM call that reads and updates state.
Conditional edgeRoute based on state or node output.
EdgeThe flow of control from one node to another.
CheckpointPersist state for durability, resume, time-travel.
Details →
When to use LangGraph
  • Complex workflows with branches and loops
  • Multi-agent or multi-role systems
  • Long-running, durable conversations
  • Human approval steps
  • Fine-grained control and observability
Details →
How LangGraph works
START Node A (LLM / Tool) Condition? YES Node B (Tool / LLM) NO Node C (LLM) END Details →
State example
{ "messages": [...], "user_profile": {...}, "docs": [...], "results": {}, "next_action": "" }
Details →
LangGraph — code walkthrough (Python)
from typing import TypedDict, List, Any
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langchain.tools import tool

# 1) Define state
class AgentState(TypedDict):
    messages: List[Any]
    docs: List[str]
    answer: str
    next_action: str

# 2) Define tools
@tool
def search_docs(query: str) -> list[str]:
    """Search your vector store or docs."""
    return [f"Doc about {query} - 1",
            f"Doc about {query} - 2"]

# 3) Nodes
llm = ChatOpenAI(model="gpt-4o", temperature=0)

def planner(state: AgentState) -> AgentState:
    user_msg = state["messages"][-1].content
    if "search" in user_msg.lower():
        state["next_action"] = "search"
    else:
        state["next_action"] = "answer"
    return state
def do_search(state: AgentState) -> AgentState:
    query = state["messages"][-1].content
    docs = search_docs.invoke({"query": query})
    state["docs"] = docs
    state["next_action"] = "answer"
    return state

def generate_answer(state: AgentState) -> AgentState:
    docs = "\n".join(state.get("docs", []))
    prompt = (
      "Use the following docs to answer the user.\n"
      f"Docs:\n{docs}\n\n"
      "Question: " + state["messages"][-1].content)
    resp = llm.invoke([HumanMessage(content=prompt)])
    state["answer"] = resp.content
    return state

# 4) Build graph
graph = StateGraph(AgentState)

graph.add_node("planner", planner)
graph.add_node("search",  do_search)
graph.add_node("answer",  generate_answer)

graph.set_entry_point("planner")

def route(state: AgentState) -> str:
    return state["next_action"]

graph.add_conditional_edges("planner", route,
    {"search": "search", "answer": "answer"})
graph.add_edge("search", "answer")
graph.add_edge("answer", END)
app = graph.compile()
Full walkthrough →
Sample run
Input: "Search LangGraph and explain"
  1. planner → next_action = "search"
  2. search_docs → docs added
  3. answer → LLM generates final answer
  4. END
Details →
Visual graph (compiled)
START planner search search answer answer Details →
Durability & checkpoints
State saved Process restarts Resume from checkpoint Details →
LangGraph features
Cycles & loops
Human-in-the-loop
Streaming
Persistence
Time travel
Subgraphs
Details →
Best practices
  • Keep state small and serializable
  • Use TypedDict / Pydantic for state
  • Make nodes idempotent
  • Add guards & timeouts
  • Log and visualize graphs
Details →

LANGCHAIN — VISUAL TUTORIAL

Build LLM apps by chaining components (prompts, models, tools, memory, retrievers)
What is LangChain?

LangChain is a framework for building LLM applications by composing together components.

  • Prompts, LLMs, tools, retrievers
  • Memory & chat history
  • Chains, agents & RAG pipelines
  • Integrations & extensibility
Details →
Core components
Chat modelsThe LLM endpoint.
Prompts & templatesReusable, parameterized instructions.
ToolsAPIs and functions the model can call.
RetrieversVector stores and search over your data.
MemoryChat history carried across turns.
Output parsersStructured, validated output.
Details →
When to use LangChain
  • Quick to build LLM apps
  • RAG, agents, tool use
  • Lots of integrations
  • Less control-flow complexity (use LangGraph when needed)
  • Large ecosystem
Details →
LangChain architecture (typical app)
Memory Chain / Agent Prompt Template LLM Output Parser User Input Output User Tools Details →
RAG variant
User question Retriever / Vectorstore Vector DB Documents Details →
LangChain — code walkthrough (Python)
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.memory import ConversationBufferMemory
from langchain.agents import create_openai_tools_agent, AgentExecutor
from langchain.tools import tool

# 1) LLM
llm = ChatOpenAI(model="gpt-4o", temperature=0)

# 2) Tools
@tool
def get_weather(location: str) -> str:
    """Get current weather for a location."""
    return f"Sunny, 28C in {location}"

@tool
def search_web(query: str) -> str:
    """Search the web and return a short summary."""
    return f"Top result for {query}: ..."

tools = [get_weather, search_web]
# 3) Prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a helpful assistant. "
               "Use tools when needed."),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

# 4) Agent + executor
agent = create_openai_tools_agent(llm, tools, prompt)

memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True,
)

executor = AgentExecutor(
    agent=agent,
    tools=tools,
    memory=memory,
    verbose=True,
)

# 5) Run
response = executor.invoke(
    {"input": "What is the weather in Boston?"})
print(response["output"])
Full walkthrough →
LangChain app flow (tools + memory + RAG)
User Question Prompt + history (to LLM) LLM Call tool? YES Tool (API / function) Tool result NO Final answer Output parser Answer Retriever (RAG) Relevant docs Details →
Red team with PyRIT (example)
1. Define target(LLM app)
2. Define goals(what to break)
3. Select attacks(PyRIT)
4. Run tests(batch / CI)
5. Analyzeresults
6. Fix & hardeniterate
Details →
Defend against attacks
Prevent
  • Input validation
  • Policy & guardrails
  • Least-privilege tools
  • Content filtering
  • Secrets & prompt hygiene
Detect
  • Anomaly detection
  • Prompt / response scanning
  • Toxicity, jailbreak, PII
  • Model monitoring
  • Audit logs
Respond
  • Alerting & SOC
  • Block / rate limit
  • Escalation workflows
  • User feedback loop
  • Rollback / hotfix
Improve
  • Red team regularly
  • Eval datasets
  • Regression tests
  • Update policies
  • Continuous learning
Details →
Key takeaway

Use LangChain for rapid composition of LLM apps. Use LangGraph for complex, stateful, controllable workflows. Use PyRIT and promptfoo to red-team and continuously harden your AI applications.

Details →
Educational material. Code samples are minimal by design — add authentication, guardrails, cost limits, and evaluation before anything reaches production.