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

Tâches

Planification et coordination

Task Graph + Dependencies

207 LOC8 outilsTaskManager 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

"Décomposez les grands objectifs en petites tâches, organisez-les, persistez sur disque" -- un graphe de tâches basé sur des fichiers avec dépendances, posant les fondations de la collaboration multi-agent.

Problème

Le TodoManager de s03 est une liste à plat en mémoire : pas d'ordonnancement, pas de dépendances, pas de statut au-delà de fait ou non. Les vrais objectifs ont une structure -- la tâche B dépend de la tâche A, les tâches C et D peuvent s'exécuter en parallèle, la tâche E attend à la fois C et D.

Sans relations explicites, l'agent ne peut pas dire ce qui est prêt, ce qui est bloqué, ou ce qui peut s'exécuter en concurrence. Et comme la liste vit seulement en mémoire, la compression de contexte (s06) l'efface complètement.

Solution

Promouvez la liste en un graphe de tâches persisté sur disque. Chaque tâche est un fichier JSON avec un statut, des dépendances (blockedBy) et des dépendants (blocks). Le graphe répond à trois questions à tout moment :

  • Quoi de prêt ? -- tâches avec statut pending et blockedBy vide.
  • Quoi de bloqué ? -- tâches en attente de dépendances non terminées.
  • Quoi de fait ? -- tâches completed, dont la complétion débloque automatiquement les dépendants.
.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"}

Graphe de tâches (DAG):
                 +----------+
            +--> | task 2   | --+
            |    | pending  |   |
+----------+     +----------+    +--> +----------+
| task 1   |                          | task 4   |
| completed| --> +----------+    +--> | blocked  |
+----------+     | task 3   | --+     +----------+
                 | pending  |
                 +----------+

Ordonnancement:  task 1 doit finir avant 2 et 3
Parallélisme:    tâches 2 et 3 peuvent s'exécuter en même temps
Dépendances:     task 4 attend à la fois 2 et 3
Statut:          pending -> in_progress -> completed

Ce graphe de tâches devient la colonne vertébrale de coordination pour tout ce qui suit s07 : exécution en arrière-plan (s08), équipes multi-agents (s09+), et isolation worktree (s12) lisent et écrivent tous dans cette même structure.

Comment Ça Marche

  1. TaskManager : un fichier JSON par tâche, CRUD avec graphe de dépendances.
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. Résolution de dépendances : compléter une tâche efface son ID de la liste blockedBy de chaque autre tâche, débloquant automatiquement les dépendants.
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. Statut + câblage de dépendances : update gère les transitions et les arêtes de dépendances.
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. Quatre outils de tâche vont dans la carte de distribution.
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"]),
}

À partir de s07, le graphe de tâches est le défaut pour le travail multi-étapes. Le Todo de s03 reste pour les checklists rapides d'une seule session.

Qu'est-ce qui a Changé par Rapport à s06

ComposantAvant (s06)Après (s07)
Outils58 (task_create/update/list/get)
Modèle de planificationChecklist plat (en mémoire)Graphe de tâches avec dépendances (sur disque)
RelationsNoneArêtes blockedBy + blocks
Suivi de statutFait ou nonpending -> in_progress -> completed
PersistancePerdu lors de la compressionSurvit à la compression et aux redémarrages

Essayer

python agents/s07_task_system.py
  1. Créer 3 tâches : "Setup project", "Write code", "Write tests". Les faire dépendre les unes des autres dans l'ordre.
  2. Lister toutes les tâches et montrer le graphe de dépendances
  3. Compléter la tâche 1 puis lister les tâches pour voir la tâche 2 débloquée
  4. Créer un tableau de tâches pour le refactoring : parse -> transform -> emit -> test, où transform et emit peuvent s'exécuter en parallèle après parse