---
title: "Task Dependency Patterns"
description: "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."
---

<span className="badge badge-gray">Reference</span> <span className="badge badge-yellow">medium</span>

> **Auto-activated** — this skill loads automatically when Claude detects matching context.

<ContextualSkillSidebar slug="task-dependency-patterns" />


# 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:

```json
// 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
```

- **pending**: Task created but not started
- **in_progress**: Actively being worked on
- **completed**: Work finished and verified
- **deleted**: Task removed — permanently removes the task

### Task Deletion

Use `status: "deleted"` to permanently remove tasks:

```json
// 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

Agent Teams provides 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. Agent(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 shutdown
```

### When 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 &lt; 3.0 | Yes | No |
| Complexity > 3.5 | Possible | Recommended |

### Team Task Patterns

```
# Spawn teammate into shared task list
Agent(
  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 task
```

### Peer 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")
```

## Context Exhaustion Handling

When using Agent Teams, if context limit is reached mid-workflow:
- Collect partial results from completed teammates via `TaskList`
- Synthesize available outputs — prefer partial results over silent failure
- Log skipped tasks with `TaskUpdate(status: "cancelled", note: "context limit")`

## 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 updates
- `ork:verify` - Verification tasks and completion checklists
- `ork:fix-issue` - Issue resolution with hypothesis-based RCA tracking
- `ork:brainstorm` - Design exploration with parallel agent tasks

## References

Load on demand with `Read("$\{CLAUDE_SKILL_DIR\}/references/&lt;file&gt;")`:

| File | Content |
|------|---------|
| `dependency-tracking.md` | Dependency tracking patterns |
| `status-workflow.md` | Status workflow details |
| `multi-agent-coordination.md` | Multi-agent coordination |


---

## 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:**
```json
// 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 conflict
```

**Correct:**
```json
// 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:**
```json
// 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 done
```

**Correct:**
```json
// 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 work
```

**Key rules:**
- Always set `owner` when transitioning a task to `in_progress` — this prevents duplicate work
- Use `TaskList` to 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 `SendMessage` to share completion context (output formats, file locations, decisions made) with agents who own dependent tasks
- Mark tasks `completed` promptly after finishing — delayed completion blocks dependent agents unnecessarily
- Release ownership (`owner: ""`) if you cannot finish a task, reverting it to `pending` so another agent can pick it up

Reference: [Multi-Agent Coordination](../references/multi-agent-coordination.md) — 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:**
```json
// 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 failure
```

**Correct:**
```json
// 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 ready
```

**Incorrect:**
```json
// 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 unblock
```

**Correct:**
```json
// 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 blocked
```

**Incorrect:**
```json
// 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 shown
```

**Correct:**
```json
// 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 transition `pending` to `in_progress` to `completed` for proper visibility
- If blocked mid-work, revert to `pending` and create a new blocker task with `addBlockedBy` linking
- 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 `TaskList` to identify newly unblocked dependents

Reference: [Status Workflow](../references/status-workflow.md) — 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:**
```json
// 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 state
```

**Correct:**
```json
// 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")  // GOOD
```

**Incorrect:**
```json
// Creating circular dependencies
TaskUpdate(taskId: "2", addBlockedBy: ["3"])
TaskUpdate(taskId: "3", addBlockedBy: ["2"])
// Deadlock: neither task can ever start
```

**Correct:**
```json
// 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 cycle
```

**Key rules:**
- Call `TaskGet` and verify `blockedBy` is empty before setting any task to `in_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 `TaskList` to 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](../references/dependency-tracking.md) — 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

```json
// During task update
{
  "taskId": "3",
  "addBlockedBy": ["1", "2"],
  "addBlocks": ["4", "5"]
}
```

## Dependency Patterns

### Sequential Chain

```
#1 → #2 → #3 → #4
```

```json
// Task #2 blocked by #1
{"taskId": "2", "addBlockedBy": ["1"]}
// Task #3 blocked by #2
{"taskId": "3", "addBlockedBy": ["2"]}
```

### Fan-Out Pattern

```
     ┌→ #2
#1 ──┼→ #3
     └→ #4
```

All depend on #1, but can run in parallel after #1 completes.

### Fan-In Pattern

```
#1 ──┐
#2 ──┼→ #4
#3 ──┘
```

```json
{"taskId": "4", "addBlockedBy": ["1", "2", "3"]}
```

### Diamond Pattern

```
     #1
    ↙  ↘
  #2    #3
    ↘  ↙
     #4
```

## Validation Rules

1. **No circular dependencies**: A → B → A is invalid
2. **Blocked tasks cannot start**: Check `blockedBy` before setting `in_progress`
3. **Completing unblocks dependents**: When #1 completes, #2 becomes available

## Querying Dependencies

```bash
# 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:

```json
// Claim a task
{"taskId": "3", "owner": "backend-agent"}

// Release task
{"taskId": "3", "owner": ""}
```

### Finding Available Work

```python
# 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 None
```

### Work 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

```json
// Agent startup: list all tasks
TaskList
```

### 2. Claim Task

```json
// Found unblocked, unowned task
{"taskId": "5", "status": "in_progress", "owner": "my-agent"}
```

### 3. Complete Work

```json
// After finishing work
{"taskId": "5", "status": "completed"}
// Check for newly unblocked tasks
TaskList
```

## Handoff Patterns

### Sequential Handoff

```
Agent-A completes #1 → Agent-B unblocked for #2
```

### Parallel Fork

```
Agent-A completes #1
├→ Agent-B can start #2
├→ Agent-C can start #3
└→ Agent-D can start #4
```

### Merge Point

```
Agent-A completes #2 ─┐
Agent-B completes #3 ─┼→ Any agent can start #5
Agent-C completes #4 ─┘
```

## Best Practices

1. **Atomic task design**: Tasks should be completable by single agent
2. **Clear ownership**: Always set owner when starting work
3. **Timely completion**: Mark completed as soon as work is done
4. **Dependency awareness**: Check blockedBy before starting
5. **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

```json
// 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:

1. **Implementation done**: All code changes complete
2. **Tests passing**: Related tests succeed
3. **No blockers**: Nothing prevents dependent tasks
4. **Documentation updated**: If applicable

## Anti-Patterns

### Premature Completion

```json
// DON'T: Mark complete with failing tests
{"taskId": "1", "status": "completed"}
```

### Abandoned in_progress

```json
// DON'T: Leave task in_progress when blocked
// DO: Revert to pending, create blocker task
{"taskId": "1", "status": "pending"}
```

### Skipping States

```json
// 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 C
```

**Fix:** Remove unnecessary dependencies, rely on transitive blocking

### Under-Specification

```
Task B has no blockedBy
# But actually needs Task A's output
```

**Fix:** 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 errors
```

### activeForm (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:**
1. Identify sub-outcomes
2. Create task per outcome
3. 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:**
1. Combine with related task
2. 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

