L'agent qui trouve lui-même du travail
« L'agent trouve lui-même du travail. » Pas besoin d'affectation humaine — il prend des tickets depuis le tableau de bord.
De « réveillé par un autre » à « qui se cherche du travail »
Les teammates de s09 / s10 sont passifs : quelqu'un doit leur envoyer un message pour qu'ils démarrent ; une fois la tâche finie, ils retournent en idle, attendant d'être rappelés.
Le teammate autonome de s11 est actif : même sans activité, il ne s'arrête pas vraiment — il scanne .tasks/ toutes les 5 secondes. S'il voit une tâche sans propriétaire, il appelle claim_task et commence à travailler.
Lifecycle d'un teammate :
+-------+
| spawn |
+---+---+
|
v
+-------+
| WORK | <-- boucle LLM tool_use
+---+---+
|
| stop_reason != tool_use OU tool_use("idle")
v
+-------+
| IDLE | poll toutes les 5s, 12 fois max = 60s timeout
+---+---+
|
+--> inbox avec nouveaux messages ? → reprendre WORK
|
+--> scan .tasks/, trouve une tâche non réclamée → claim → reprendre WORK
|
+--> 60s sans rien → status = shutdown, thread se termine
Auto-claim · « prendre un ticket » sur le tableau
La fonction centrale :
def scan_unclaimed_tasks() -> list: unclaimed = [] for f in sorted(TASKS_DIR.glob("task_*.json")): task = json.loads(f.read_text()) if (task.get("status") == "pending" and not task.get("owner") and not task.get("blockedBy")): unclaimed.append(task) return unclaimed
Trois filtres = pending + sans owner + sans blockedBy. Les trois sont nécessaires.
Le claim lui-même est protégé par un verrou (_claim_lock) pour éviter que deux agents voient simultanément la même tâche libre et tentent de la prendre — sous le verrou, on relit l'état, on vérifie que owner est encore vide, puis on écrit « in_progress » + owner sur disque.
Simulation de plusieurs agents scannant simultanément le tableau
3 teammates en idle, 3 tâches en attente. Cliquez sur « Prochain scan » pour voir qui s'empare de quelle tâche en premier.
Réinjection d'identity · après compression, l'agent se souvient-il de lui ?
s06 nous a montré qu'auto_compact remplace messages[] par un résumé. Un agent autonome qui tourne plusieurs heures peut facilement déclencher ce mécanisme — après compression, le modèle ne sait plus comment il s'appelle ni quel rôle il joue.
La technique de s11 : quand une nouvelle tâche est réclamée et que len(messages) ≤ 3 (signe qu'une compression vient d'avoir lieu), un bloc d'identity est automatiquement inséré au début :
if len(messages) <= 3: messages.insert(0, { "role": "user", "content": f"<identity>You are 'alice', role: coder, team: my-team. Continue your work.</identity>", }) messages.insert(1, {"role":"assistant", "content": f"I am alice. Continuing."})
Ce pattern s'appelle identity reinjection — on construit artificiellement un tour de dialogue pour « dire au modèle qui il est » et lui redonner le sens de son rôle.