s11
Agentes Autonomos
ColaboracaoScan Board, Claim Tasks
499 LOC14 ferramentasTask board polling + timeout-based self-governance
Teammates scan the board and claim tasks themselves; no need for the lead to assign each one
s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > [ s11 ] s12
"Companheiros verificam o quadro e reivindicam tarefas eles mesmos" -- não há necessidade do lead atribuir cada um.
Problema
No s09-s10, companheiros só trabalham quando explicitamente dito. O lead deve fazer spawn de cada um com um prompt específico. 10 tarefas não reclamadas no quadro? O lead atribui cada uma manualmente. Não escala.
Autonomia real: companheiros verificam o quadro de tarefas eles mesmos, reclamam tarefas não reclamadas, trabalham nelas, então procuram mais.
Uma sutileza: após compressão de contexto (s06), o agente pode esquecer quem ele é. Re-injeção de identidade corrige isso.
Solução
Ciclo de vida do companheiro com ciclo idle:
+-------+
| spawn |
+---+---+
|
v
+-------+ tool_use +-------+
| WORK | <------------- | LLM |
+-------+ +-------+
|
| stop_reason != tool_use (or idle tool called)
v
+--------+
| IDLE | poll every 5s for up to 60s
+---+----+
|
+---> check inbox --> message? ----------> WORK
|
+---> scan .tasks/ --> unclaimed? -------> claim -> WORK
|
+---> 60s timeout ----------------------> SHUTDOWN
Identity re-injection after compression:
if len(messages) <= 3:
messages.insert(0, identity_block)
Como Funciona
- O loop do companheiro tem duas fases: WORK e IDLE. Quando o LLM para de chamar ferramentas (ou chama
idle), o companheiro entra em IDLE.
def _loop(self, name, role, prompt):
while True:
# -- WORK PHASE --
messages = [{"role": "user", "content": prompt}]
for _ in range(50):
response = client.messages.create(...)
if response.stop_reason != "tool_use":
break
# execute tools...
if idle_requested:
break
# -- IDLE PHASE --
self._set_status(name, "idle")
resume = self._idle_poll(name, messages)
if not resume:
self._set_status(name, "shutdown")
return
self._set_status(name, "working")
- A fase idle faz poll da caixa de entrada e quadro de tarefas em loop.
def _idle_poll(self, name, messages):
for _ in range(IDLE_TIMEOUT // POLL_INTERVAL): # 60s / 5s = 12
time.sleep(POLL_INTERVAL)
inbox = BUS.read_inbox(name)
if inbox:
messages.append({"role": "user",
"content": f"<inbox>{inbox}</inbox>"})
return True
unclaimed = scan_unclaimed_tasks()
if unclaimed:
claim_task(unclaimed[0]["id"], name)
messages.append({"role": "user",
"content": f"<auto-claimed>Task #{unclaimed['id']}: "
f"{unclaimed[0]['subject']}</auto-claimed>"})
return True
return False # timeout -> shutdown
- Verificação do quadro de tarefas: encontrar tarefas pending, sem dono, não bloqueadas.
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
- Re-injeção de identidade: quando o contexto é muito curto (compressão aconteceu), insira um bloco de identidade.
if len(messages) <= 3:
messages.insert(0, {"role": "user",
"content": f"<identity>You are '{name}', role: {role}, "
f"team: {team_name}. Continue your work.</identity>"})
messages.insert(1, {"role": "assistant",
"content": f"I am {name}. Continuing."})
O Que Mudou Desde s10
| Componente | Antes (s10) | Depois (s11) |
|---|---|---|
| Ferramentas | 12 | 14 (+idle, +claim_task) |
| Autonomia | Direcionado pelo lead | Auto-organizado |
| Fase idle | Nenhum | Poll inbox + quadro de tarefas |
| Reivindicação de tarefas | Apenas manual | Auto-reivindicar tarefas não reclamadas |
| Identidade | Prompt do sistema | + re-injeção após compressão |
| Timeout | Nenhum | 60s idle -> auto shutdown |
Experimente
python agents/s11_autonomous_agents.py
Crie 3 tarefas no quadro, então spawn alice e bob. Observe-os auto-reivindicar.Spawn um companheiro coder e deixe ele encontrar trabalho do quadro de tarefasCrie tarefas com dependências. Observe companheiros respeitarem a ordem bloqueada.- Digite
/taskspara ver o quadro de tarefas com donos - Digite
/teampara monitorar quem está trabalhando vs idle
