Las tareas corren solas; el agent no se bloquea
«Fire and forget — the agent doesn't block while the command runs.»
El dolor de las llamadas síncronas
La herramienta bash de s02 es síncrona: subprocess.run(..., timeout=120). Si el comando tarda 90 segundos como npm install, todo el agent loop se detiene esos 90 segundos. El usuario mira la terminal sin saber si el proceso está colgado o simplemente trabajando.
La solución de s08: darle al agent una herramienta background_run. Devuelve de inmediato un task_id y el comando se ejecuta en otro hilo. El agent continúa el bucle y hace otras cosas; cuando el proceso termina, mete el resultado en una notification queue.
def run(self, command: str) -> str: task_id = str(uuid.uuid4())[:8] self.tasks[task_id] = {"status":"running", ...} thread = threading.Thread(target=self._execute, args=(task_id, command), daemon=True) thread.start() return f"Background task {task_id} started" # devuelve inmediatamente
¿Cómo vuelve el resultado al agent?
La clave es una queue thread-safe: el hilo en background hace append al terminar; el hilo principal drena la queue antes de cada llamada LLM y mete las notificaciones como mensajes de usuario.
def agent_loop(messages): while True: # Drain bg notifications before each LLM call notifs = BG.drain_notifications() if notifs: messages.append({ "role": "user", "content": f"<background-results>{notif_text}</background-results>", }) response = client.messages.create(...) ...
Así, si el agent lanza una tarea en background en el turno N y esta termina durante el turno N+3, la próxima llamada LLM incluirá automáticamente los resultados — el modelo ve el bloque <background-results> y sabe que «aquella tarea terminó, puedo continuar».
Demostración de la línea de tiempo
El widget siguiente simula el proceso: el hilo principal hace tick cada segundo (simula el ritmo del bucle); puedes lanzar tareas en background en cualquier momento. Observa cómo las dos líneas se encuentran en el «punto de drain».
¿Qué comandos vale la pena lanzar en background?
No todos los comandos deben ir al background. Dos criterios:
- Duración: los que tardan pocos segundos es más simple ejecutarlos síncronamente; el overhead de mantener la queue no compensa esperar 0,1 s.
- Dependencia inmediata del resultado: si el siguiente paso necesita ese resultado de inmediato (por ejemplo,
cat file.txtseguido de ungrep), ponerlo en background no tiene sentido — igual tienes que esperar.