04 · LangGraph & LangChain

How orchestration frameworks compose LLM calls, tool use, and data flow into reliable, stateful pipelines.


Why Orchestration Frameworks?

A raw LLM API call is just a function: prompt → completion. Complex agents require:

  • State management across multiple LLM calls
  • Conditional branching (if the agent is confused, ask for clarification)
  • Loop control (retry failed tool calls, max iteration limits)
  • Human-in-the-loop integration (pause and wait for approval)
  • Streaming and observability (trace every step)

LangChain and LangGraph are the dominant Python frameworks for this. Java alternatives include Spring AI and Semantic Kernel.


LangChain vs. LangGraph

Aspect LangChain LangGraph
Core abstraction Linear chains and pipelines Directed graphs with state
Control flow Sequential, limited branching Full graph: loops, conditionals, parallel
State Implicit, hard to inspect Explicit TypedDict state object
Human-in-the-loop Complex to add First-class via interrupt()
Observability LangSmith tracing LangSmith tracing + graph visualisation
Best for Simple RAG chains, single-shot tasks Agents, multi-step workflows, multi-agent

The Ecosystem Reality

LangGraph is built on LangChain — it uses LangChain's model integrations, tools, and document loaders. Think of LangGraph as "LangChain with a control flow engine." Most new agentic projects start with LangGraph directly.


LangGraph Core Concepts

graph LR
    A[Node: read_ticket] --> B[Node: find_service]
    B --> C[Node: read_code]
    C --> D{Conditional Edge: enough context?}
    D -->|No| C
    D -->|Yes| E[Node: generate_fix]
    E --> F[Node: write_tests]
    F --> G[Node: human_review]
    G -->|Approved| H[Node: create_pr]
    G -->|Rejected| E
Concept Description
Node A Python function that reads from and writes to the graph state
Edge A directed connection between nodes
Conditional Edge A function that decides which node to route to next
State A typed dictionary shared across all nodes in the graph
Interrupt Pause execution and wait for external input (human approval)
Checkpointer Persists graph state to a store for long-running or resumable workflows

Deep Dive: LangGraph — Node patterns, state design, tool integration
Deep Dive: State Machines & Workflows — Complex flow control, parallel branches


The State Object

All data flows through a single state object. Every node receives the full state and returns a partial update.

class AgentState(TypedDict):
    jira_ticket: dict
    service_name: str
    relevant_files: List[str]
    code_diff: str
    tests_added: List[str]
    review_status: str  # "pending" | "approved" | "rejected"
    pr_url: str
    messages: List[BaseMessage]  # LLM conversation history

This design makes the entire agent state inspectable, serialisable, and resumable.


Spring AI — Java-Native Alternative

For teams building Spring Boot backends who want agent logic in Java:

Feature Spring AI
LLM clients OpenAI, Anthropic, Ollama, Azure OpenAI
RAG support VectorStore abstraction, Advisors API
Tool calling @Tool annotated methods
Structured output BeanOutputConverter for mapping to Java objects
Memory ChatMemory with in-memory or JDBC backends

Spring AI vs. LangGraph

Spring AI is excellent for embedding AI into existing Spring Boot services. LangGraph (Python) is better for complex multi-agent orchestration. A common pattern: Spring Boot service exposes a REST endpoint that the Python LangGraph agent calls as a tool.


Observability with LangSmith

LangSmith is the tracing and evaluation platform for LangChain/LangGraph. Every run produces:

  • Full trace of every LLM call with inputs/outputs
  • Token counts and latency per step
  • Tool call inputs and results
  • Graph visualisation of which nodes executed

This is essential for debugging agent loops and detecting prompt regressions.