How to Build an AI Agent
How to Build an AI Agent
s07

작업

계획 및 조정

Task Graph + Dependencies

207 LOC8 도구TaskManager with file-based state + dependency graph
A file-based task graph with ordering, parallelism, and dependencies -- the coordination backbone for multi-agent work

s01 > s02 > s03 > s04 > s05 > s06 | [ s07 ] s08 > s09 > s10 > s11 > s12

"Break big goals into small tasks, order them, persist to disk" -- a file-based task graph with dependencies, laying the foundation for multi-agent collaboration.

Problem

s03's TodoManager is a flat checklist in memory: no ordering, no dependencies, no status beyond done-or-not. Real goals have structure -- task B depends on task A, tasks C and D can run in parallel, task E waits for both C and D.

Without explicit relationships, the agent can't tell what's ready, what's blocked, or what can run concurrently. And because the list lives only in memory, context compression (s06) wipes it clean.

Solution

Promote the checklist into a task graph persisted to disk. Each task is a JSON file with status, dependencies (blockedBy), and dependents (blocks). The graph answers three questions at any moment:

  • What's ready? -- tasks with pending status and empty blockedBy.
  • What's blocked? -- tasks waiting on unfinished dependencies.
  • What's done? -- completed tasks, whose completion automatically unblocks dependents.
.tasks/
  task_1.json  {"id":1, "status":"completed"}
  task_2.json  {"id":2, "blockedBy":[1], "status":"pending"}
  task_3.json  {"id":3, "blockedBy":[1], "status":"pending"}
  task_4.json  {"id":4, "blockedBy":[2,3], "status":"pending"}

Task graph (DAG):
                 +----------+
            +--> | task 2   | --+
            |    | pending  |   |
+----------+     +----------+    +--> +----------+
| task 1   |                          | task 4   |
| completed| --> +----------+    +--> | blocked  |
+----------+     | task 3   | --+     +----------+
                 | pending  |
                 +----------+

Ordering:     task 1 must finish before 2 and 3
Parallelism:  tasks 2 and 3 can run at the same time
Dependencies: task 4 waits for both 2 and 3
Status:       pending -> in_progress -> completed

This task graph becomes the coordination backbone for everything after s07: background execution (s08), multi-agent teams (s09+), and worktree isolation (s12) all read from and write to this same structure.

How It Works

  1. TaskManager: one JSON file per task, CRUD with dependency graph.
class TaskManager:
    def __init__(self, tasks_dir: Path):
        self.dir = tasks_dir
        self.dir.mkdir(exist_ok=True)
        self._next_id = self._max_id() + 1

    def create(self, subject, description=""):
        task = {"id": self._next_id, "subject": subject,
                "status": "pending", "blockedBy": [],
                "blocks": [], "owner": ""}
        self._save(task)
        self._next_id += 1
        return json.dumps(task, indent=2)
  1. Dependency resolution: completing a task clears its ID from every other task's blockedBy list, automatically unblocking dependents.
def _clear_dependency(self, completed_id):
    for f in self.dir.glob("task_*.json"):
        task = json.loads(f.read_text())
        if completed_id in task.get("blockedBy", []):
            task["blockedBy"].remove(completed_id)
            self._save(task)
  1. Status + dependency wiring: update handles transitions and dependency edges.
def update(self, task_id, status=None,
           add_blocked_by=None, add_blocks=None):
    task = self._load(task_id)
    if status:
        task["status"] = status
        if status == "completed":
            self._clear_dependency(task_id)
    self._save(task)
  1. Four task tools go into the dispatch map.
TOOL_HANDLERS = {
    # ...base tools...
    "task_create": lambda **kw: TASKS.create(kw["subject"]),
    "task_update": lambda **kw: TASKS.update(kw["task_id"], kw.get("status")),
    "task_list":   lambda **kw: TASKS.list_all(),
    "task_get":    lambda **kw: TASKS.get(kw["task_id"]),
}

From s07 onward, the task graph is the default for multi-step work. s03's Todo remains for quick single-session checklists.

What Changed From s06

ComponentBefore (s06)After (s07)
Tools58 (task_create/update/list/get)
Planning modelFlat checklist (in-memory)Task graph with dependencies (on disk)
RelationshipsNoneblockedBy + blocks edges
Status trackingDone or notpending -> in_progress -> completed
PersistenceLost on compressionSurvives compression and restarts

Try It

python agents/s07_task_system.py
  1. Create 3 tasks: "Setup project", "Write code", "Write tests". Make them depend on each other in order.
  2. List all tasks and show the dependency graph
  3. Complete task 1 and then list tasks to see task 2 unblocked
  4. Create a task board for refactoring: parse -> transform -> emit -> test, where transform and emit can run in parallel after parse