{"meta":{"title":"Bucle del agente","intro":"Cómo la CLI de Copilot procesa un mensaje de usuario de un extremo a otro: desde la solicitud hasta session.idle.","product":"GitHub Copilot","breadcrumbs":[{"href":"/es/copilot","title":"GitHub Copilot"},{"href":"/es/copilot/how-tos","title":"Procedimientos"},{"href":"/es/copilot/how-tos/copilot-sdk","title":"SDK de Copilot"},{"href":"/es/copilot/how-tos/copilot-sdk/features","title":"Características"},{"href":"/es/copilot/how-tos/copilot-sdk/features/agent-loop","title":"Bucle del agente"}],"documentType":"article"},"body":"# Bucle del agente\n\nCómo la CLI de Copilot procesa un mensaje de usuario de un extremo a otro: desde la solicitud hasta session.idle.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\n## Architecture\n\n![Diagrama: diagrama de gráfico que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-0.png)\n\nEl **SDK** es una capa de transporte: envía el mensaje al **Copilot CLI** a través de JSON-RPC y expone eventos de vuelta a la aplicación. La **CLI** es el orquestador que ejecuta el bucle de uso de herramientas por parte del agente, realizando una o varias llamadas a la API de LLM hasta que la tarea se completa.\n\n## Bucle de uso de herramientas\n\nCuando se llama a `session.send({ prompt })`, la CLI entra en un bucle:\n\n![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png)\n\nEl modelo ve el **historial de conversaciones completo** en cada llamada: aviso del sistema, mensaje de usuario y todas las llamadas y resultados de las herramientas anteriores.\n\n**Información clave:** Cada iteración de este bucle es exactamente una llamada API de LLM, visible como un `assistant.turn_start` / `assistant.turn_end` par en el registro de eventos. No hay llamadas ocultas.\n\n## Turnos: lo que son\n\nUn **turno** es una sola llamada API de LLM y sus consecuencias:\n\n1. La CLI envía el historial de conversaciones al LLM.\n2. El LLM responde (posiblemente con peticiones de herramientas)\n3. Si se solicitaron herramientas, la CLI las ejecuta.\n4. `assistant.turn_end` se emite\n\nUn único mensaje de usuario suele dar lugar a **varios turnos**. Por ejemplo, una pregunta como \"¿cómo funciona X en este código base?\" puede producir:\n\n| Turno                    | Qué hace el modelo                                                    | toolRequests? |\n| ------------------------ | --------------------------------------------------------------------- | ------------- |\n| 1                        | Llama a `grep` y a `glob` para buscar en la base de código            |               |\n| ✅ Sí                     |                                                                       |               |\n| 2                        | Lee archivos específicos en función de los resultados de la búsqueda. |               |\n| ✅ Sí                     |                                                                       |               |\n| 3                        | Lee más archivos para un contexto más profundo.                       |               |\n| ✅ Sí                     |                                                                       |               |\n| 4                        | Genera la respuesta de texto final.                                   |               |\n| ❌ No → finaliza el bucle |                                                                       |               |\n\nEl modelo decide cada turno si desea solicitar más herramientas o generar una respuesta final. Cada llamada ve el **contexto acumulado completo** (todas las llamadas a herramientas y resultados anteriores), por lo que puede tomar una decisión informada sobre si tiene suficiente información.\n\n## Flujo de eventos para una interacción de varios turnos\n\n![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png)\n\n## ¿Quién desencadena cada turno?\n\n| Actor             | Responsabilidad                                                                                                             |\n| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |\n| **La aplicación** | Envía el mensaje inicial a través de `session.send()`                                                                       |\n| **Copilot CLI**   | Ejecuta el bucle de uso de herramientas: ejecuta las herramientas y devuelve los resultados al LLM para el siguiente turno. |\n| **LLM**           | Decide si solicitar herramientas (seguir en bucle) o generar una respuesta final (detenerse)                                |\n| **SDK**           | Deja pasar los eventos; no controla el bucle                                                                                |\n\nLa CLI es puramente mecánica: \"el modelo pide herramientas → ejecutar → volver a llamar al modelo\". El **modelo** es quien decide cuándo detenerse.\n\n## `session.idle` frente a `session.task_complete`\n\nEstas son dos señales de finalización diferentes con garantías muy diferentes:\n\n### `session.idle`\n\n* **Siempre se emite** cuando finaliza el bucle de uso de herramientas\n* **Efímero**: no se conserva en el disco, no se reproduce en el reanudación de la sesión\n* Significa: \"el agente ha detenido el procesamiento y está listo para el siguiente mensaje\"\n* **Use esto** como una señal fiable de \"hecho\"\n\nEl método del `sendAndWait()` SDK espera este evento:\n\n```typescript\n// Blocks until session.idle fires\nconst response = await session.sendAndWait({ prompt: \"Fix the bug\" });\n```\n\n### `session.task_complete`\n\n* **Opcionalmente emitido**: requiere que el modelo lo indique explícitamente.\n* **Persistente**: guardado en el registro de eventos de sesión en el disco\n* Significa: \"el agente considera que se ha cumplido la tarea general\"\n* Lleva un campo opcional `summary`\n\n```typescript\nsession.on(\"session.task_complete\", (event) => {\n    console.log(\"Task done:\", event.data.summary);\n});\n```\n\n### Modo piloto automático: indicaciones de la CLI para `task_complete`\n\nEn **modo de piloto automático** (funcionamiento sin interfaz o autónomo), la CLI supervisa activamente si el modelo ha invocado `task_complete`. Si el bucle de uso de herramientas termina sin que eso ocurra, la CLI inyecta un mensaje de usuario sintético para orientar al modelo:\n\n> *\"Todavía no ha marcado la tarea como completada con la herramienta task\\_complete. Si estaba planeando, detenga la planeación y empiece a implementar. No ha terminado hasta que haya completado completamente la tarea\".*\n\nEsto reinicia eficazmente el bucle tool-use: el modelo ve el nudge como un nuevo mensaje de usuario y continúa funcionando. La indicación también instruye al modelo para **no** llamar prematuramente a `task_complete`:\n\n* No lo llames si tienes preguntas abiertas, toma decisiones y sigue trabajando\n* No lo llame si se produce un error: intente resolverlo.\n* No lo invoques si quedan pasos pendientes: complétalos primero\n\nEsto crea un **mecanismo de finalización de dos niveles** en Autopilot:\n\n1. El modelo llama a `task_complete` con un resumen → la CLI genera `session.task_complete` → listo\n2. El modelo se detiene sin invocarlo → la CLI lo reorienta → el modelo continúa o llama a `task_complete`\n\n### ¿Por qué `task_complete` podría no aparecer?\n\nEn **modo interactivo** (chat normal), la CLI no solicita `task_complete`. El modelo puede omitirlo por completo. Motivos comunes:\n\n* **Preguntas y respuestas conversacionales**: El modelo responde a una pregunta y simplemente se detiene, no hay ninguna \"tarea\" discreta para completarse.\n* **Discreción** del modelo: el modelo genera una respuesta de texto final sin llamar a la señal de tarea completa.\n* **Sesiones interrumpidas**: la sesión finaliza antes de que el modelo alcance un punto de finalización.\n\nLa CLI emite `session.idle` independientemente, ya que es una señal mecánica (el bucle finalizó), no una semántica (el modelo cree que se ha hecho).\n\n### ¿Cuál deberías usar?\n\n| Caso de uso                                         | Señal |\n| --------------------------------------------------- | ----- |\n| \"Espere a que el agente finalice el procesamiento\"  |       |\n| `session.idle`                                      |       |\n| ✅                                                   |       |\n|                                                     |       |\n| \"Saber cuándo se realiza una tarea de codificación\" |       |\n| `session.task_complete` (mejor esfuerzo)            |       |\n| \"Tiempo de espera/control de errores\"               |       |\n| `session.idle`                                      |       |\n\n*\n\n`session.error`\n✅\n|\n\n## Recuento de llamadas LLM\n\nEl número de pares del registro de eventos es igual al número total de `assistant.turn_start` / `assistant.turn_end` llamadas API de LLM realizadas. No hay llamadas ocultas para la planeación, evaluación o comprobación de finalización.\n\nPara inspeccionar el recuento de turnos de una sesión:\n\n```bash\n# Count turns in a session's event log\ngrep -c \"assistant.turn_start\" ~/.copilot/session-state/<sessionId>/events.jsonl\n```\n\n## Lectura adicional\n\n* [Eventos de la sesión de transmisión](/es/copilot/how-tos/copilot-sdk/features/streaming-events): Referencia completa de nivel de campo para cada tipo de evento\n* [Reanudación y persistencia de sesión](/es/copilot/how-tos/copilot-sdk/features/session-persistence): Cómo se guardan y reanudan las sesiones\n* [Trabajar con enlaces](/es/copilot/how-tos/copilot-sdk/features/hooks): Interceptación de eventos en el bucle (permisos, herramientas)"}