# Bucle del agente

Cómo la CLI de Copilot procesa un mensaje de usuario de un extremo a otro: desde la solicitud hasta session.idle.

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

## Architecture

![Diagrama: diagrama de gráfico que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-0.png)

El **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.

## Bucle de uso de herramientas

Cuando se llama a `session.send({ prompt })`, la CLI entra en un bucle:

![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png)

El 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.

**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.

## Turnos: lo que son

Un **turno** es una sola llamada API de LLM y sus consecuencias:

1. La CLI envía el historial de conversaciones al LLM.
2. El LLM responde (posiblemente con peticiones de herramientas)
3. Si se solicitaron herramientas, la CLI las ejecuta.
4. `assistant.turn_end` se emite

Un ú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:

| Turno                    | Qué hace el modelo                                                    | toolRequests? |
| ------------------------ | --------------------------------------------------------------------- | ------------- |
| 1                        | Llama a `grep` y a `glob` para buscar en la base de código            |               |
| ✅ Sí                     |                                                                       |               |
| 2                        | Lee archivos específicos en función de los resultados de la búsqueda. |               |
| ✅ Sí                     |                                                                       |               |
| 3                        | Lee más archivos para un contexto más profundo.                       |               |
| ✅ Sí                     |                                                                       |               |
| 4                        | Genera la respuesta de texto final.                                   |               |
| ❌ No → finaliza el bucle |                                                                       |               |

El 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.

## Flujo de eventos para una interacción de varios turnos

![Diagrama: Diagrama de flujo que muestra el proceso descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png)

## ¿Quién desencadena cada turno?

| Actor             | Responsabilidad                                                                                                             |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **La aplicación** | Envía el mensaje inicial a través de `session.send()`                                                                       |
| **Copilot CLI**   | Ejecuta el bucle de uso de herramientas: ejecuta las herramientas y devuelve los resultados al LLM para el siguiente turno. |
| **LLM**           | Decide si solicitar herramientas (seguir en bucle) o generar una respuesta final (detenerse)                                |
| **SDK**           | Deja pasar los eventos; no controla el bucle                                                                                |

La CLI es puramente mecánica: "el modelo pide herramientas → ejecutar → volver a llamar al modelo". El **modelo** es quien decide cuándo detenerse.

## `session.idle` frente a `session.task_complete`

Estas son dos señales de finalización diferentes con garantías muy diferentes:

### `session.idle`

* **Siempre se emite** cuando finaliza el bucle de uso de herramientas
* **Efímero**: no se conserva en el disco, no se reproduce en el reanudación de la sesión
* Significa: "el agente ha detenido el procesamiento y está listo para el siguiente mensaje"
* **Use esto** como una señal fiable de "hecho"

El método del `sendAndWait()` SDK espera este evento:

```typescript
// Blocks until session.idle fires
const response = await session.sendAndWait({ prompt: "Fix the bug" });
```

### `session.task_complete`

* **Opcionalmente emitido**: requiere que el modelo lo indique explícitamente.
* **Persistente**: guardado en el registro de eventos de sesión en el disco
* Significa: "el agente considera que se ha cumplido la tarea general"
* Lleva un campo opcional `summary`

```typescript
session.on("session.task_complete", (event) => {
    console.log("Task done:", event.data.summary);
});
```

### Modo piloto automático: indicaciones de la CLI para `task_complete`

En **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:

> *"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".*

Esto 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`:

* No lo llames si tienes preguntas abiertas, toma decisiones y sigue trabajando
* No lo llame si se produce un error: intente resolverlo.
* No lo invoques si quedan pasos pendientes: complétalos primero

Esto crea un **mecanismo de finalización de dos niveles** en Autopilot:

1. El modelo llama a `task_complete` con un resumen → la CLI genera `session.task_complete` → listo
2. El modelo se detiene sin invocarlo → la CLI lo reorienta → el modelo continúa o llama a `task_complete`

### ¿Por qué `task_complete` podría no aparecer?

En **modo interactivo** (chat normal), la CLI no solicita `task_complete`. El modelo puede omitirlo por completo. Motivos comunes:

* **Preguntas y respuestas conversacionales**: El modelo responde a una pregunta y simplemente se detiene, no hay ninguna "tarea" discreta para completarse.
* **Discreción** del modelo: el modelo genera una respuesta de texto final sin llamar a la señal de tarea completa.
* **Sesiones interrumpidas**: la sesión finaliza antes de que el modelo alcance un punto de finalización.

La 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).

### ¿Cuál deberías usar?

| Caso de uso                                         | Señal |
| --------------------------------------------------- | ----- |
| "Espere a que el agente finalice el procesamiento"  |       |
| `session.idle`                                      |       |
| ✅                                                   |       |
|                                                     |       |
| "Saber cuándo se realiza una tarea de codificación" |       |
| `session.task_complete` (mejor esfuerzo)            |       |
| "Tiempo de espera/control de errores"               |       |
| `session.idle`                                      |       |

*

`session.error`
✅
|

## Recuento de llamadas LLM

El 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.

Para inspeccionar el recuento de turnos de una sesión:

```bash
# Count turns in a session's event log
grep -c "assistant.turn_start" ~/.copilot/session-state/<sessionId>/events.jsonl
```

## Lectura adicional

* [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
* [Reanudación y persistencia de sesión](/es/copilot/how-tos/copilot-sdk/features/session-persistence): Cómo se guardan y reanudan las sesiones
* [Trabajar con enlaces](/es/copilot/how-tos/copilot-sdk/features/hooks): Interceptación de eventos en el bucle (permisos, herramientas)