Lección 08 · concurrente

Deje que el agente se ejecute solo sin bloquearlo.

「Fire and forget — the agent doesn't block while the command runs.」

⏱ ~10 min · 📝 3 widgets interactivos · 🧑‍💻 Basado en shareAI-lab · s08_background_tasks.py

El dolor de bloquear llamadas

La herramienta bash en S02 es sincrónica: subprocess.run(..., timeout=120). Ejecutar un comando como npm install tarda 90 segundos y todo el ciclo del agente se bloquea durante 90 segundos. El usuario mira fijamente el terminal sin saber si está colgado o funcionando.

Solución para s08: proporcione al agente una herramienta background_run. Inmediatamente devuelve un task_id y el comando se ejecuta en otro hilo. El agente continúa haciendo bucles y haciendo otras cosas; cuando se completa la tarea bg, los resultados se agregan a la cola de notificaciones.

def ejecutar(self, comando: str) -> cadena:
    task_id = cadena(uuid.uuid4())[:8]
    self.tasks[task_id] = {"status":"running", ...}
    thread = threading.Thread(target=self._execute, args=(task_id, comando), daemon=True)
    hilo.start()
    return f"Tarea en segundo plano {task_id} iniciada" # Regresar inmediatamente

¿Cómo devolver el resultado al agente?

La clave es una cola segura para subprocesos: cuando el subproceso bg se completa, se agrega a la cola; antes de cada llamada de LLM por parte del hilo principal, la cola se vacía y la notificación de finalización se incluye en mensajes como mensajes de usuario.

def agent_loop(mensajes):
    mientras Verdadero:
        # Drenar notificaciones de bg antes de cada llamada de LLM
        notifs = BG.drain_notificaciones()
        si notifica:
            mensajes.append({
                "rol": "usuario",
                "content": f"<background-results>{notif_text}</background-results>",
            })
        respuesta = cliente.mensajes.create(...)
        ...

De esta manera, el agente genera una tarea básica en la enésima ronda. Cuando se completa la tarea en la ronda N+3, la siguiente llamada de LLM traerá automáticamente los resultados; el modelo sabrá cuando vea el bloque <background-results>: "Oh, esa tarea ha terminado, continuaré".

Demostración de la línea de tiempo

El siguiente widget le permite simular: el hilo principal marca cada segundo (simulando el ritmo del ciclo del agente); puedes generar la tarea bg en cualquier momento. Observe cómo las dos pistas se encuentran en el "punto de drenaje".

¿Qué comandos deberían colocarse en segundo plano?

No todos los comandos deben pasarse a segundo plano. Hay dos criterios:

  1. Consume mucho tiempo: la ejecución sincrónica en unos pocos segundos es más sencilla y elimina la necesidad de mantener colas.
  2. Importancia del resultado: si el resultado se usa inmediatamente en el siguiente paso (como cat file.txt seguido inmediatamente de grep), el fondo no tiene sentido; aún debe esperar.
Interactivo

Widget 1 · Línea de tiempo · Hilo principal + 2 hilos bg

Haga clic en Generar para enviar el trabajo al hilo de bg. El hilo principal verifica la cola de notificaciones en cada tic. Mire cómo se entrelazan los tres carriles de nado.

🧠 Main (agent loop)
⚙ Background thread A
(idle)
⚙ Background thread B
(idle)
queue: []
Interactivo

Widget 2 · Fire & Forget Judgment · 8 comandos, ¿cuáles vale la pena respaldar?

Elija primer plano (sincrónico, etc.) o fondo (generación asincrónica) para cada comando. Preste atención a las dos dimensiones de "debería esperar el resultado" + "lleva mucho tiempo".

答对 0 / 8
Interactivo

Widget 3 · Tiempo de drenaje · En qué ronda se vio la notificación

Regla clave: el hilo principal drena la cola antes de cada llamada de LLM. Te doy 5 escenarios. Respuesta: Una vez completada la tarea bg, ¿en qué ronda entrarán los resultados en el campo de visión del agente?

答对 0 / 5