# O ciclo do agente

Como a CLI do Copilot processa uma mensagem de usuário de ponta a ponta: do prompt ao session.idle.

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

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

## Architecture

![Diagrama: diagrama de grafo mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-0.png)

O **SDK** é uma camada de transporte — ele envia seu prompt para o **Copilot CLI** via JSON-RPC e retorna os eventos para o seu aplicativo. A **CLI** é o orquestrador que executa o ciclo de uso de ferramentas pelo agente, realizando uma ou mais chamadas à API de LLM até que a tarefa seja concluída.

## O ciclo de uso de ferramentas

Quando você chama `session.send({ prompt })`, a CLI insere um loop:

![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-1.png)

O modelo vê o **histórico completo da conversa** em cada chamada — prompt do sistema, mensagem do usuário e todas as chamadas e resultados de ferramentas anteriores.

**Insight principal:** Cada iteração desse loop é exatamente uma chamada à API de LLM, visível no log de eventos como um par `assistant.turn_start` / `assistant.turn_end`. Não há chamadas ocultas.

## Turnos – o que são

Um **turno** é uma única chamada à API LLM e suas consequências:

1. A CLI envia o histórico de conversas para o LLM
2. O LLM responde (possivelmente com solicitações de ferramentas)
3. Se as ferramentas foram solicitadas, a CLI as executa
4. `assistant.turn_end` é emitido

Normalmente, uma única mensagem de usuário resulta em **várias voltas**. Por exemplo, uma pergunta como "como o X funciona nessa base de código?" pode produzir:

| Volta                  | O que o modelo faz                                          | toolRequests? |
| ---------------------- | ----------------------------------------------------------- | ------------- |
| 1                      | Chama `grep` e `glob` para pesquisar na base de código      |               |
| ✅ Sim                  |                                                             |               |
| 2                      | Lê arquivos específicos com base nos resultados da pesquisa |               |
| ✅ Sim                  |                                                             |               |
| 3                      | Lê mais arquivos para um contexto mais profundo             |               |
| ✅ Sim                  |                                                             |               |
| 4                      | Produz a resposta de texto final                            |               |
| ❌ Não → o loop termina |                                                             |               |

O modelo decide em cada turno se deseja solicitar mais ferramentas ou produzir uma resposta final. Cada chamada vê o **contexto acumulado completo** (todas as chamadas e resultados de ferramentas anteriores), para que possa tomar uma decisão informada sobre se ela tem informações suficientes.

## Fluxo de eventos para uma interação de vários turnos

![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/features-agent-loop-diagram-2.png)

## Quem dispara cada turno?

| Ator               | Responsabilidade                                                                                                 |
| ------------------ | ---------------------------------------------------------------------------------------------------------------- |
| **Seu aplicativo** | Envia o prompt inicial por meio de `session.send()`                                                              |
| **Copilot CLI**    | Executa o ciclo de uso de ferramentas — executa as ferramentas e exibe os resultados ao LLM para o próximo turno |
| **LLM**            | Decide se deve solicitar ferramentas (continuar o loop) ou produzir uma resposta final (interromper)             |
| **SDK**            | Transmite eventos; não controla o loop                                                                           |

A CLI é puramente mecânica: "o modelo solicitou ferramentas → executá-las → chamar o modelo novamente." O **modelo** é o tomador de decisão para quando parar.

## `session.idle` versus `session.task_complete`

Estes são dois sinais de conclusão diferentes com garantias muito diferentes:

### `session.idle`

* **Sempre emitido** quando o loop de uso da ferramenta termina
* **Efêmero**: não persistido em disco, não reexecutado na retomada da sessão
* Significa: "o agente parou de processar e está pronto para a próxima mensagem"
* **Use isso** como seu sinal confiável de "concluído"

O método do `sendAndWait()` SDK aguarda este evento:

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

### `session.task_complete`

* **Emitido opcionalmente**: requer que o modelo o indique explicitamente
* **Persistido**: salvo no log de eventos da sessão em disco
* Significa: "o agente considera a tarefa geral atendida"
* Carrega um campo opcional `summary`

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

### Modo Autopilot: as sugestões da CLI para `task_complete`

No **modo de piloto automático** (operação sem cabeça/autônoma), a CLI controla ativamente se o modelo chamou `task_complete`. Se o loop de uso da ferramenta terminar sem isso, a CLI injetará uma mensagem sintética de usuário para orientar o modelo:

> *"Você ainda não marcou a tarefa como concluída usando a ferramenta task\_complete. Se você estava planejando, interrompa o planejamento e comece a implementar. Você não terminará até concluir totalmente a tarefa."*

Isso reinicia efetivamente o loop de uso de ferramentas– o modelo vê o empurrão como uma nova mensagem de usuário e continua funcionando. A sugestão também instrui o modelo a **não** chamar `task_complete` prematuramente:

* Não chame se você tiver perguntas abertas, tome decisões e continue trabalhando
* Não a chame se encontrar um erro — tente resolvê-lo
* Não chame se houver etapas restantes – conclua-as primeiro

Isso cria um **mecanismo de conclusão de dois níveis** no piloto automático:

1. O modelo chama `task_complete` com um resumo → CLI emite `session.task_complete` → concluído
2. O modelo interrompe sem fazer a chamada → a CLI dá um aviso → o modelo continua ou chama `task_complete`

### Por que `task_complete` talvez não apareça

No **modo interativo** (chat normal), a CLI não solicita `task_complete`. O modelo pode ignorá-lo completamente. Motivos comuns:

* **Q\&A de conversa**: o modelo responde a uma pergunta e simplesmente para — não há nenhuma "tarefa" discreta para concluir
* **Critério do modelo**: o modelo produz uma resposta de texto final sem chamar o sinal de conclusão da tarefa
* **Sessões interrompidas**: a sessão termina antes que o modelo atinja um ponto de conclusão

A CLI emite `session.idle` independentemente, porque é um sinal mecânico (o loop terminou), não um semântico (o modelo acha que foi feito).

### Qual você deve usar?

| Caso de uso                                          | Sinal |
| ---------------------------------------------------- | ----- |
| "Aguarde até que o agente conclua o processamento"   |       |
| `session.idle`                                       |       |
| ✅                                                    |       |
|                                                      |       |
| "Saiba quando uma tarefa de codificação é concluída" |       |
| `session.task_complete` (melhor esforço)             |       |
| "Tempo limite/tratamento de erros"                   |       |
| `session.idle`                                       |       |

*

`session.error`
✅
|

## Contagem de chamadas ao LLM

O número de pares `assistant.turn_start` / `assistant.turn_end` no log de eventos é igual ao número total de chamadas feitas à API LLM. Não há chamadas ocultas para planejamento, avaliação ou verificação de conclusão.

Para inspecionar a contagem de turnos de uma sessão:

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

## Leitura adicional

* [Eventos de sessão de streaming](/pt/copilot/how-tos/copilot-sdk/features/streaming-events): Referência completa no nível de campo para cada tipo de evento
* [Retomada e persistência da sessão](/pt/copilot/how-tos/copilot-sdk/features/session-persistence): Como as sessões são salvas e retomadas
* [Trabalhando com ganchos](/pt/copilot/how-tos/copilot-sdk/features/hooks): interceptar eventos no loop (permissões, ferramentas)