Task Dependency Patterns
CC 2.1.16 Task Management patterns with TaskCreate, TaskUpdate, TaskGet, TaskList tools. Decompose complex work into trackable tasks with dependency chains. Use when managing multi-step implementations, coordinating parallel work, or tracking completion status.
Primary Agent: workflow-architect
Task Dependency Patterns
Overview
Claude Code 2.1.16 introduces a native Task Management System with four tools:
- TaskCreate: Create new tasks with subject, description, and activeForm
- TaskUpdate: Update status (pending → in_progress → completed), set dependencies
- TaskGet: Retrieve full task details including blockers
- TaskList: View all tasks with status and dependency summary
Tasks enable structured work tracking, parallel coordination, and clear progress visibility.
When to Use
- Breaking down complex multi-step implementations
- Coordinating parallel work across multiple files
- Tracking progress on large features
- Managing dependencies between related changes
- Providing visibility into work status
Key Patterns
1. Task Decomposition
Break complex work into atomic, trackable units:
Feature: Add user authentication
Tasks:
#1. [pending] Create User model
#2. [pending] Add auth endpoints (blockedBy: #1)
#3. [pending] Implement JWT tokens (blockedBy: #2)
#4. [pending] Add auth middleware (blockedBy: #3)
#5. [pending] Write integration tests (blockedBy: #4)2. Dependency Chains
Use addBlockedBy to create execution order:
// Task #3 cannot start until #1 and #2 complete
{"taskId": "3", "addBlockedBy": ["1", "2"]}3. Status Workflow
pending → in_progress → completed
↓ ↓
(unblocked) (active)
pending/in_progress → deleted (CC 2.1.20)- pending: Task created but not started
- in_progress: Actively being worked on
- completed: Work finished and verified
- deleted: Task removed (CC 2.1.20) - permanently removes the task
Task Deletion (CC 2.1.20)
CC 2.1.20 adds status: "deleted" to permanently remove tasks:
// Delete a task
{"taskId": "3", "status": "deleted"}When to delete:
- Orphaned tasks whose blockers have all failed
- Tasks superseded by a different approach
- Duplicate tasks created in error
- Tasks from a cancelled pipeline
When NOT to delete:
- Tasks that might be retried later (keep as pending)
- Tasks with useful history (mark completed instead)
- Tasks blocked by in_progress work (wait for resolution)
4. activeForm Pattern
Provide present-continuous form for spinner display:
| subject (imperative) | activeForm (continuous) |
|---|---|
| Run tests | Running tests |
| Update schema | Updating schema |
| Fix authentication | Fixing authentication |
Agent Teams (CC 2.1.33+)
CC 2.1.33 introduces Agent Teams for multi-agent coordination with shared task lists and peer-to-peer messaging.
Team Workflow
1. TeamCreate("my-feature") → Creates team + shared task list
2. TaskCreate(subject, description) → Add tasks to shared list
3. Task(prompt, team_name, name) → Spawn teammates
4. TaskUpdate(owner: "teammate-name") → Assign tasks
5. SendMessage(type: "message") → Direct teammate communication
6. SendMessage(type: "shutdown_request") → Graceful shutdownWhen to Use Teams vs Task Tool
| Criteria | Task Tool (subagents) | Agent Teams |
|---|---|---|
| Independent tasks | Yes | Overkill |
| Cross-cutting changes | Limited | Yes |
| Agents need to talk | No (star topology) | Yes (mesh) |
| Cost sensitivity | Lower (~1x) | Higher (~2.5x) |
| Complexity < 3.0 | Yes | No |
| Complexity > 3.5 | Possible | Recommended |
Team Task Patterns
# Spawn teammate into shared task list
Task(
prompt="You are the backend architect...",
team_name="my-feature",
name="backend-architect",
subagent_type="backend-system-architect"
)
# Teammate claims and works tasks
TaskList → find unblocked, unowned tasks
TaskUpdate(taskId, owner: "backend-architect", status: "in_progress")
# ... do work ...
TaskUpdate(taskId, status: "completed")
TaskList → find next taskPeer Messaging
# Direct message between teammates
SendMessage(type: "message", recipient: "frontend-dev",
content: "API contract ready: GET /users/:id returns {...}",
summary: "API contract shared")
# Broadcast to all (use sparingly)
SendMessage(type: "broadcast",
content: "Breaking change: auth header format changed",
summary: "Breaking auth change")Anti-Patterns
- Creating tasks for trivial single-step work
- Circular dependencies (A blocks B, B blocks A)
- Leaving tasks in_progress when blocked
- Not marking tasks completed after finishing
- Using broadcast for messages that only concern one teammate
- Spawning teams for simple sequential work (use Task tool instead)
Related Skills
ork:implement- Implementation workflow with task tracking and progress updatesork:verify- Verification tasks and completion checklistsork:fix-issue- Issue resolution with hypothesis-based RCA trackingork:brainstorming- Design exploration with parallel agent tasks
References
Rules (3)
Coordinate agent task ownership to prevent duplicated work and orphaned tasks — HIGH
Tasks: Agent Coordination
In multi-agent workflows, every in-progress task must have a clear owner, and agents must coordinate through the task list and messaging tools. Without ownership, two agents may silently work on the same task, causing merge conflicts and wasted effort.
Incorrect:
// Two agents both start the same task without claiming ownership
// Agent-A:
TaskUpdate(taskId: "5", status: "in_progress") // No owner set
// Agent-B (simultaneously):
TaskUpdate(taskId: "5", status: "in_progress") // No owner set
// Both agents now work on #5 — duplicate effort, likely merge conflictCorrect:
// Agent-A claims the task atomically with owner field
TaskList // Review available tasks
// Found #5: pending, no owner, blockedBy: []
TaskUpdate(taskId: "5", status: "in_progress", owner: "agent-a")
// Agent-B sees #5 is owned
TaskList // #5 shows owner: "agent-a", in_progress
// Agent-B picks a different unblocked, unowned task instead
TaskUpdate(taskId: "6", status: "in_progress", owner: "agent-b")Incorrect:
// Agent completes work silently — no one knows the output or context
TaskUpdate(taskId: "5", status: "completed")
// Downstream agent starts #7 (blocked by #5) with no context about what was doneCorrect:
// Agent communicates completion context to dependent agent
TaskUpdate(taskId: "5", status: "completed")
SendMessage(
type: "message",
recipient: "frontend-dev",
content: "Task #5 done: API returns { users: User[], total: number }. Schema in src/types/user.ts.",
summary: "API contract ready for frontend"
)
// Downstream agent has full context to start dependent workKey rules:
- Always set
ownerwhen transitioning a task toin_progress— this prevents duplicate work - Use
TaskListto find unblocked, unowned tasks before claiming one - Design tasks to be completable by a single agent — avoid tasks that require two agents to collaborate mid-execution
- Use
SendMessageto share completion context (output formats, file locations, decisions made) with agents who own dependent tasks - Mark tasks
completedpromptly after finishing — delayed completion blocks dependent agents unnecessarily - Release ownership (
owner: "") if you cannot finish a task, reverting it topendingso another agent can pick it up
Reference: Multi-Agent Coordination — Best Practices (lines 110-116), Agent Workflow (lines 47-70)
Verify task completion criteria before marking done to prevent cascading dependency failures — HIGH
Tasks: Completion Criteria
A task must only be marked completed when all implementation is done, tests pass, and nothing blocks dependent tasks from proceeding safely. Premature completion cascades errors: downstream agents start work assuming a solid foundation that does not exist.
Incorrect:
// Marking complete when tests are failing
// Agent implements feature but 2 of 8 tests fail
TaskUpdate(taskId: "3", status: "completed") // BAD: tests not passing
// Dependent task #4 starts, builds on broken code — compounds the failureCorrect:
// Verify all criteria before marking complete
// 1. Implementation done — all code changes committed
// 2. Tests passing — ran test suite, all green
// 3. No blockers for dependents — output matches expected interface
// 4. Documentation updated (if applicable)
TaskUpdate(taskId: "3", status: "completed") // GOOD: fully verified
TaskList // Check if #4 is now unblocked and readyIncorrect:
// Leaving a task in_progress when blocked by a discovered issue
// Agent hits unexpected blocker mid-work
// Task sits as in_progress indefinitely — no one else can pick it up
// Other agents wait for dependent tasks that will never unblockCorrect:
// Revert to pending and create a blocker task for the discovered issue
TaskUpdate(taskId: "3", status: "pending") // Revert — not abandonable as in_progress
TaskCreate(
subject: "Fix database connection pooling",
description: "Discovered during #3: pool exhaustion under load. Must fix before #3 can proceed.",
activeForm: "Fixing connection pooling"
)
// New task #7 created
TaskUpdate(taskId: "3", addBlockedBy: ["7"]) // #3 now properly blockedIncorrect:
// Skipping in_progress — going directly from pending to completed
TaskUpdate(taskId: "1", status: "completed") // BAD: skipped in_progress
// No visibility that work was happening; no activeForm spinner shownCorrect:
// Always transition through in_progress for visibility
TaskUpdate(taskId: "1", status: "in_progress", activeForm: "Creating user model")
// ... do work, verify results ...
TaskUpdate(taskId: "1", status: "completed")Key rules:
- Verify all four completion criteria before marking done: implementation complete, tests passing, no blockers for dependents, documentation updated if applicable
- Never skip
in_progress— always transitionpendingtoin_progresstocompletedfor proper visibility - If blocked mid-work, revert to
pendingand create a new blocker task withaddBlockedBylinking - When partial work is done but scope remains, create follow-up tasks for the remaining items rather than leaving one large task incomplete
- After completing a task, run
TaskListto identify newly unblocked dependents
Reference: Status Workflow — Completion Criteria (lines 71-78), Anti-Patterns (lines 80-105)
Validate task dependencies before starting to avoid wasted work on blocked tasks — HIGH
Tasks: Dependency Validation
Always validate that a task's dependencies are fully resolved before transitioning it to in_progress. Skipping validation leads to wasted effort, incorrect assumptions about system state, and potential circular dependency deadlocks.
Incorrect:
// Starting a task without checking if blockers are resolved
TaskList // shows #3 has blockedBy: ["1", "2"]
// Task #1 is completed but #2 is still in_progress
TaskUpdate(taskId: "3", status: "in_progress") // BAD: #2 not done yet
// Agent now works against incomplete prerequisite stateCorrect:
// Always verify blockedBy is empty before starting work
TaskGet(taskId: "3")
// Returns: blockedBy: ["1", "2"], status: "pending"
// Check: #1 = completed, #2 = completed? No — #2 still in_progress
// Result: Do NOT start #3. Pick a different unblocked task instead.
// Later, when #2 completes:
TaskGet(taskId: "3")
// Returns: blockedBy: [] (all resolved), status: "pending"
TaskUpdate(taskId: "3", status: "in_progress", owner: "my-agent") // GOODIncorrect:
// Creating circular dependencies
TaskUpdate(taskId: "2", addBlockedBy: ["3"])
TaskUpdate(taskId: "3", addBlockedBy: ["2"])
// Deadlock: neither task can ever startCorrect:
// Keep dependency chains acyclic — review the full chain before adding
// If #2 depends on #3 output, restructure:
TaskCreate(subject: "Extract shared interface", ...) // New task #6
TaskUpdate(taskId: "2", addBlockedBy: ["6"])
TaskUpdate(taskId: "3", addBlockedBy: ["6"])
// Both #2 and #3 depend on #6, no cycleKey rules:
- Call
TaskGetand verifyblockedByis empty before setting any task toin_progress - Never add a dependency that creates a cycle (A blocks B blocks A); restructure with a shared prerequisite task instead
- Keep dependency chains shallow (3-4 levels max) to avoid long critical paths
- When completing a task, call
TaskListto check if dependent tasks are now unblocked - Document why each dependency exists in the task description so future agents understand the ordering
Reference: Dependency Tracking — Validation Rules (lines 72-77), Best Practices (lines 89-94)
References (3)
Dependency Tracking
Dependency Tracking
Overview
Task dependencies ensure correct execution order through blocks and blockedBy relationships.
Dependency Fields
| Field | Description |
|---|---|
blocks | Tasks that cannot start until this task completes |
blockedBy | Tasks that must complete before this task can start |
Creating Dependencies
// During task update
{
"taskId": "3",
"addBlockedBy": ["1", "2"],
"addBlocks": ["4", "5"]
}Dependency Patterns
Sequential Chain
#1 → #2 → #3 → #4// Task #2 blocked by #1
{"taskId": "2", "addBlockedBy": ["1"]}
// Task #3 blocked by #2
{"taskId": "3", "addBlockedBy": ["2"]}Fan-Out Pattern
┌→ #2
#1 ──┼→ #3
└→ #4All depend on #1, but can run in parallel after #1 completes.
Fan-In Pattern
#1 ──┐
#2 ──┼→ #4
#3 ──┘{"taskId": "4", "addBlockedBy": ["1", "2", "3"]}Diamond Pattern
#1
↙ ↘
#2 #3
↘ ↙
#4Validation Rules
- No circular dependencies: A → B → A is invalid
- Blocked tasks cannot start: Check
blockedBybefore settingin_progress - Completing unblocks dependents: When #1 completes, #2 becomes available
Querying Dependencies
# List tasks to see blockedBy summary
TaskList
# Get full dependency details
TaskGet taskId="3"
# Returns: blockedBy: ["1", "2"], blocks: ["4"]Best Practices
- Keep dependency chains shallow (3-4 levels max)
- Use fan-out for parallelizable work
- Document why dependencies exist in task description
- Review blocked tasks when completing work
Multi Agent Coordination
Multi-Agent Task Coordination
Overview
When multiple Claude Code instances or agents work on a shared codebase, the Task system provides coordination primitives.
Coordination Patterns
Task Assignment
Use owner field to track which agent owns a task:
// Claim a task
{"taskId": "3", "owner": "backend-agent"}
// Release task
{"taskId": "3", "owner": ""}Finding Available Work
# Pseudo-code for agent task selection
tasks = TaskList()
available = [t for t in tasks
if t.status == "pending"
and not t.owner
and not t.blockedBy]
next_task = available[0] if available else NoneWork Distribution
┌─────────────────────────────────────────┐
│ Task Board │
├──────────────┬──────────────┬───────────┤
│ pending │ in_progress │ completed │
├──────────────┼──────────────┼───────────┤
│ #4 (blocked) │ #2 (agent-A) │ #1 │
│ #5 (ready) │ #3 (agent-B) │ │
│ #6 (ready) │ │ │
└──────────────┴──────────────┴───────────┘Agent Workflow
1. Check for Work
// Agent startup: list all tasks
TaskList2. Claim Task
// Found unblocked, unowned task
{"taskId": "5", "status": "in_progress", "owner": "my-agent"}3. Complete Work
// After finishing work
{"taskId": "5", "status": "completed"}
// Check for newly unblocked tasks
TaskListHandoff Patterns
Sequential Handoff
Agent-A completes #1 → Agent-B unblocked for #2Parallel Fork
Agent-A completes #1
├→ Agent-B can start #2
├→ Agent-C can start #3
└→ Agent-D can start #4Merge Point
Agent-A completes #2 ─┐
Agent-B completes #3 ─┼→ Any agent can start #5
Agent-C completes #4 ─┘Best Practices
- Atomic task design: Tasks should be completable by single agent
- Clear ownership: Always set owner when starting work
- Timely completion: Mark completed as soon as work is done
- Dependency awareness: Check blockedBy before starting
- Communication via tasks: Use description for context handoff
Integration with OrchestKit
The task system integrates with:
- context-compression: Task context in compressed summaries
- agent handoff hooks: Auto-document in decision log
Status Workflow
Status Workflow
Overview
Tasks progress through a defined state machine: pending → in_progress → completed.
Status States
pending
- Task created but not started
- May be blocked by other tasks
- Available for claiming if no blockers
in_progress
- Actively being worked on
- Only one task should typically be in_progress per worker
- Mark immediately when starting work
completed
- Work finished and verified
- Unblocks dependent tasks
- Cannot be modified further
deleted (CC 2.1.20)
- Task permanently removed
- Use for orphaned, superseded, or duplicate tasks
- Cannot be recovered after deletion
State Transitions
┌─────────┐ start ┌─────────────┐ finish ┌───────────┐
│ pending │ ────────────→ │ in_progress │ ───────────→ │ completed │
└─────────┘ └─────────────┘ └───────────┘
↑ │ │ │
│ └───────────────────────│──│──→ ┌─────────┐
└───── revert ─────────────┘ └──→ │ deleted │ (CC 2.1.20)
(if blocked) └─────────┘Valid Transitions
| From | To | When |
|---|---|---|
| pending | in_progress | Starting work, no blockers |
| in_progress | completed | Work verified complete |
| in_progress | pending | Discovered blocker, need to wait |
| pending | deleted | Orphaned, superseded, or duplicate (CC 2.1.20) |
| in_progress | deleted | Cancelled or superseded (CC 2.1.20) |
Status Update Examples
// Start work
{"taskId": "1", "status": "in_progress"}
// Mark complete
{"taskId": "1", "status": "completed"}
// Revert if blocked
{"taskId": "1", "status": "pending"}
// Delete orphaned task (CC 2.1.20)
{"taskId": "1", "status": "deleted"}Completion Criteria
Before marking completed, verify:
- Implementation done: All code changes complete
- Tests passing: Related tests succeed
- No blockers: Nothing prevents dependent tasks
- Documentation updated: If applicable
Anti-Patterns
Premature Completion
// DON'T: Mark complete with failing tests
{"taskId": "1", "status": "completed"}Abandoned in_progress
// DON'T: Leave task in_progress when blocked
// DO: Revert to pending, create blocker task
{"taskId": "1", "status": "pending"}Skipping States
// DON'T: Go directly from pending to completed
// DO: Always transition through in_progress
{"taskId": "1", "status": "in_progress"}
// ... do work ...
{"taskId": "1", "status": "completed"}activeForm Display
The activeForm field displays during in_progress status:
[#1 in_progress] Running tests... ⣾Provide meaningful present-continuous descriptions:
- "Creating database schema"
- "Updating API endpoints"
- "Writing integration tests"
Checklists (2)
Dependency Checklist
Dependency Validation Checklist
Before Adding Dependencies
- Is there a true execution order requirement?
- Would parallel execution cause conflicts?
- Is the dependency on task completion (not just start)?
Dependency Types
Code Dependencies
- Task B modifies files created by Task A
- Task B imports modules defined in Task A
- Task B extends patterns established in Task A
Schema Dependencies
- Task B uses database schema from Task A
- Task B consumes API contracts from Task A
- Task B references types defined in Task A
Test Dependencies
- Task B tests functionality from Task A
- Task B requires fixtures from Task A
- Task B extends test suites from Task A
Dependency Anti-Patterns
Circular Dependencies
Task A blockedBy [B]
Task B blockedBy [A]Fix: Identify shared prerequisite, extract to Task C
Over-Specification
Task D blockedBy [A, B, C]
# But really only needs CFix: Remove unnecessary dependencies, rely on transitive blocking
Under-Specification
Task B has no blockedBy
# But actually needs Task A's outputFix: Add explicit dependency to prevent race conditions
Validation Steps
1. Trace Dependency Chain
For each task with blockedBy:
- Can the blocking task(s) actually complete?
- Is there a path from START to this task?
- Is there a path from this task to END?2. Check for Cycles
For each task T:
visited = {}
queue = [T.blockedBy]
while queue:
current = queue.pop()
if current == T: ERROR: Cycle detected
if current in visited: continue
visited.add(current)
queue.extend(current.blockedBy)3. Verify Parallelism
Tasks without mutual dependencies CAN run in parallel.
Verify: No shared file writes, no ordering requirement.Updating Dependencies
When modifying existing dependencies:
- Reviewed impact on blocked tasks
- No orphaned tasks (tasks that can never unblock)
- Critical path still reasonable
- Notified other agents/workers if relevant
Documentation
For complex dependency chains:
- Diagram in task description or PR
- Rationale for non-obvious dependencies
- Expected execution order documented
Task Design Checklist
Task Design Checklist
Before Creating Tasks
- Is this work complex enough to need task tracking? (3+ steps)
- Have you identified the natural work boundaries?
- Can each task be completed independently once unblocked?
Task Structure
Subject (required)
- Uses imperative form ("Add", "Fix", "Update", not "Adding", "Fixed")
- Describes the outcome, not the process
- Concise but descriptive (5-10 words max)
Good examples:
- "Create User model with validation"
- "Add JWT authentication endpoint"
- "Fix pagination in search results"
Bad examples:
- "Work on the feature" (too vague)
- "Adding stuff to the database" (wrong tense, vague)
- "Implement the new user authentication system with JWT tokens and refresh token rotation including rate limiting" (too long)
Description (required)
- Explains what needs to be done
- Includes acceptance criteria
- Notes any constraints or considerations
- References relevant files or patterns
Template:
Implement [specific thing] that:
- [Requirement 1]
- [Requirement 2]
Acceptance criteria:
- [ ] Tests pass
- [ ] Documentation updated
- [ ] No type errorsactiveForm (recommended)
- Uses present continuous tense
- Matches the subject semantically
- Reads naturally as spinner text
| Subject | activeForm |
|---|---|
| Add user validation | Adding user validation |
| Fix broken tests | Fixing broken tests |
| Update API schema | Updating API schema |
Dependency Design
- Dependencies represent real execution order requirements
- No circular dependency chains
- Parallel work identified and unblocked appropriately
- Critical path minimized
Task Granularity
Too Large
Signs your task is too large:
- Description exceeds 200 words
- Estimated to touch 5+ files
- Multiple distinct outcomes combined
Split strategy:
- Identify sub-outcomes
- Create task per outcome
- Link with dependencies
Too Small
Signs your task is too small:
- Single line change
- Pure refactoring without behavior change
- Part of another task's natural work
Merge strategy:
- Combine with related task
- Add to description as sub-item
Review Before Submitting
- Each task has clear completion criteria
- Dependencies are minimal but sufficient
- Task can be understood without external context
- activeForm provides useful progress feedback
Skill Evolution
Analyzes skill usage patterns and suggests improvements. Use when reviewing skill performance, applying auto-suggested changes, or rolling back versions.
Testing Patterns
Comprehensive testing patterns for unit, integration, E2E, pytest, API mocking (MSW/VCR), test data, property/contract testing, performance, LLM, and accessibility testing. Use when writing tests, setting up test infrastructure, or validating application quality.
Last updated on