Task Graph & Dependencies
Learn how Claude Code coordinates multiple tasks with dependency edges, enabling complex workflows.
What You’ll Learn
In Session 3, you learned how TodoWrite creates flat task lists. But real projects aren’t flat — tasks depend on each other. You can’t write integration tests before the API exists, and you can’t deploy before the tests pass.
By the end of this session, you’ll understand:
- How tasks form a Directed Acyclic Graph (DAG) with dependency edges
- How Claude Code resolves which tasks can run in parallel vs. sequentially
- The graph traversal algorithm for executing tasks in the right order
- How to structure prompts that produce well-formed dependency graphs
The Problem
A flat task list looks like this:
□ Create database migration
□ Add API routes
□ Create auth middleware
□ Write integration tests
□ Update the frontend
The AI works through these sequentially, top to bottom. But this misses critical information:
- Wasted sequentiality — “Create database migration” and “Add API routes” could run in parallel, but a flat list forces them to be sequential
- Incorrect ordering — Nothing prevents “Write integration tests” from running before the API routes exist
- Cascading failures — If “Create auth middleware” fails, the AI doesn’t know which downstream tasks are now blocked
These problems multiply as task lists grow. A 15-task implementation plan with hidden dependencies is a recipe for backtracking and wasted context.
How It Works
Tasks as a DAG
When Claude Code plans complex work, tasks naturally form a Directed Acyclic Graph. Each task is a node, and dependency relationships are edges:
┌──────────────┐
│ Analyze │
│ Requirements│
└──────┬───────┘
│
┌────────┴────────┐
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ DB Migration │ │ Route Handlers│
│ (users table) │ │ (auth routes) │
└────────┬───────┘ └────────┬───────┘
│ │
└────────┬──────────┘
│
▼
┌────────────────┐
│ Auth │
│ Middleware │
└────────┬───────┘
│
┌────────┴────────┐
│ │
▼ ▼
┌────────────────┐ ┌────────────────┐
│ Integration │ │ Update │
│ Tests │ │ Frontend │
└────────────────┘ └────────────────┘
In this graph:
- DB Migration and Route Handlers are independent — they can run in parallel
- Auth Middleware depends on both — it can’t start until both are complete
- Integration Tests and Update Frontend depend on Auth Middleware but not on each other
Dependency Edges
Each task carries two relationship fields:
Task: "Auth Middleware"
status: pending
blockedBy: ["DB Migration", "Route Handlers"]
blocks: ["Integration Tests", "Update Frontend"]
These edges encode the full graph:
| Field | Meaning |
|---|---|
blockedBy | Tasks that must complete before this one can start |
blocks | Tasks that cannot start until this one completes |
The blockedBy / blocks relationship is symmetric — if Task A blocks Task B, then Task B is blocked by Task A.
Graph Traversal Algorithm
Claude Code traverses the task graph with a simple but effective algorithm:
REPEAT:
1. Scan all tasks
2. Find tasks where:
- status = "pending"
- ALL blockedBy tasks have status = "completed"
3. These are "ready" tasks -- execute them
(If multiple tasks are ready, run in parallel)
4. Mark completed tasks
5. Check: did completing these unlock new tasks?
6. If no tasks remain, DONE
Here’s the algorithm visualized across time:
Time ──────────────────────────────────────────────►
Round 1: [Analyze Requirements]
status: pending → in_progress → completed
Round 2: [DB Migration]────────┐ (parallel)
[Route Handlers]──────┘
Round 3: [Auth Middleware]
(unlocked because both blockers completed)
Round 4: [Integration Tests]───┐ (parallel)
[Update Frontend]─────┘
DONE ✓
Four rounds instead of six sequential steps. The graph reveals that two rounds can run tasks in parallel, cutting total execution time.
How the AI Builds the Graph
When you ask Claude Code for a complex feature, it analyzes the natural dependencies between subtasks. The planning phase looks like this:
User: "Add authentication to the Express app"
AI internal reasoning:
"I need to break this down. Let me think about what
depends on what..."
1. Analyze requirements → nothing depends on, everything starts here
2. DB migration (users table) → needs requirements analysis
3. Route handlers (login/signup) → needs requirements analysis
4. Auth middleware (JWT validation) → needs both DB and routes
5. Tests → needs middleware
6. Frontend login page → needs middleware
TodoWrite output:
Task 1: Analyze requirements blockedBy: []
Task 2: Create users table migration blockedBy: [1]
Task 3: Create auth route handlers blockedBy: [1]
Task 4: Implement auth middleware blockedBy: [2, 3]
Task 5: Write integration tests blockedBy: [4]
Task 6: Update frontend with login blockedBy: [4]
The key is that Tasks 2 and 3 share the same blocker (Task 1) but don’t block each other. The AI recognizes they’re independent and can run concurrently.
Parallel Execution with Subagents
When multiple tasks become ready simultaneously, Claude Code can delegate them to parallel subagents:
Round 2 — Two tasks ready:
Parent Agent
│
├──► Subagent A: "Create users table migration"
│ └── Works in isolated context
│
└──► Subagent B: "Create auth route handlers"
└── Works in isolated context
Both return results → Parent continues to Round 3
This combines two concepts from the course: the task graph identifies parallelizable work, and subagents (Session 4) provide the isolated contexts to execute them.
Key Insight
Task graphs let the AI do more work per turn by identifying parallelizable subtasks. Without a graph, the AI processes tasks one-by-one in a linear sequence. With a graph, it can batch independent tasks and execute them concurrently.
But the deeper insight is about correctness, not just speed. A flat task list has no way to express “don’t start this until that finishes.” The dependency graph makes ordering constraints explicit, preventing the AI from writing tests against code that doesn’t exist yet, or integrating a middleware before its dependencies are ready.
Think of it like a build system. make doesn’t compile files randomly — it reads the dependency graph, builds leaves first, and works its way up. Claude Code’s task graph works the same way. And just like make -j4 can parallelize independent compilation units, Claude Code can parallelize independent tasks.
Hands-On Example
Structuring Prompts for Good Dependency Graphs
You can guide Claude Code to produce well-structured task graphs by being explicit about the relationships in your prompt:
Add a notification system to the app. Break it into tasks
with clear dependencies:
Phase 1 (no dependencies):
- Design the notification data model
- Research WebSocket libraries
Phase 2 (depends on Phase 1):
- Create notifications table migration
- Set up WebSocket server
Phase 3 (depends on Phase 2):
- Build notification API endpoints
- Implement real-time push via WebSocket
Phase 4 (depends on Phase 3):
- Create frontend notification component
- Write end-to-end tests
Use TodoWrite with blockedBy edges. Run parallel tasks
where possible.
Recognizing Dependency Patterns
Common dependency patterns you’ll encounter:
Linear Chain: Fan-Out: Fan-In:
A → B → C A → B D ←─ A
A → C D ←─ B
A → D D ←─ C
Diamond: Independent:
A A B C
/ \ (no edges)
B C
\ /
D
The diamond pattern is the most common in real projects. One analysis task fans out to parallel implementation tasks, which converge on an integration task.
Handling Failures in the Graph
When a task fails, its downstream dependents are blocked:
Before failure:
✓ Analyze requirements
→ DB Migration (in progress)
→ Route Handlers (in progress)
□ Auth Middleware (blocked by 2, 3)
DB Migration fails:
✓ Analyze requirements
✗ DB Migration (FAILED)
✓ Route Handlers
⊘ Auth Middleware (BLOCKED — dependency failed)
Recovery:
The AI diagnoses the failure, fixes the migration,
re-runs it, and then Auth Middleware becomes unblocked.
The graph makes the blast radius of a failure visible. Without it, the AI might try to proceed with Auth Middleware and encounter cryptic errors because the database table doesn’t exist.
Reading the Graph at a Glance
During execution, the task list becomes a live dashboard:
Task Graph Status:
✓ [1] Analyze requirements
✓ [2] Create users table migration
✓ [3] Create auth route handlers
→ [4] Implement auth middleware (blockedBy: 2✓, 3✓)
□ [5] Write integration tests (blockedBy: 4)
□ [6] Update frontend with login (blockedBy: 4)
Progress: 3/6 tasks completed | 1 in progress | 2 blocked
Next parallel batch: [5, 6] when [4] completes
What Changed
| Flat Task List | Task Graph with Dependencies |
|---|---|
| Sequential execution only | Parallel execution of independent tasks |
| No ordering guarantees | Explicit dependency edges prevent wrong order |
| Failure blocks everything | Failure blocks only downstream dependents |
| No progress visibility beyond current task | Full graph shows what’s done, running, and waiting |
| AI must remember ordering in context | Dependencies encoded in data, survive compaction |
| One task at a time | Multiple subagents on independent tasks |
Next Session
Session 8 covers Background Tasks — how Claude Code launches long-running operations (builds, test suites, deployments) in the background and continues productive work while waiting for results.