The workflow
A pile of specialists is not a workflow. LangGraph turns them into a compiled graph with a typed state object, named nodes, and explicit edges between them. This is where orchestration stops being a buzzword and becomes code.
The sequential CV graph
Each agent is a node. Each edge is a transition. State flows from entry to END.
from typing import TypedDict, Optional, Dict, Any, List
class CVAnalysisState(TypedDict):
"""Shared memory for every agent in the graph."""
cv_content: str
job_description: Optional[str]
job_analysis: Dict[str, Any]
analysis_results: Dict[str, Any]
strengths: List[str]
weaknesses: List[str]
improvement_suggestions: List[str]
score: int
keyword_match_score: int
experience_relevance: int
skills_alignment: int
format_score: int
score_rationale: Dict[str, str]
ats_analysis: Dict[str, Any]
error: Optional[str]Every agent reads from and writes to this object. TypedDict keeps the contract explicit so a typo in one agent does not silently break the next one.
from langgraph.graph import StateGraph, END
def _build_workflow(self):
workflow = StateGraph(CVAnalysisState)
# Nodes: each agent is registered under a name
workflow.add_node("extract_content", self.content_extractor.extract_content)
workflow.add_node("analyze_jd", self.jd_analyzer.analyze_jd)
workflow.add_node("analyze_strengths", self.strengths_analyzer.analyze_strengths)
workflow.add_node("analyze_weaknesses", self.weaknesses_analyzer.analyze_weaknesses)
workflow.add_node("generate_suggestions", self.improvement_suggester.generate_suggestions)
workflow.add_node("score_cv", self.scorer.score_cv)
workflow.add_node("analyze_ats", self.ats_analyzer.analyze_ats)
# Entry point and edges
workflow.set_entry_point("extract_content")
workflow.add_edge("extract_content", "analyze_jd")
workflow.add_edge("analyze_jd", "analyze_strengths")
workflow.add_edge("analyze_strengths", "analyze_weaknesses")
workflow.add_edge("analyze_weaknesses", "generate_suggestions")
workflow.add_edge("generate_suggestions", "score_cv")
workflow.add_edge("score_cv", "analyze_ats")
workflow.add_edge("analyze_ats", END)
return workflow.compile()Compile once, invoke many times. The compiled graph manages state propagation, error surfacing, and execution order for free.
You can. It works for three agents. It stops working when you need conditional routing, parallel branches, retries on specific nodes, or streaming progress per node. LangGraph is not magic. It is a structure that makes those needs trivial to add later.
Quiz: Quiz
Loading practice…
Checkpoint: Halfway checkpoint
Loading practice…