Loop dell’agente
Descrive come la Copilot CLI elabora end-to-end i messaggi dell’utente (dall’invio del prompt fino asession.idle).
Architettura
L’SDK è il livello di trasporto. Invia i prompt alla Copilot CLI tramite JSON-RPC e inoltra gli eventi all’applicazione. È la CLI a eseguire il loop di utilizzo degli strumenti in modo agentico, orchestrando una o più chiamate API all’LLM fino al completamento del task.Loop di utilizzo degli strumenti
Quando chiamisession.send({ prompt }), la CLI entra nel seguente loop.
A ogni chiamata il modello fa riferimento all’intera cronologia della conversazione (system prompt / user message / tutte le chiamate a strumenti e i relativi risultati fino a quel momento).
Importante: una iterazione di questo loop corrisponde esattamente a una chiamata API all’LLM e, nel log degli eventi, appare come una coppia assistant.turn_start / assistant.turn_end. Non ci sono chiamate nascoste.
Cos’è un turn
Un turn è una singola chiamata API all’LLM e il suo risultato.- La CLI invia la cronologia della conversazione all’LLM
- L’LLM risponde (eventualmente includendo richieste di strumenti)
- Se ci sono richieste di strumenti, la CLI le esegue
- Viene emesso
assistant.turn_end
| Turn | Comportamento del modello | toolRequests? |
|---|---|---|
| 1 | Cerca nella codebase con grep e glob | ✅ Sì |
| 2 | Legge file specifici in base ai risultati della ricerca | ✅ Sì |
| 3 | Legge ulteriori file per un contesto più approfondito | ✅ Sì |
| 4 | Genera la risposta testuale finale | ❌ No → loop ends |
Flusso di eventi in caso di più turn
Chi avvia ciascun turn
| Attore | Responsabilità |
|---|---|
| La tua app | Invia il primo prompt con session.send() |
| Copilot CLI | Esegue il loop di utilizzo degli strumenti e restituisce all’LLM i risultati come input del turn successivo |
| LLM | Decide se richiedere altri strumenti e proseguire, oppure restituire la risposta finale e terminare |
| SDK | Si limita a inoltrare gli eventi. Non controlla il loop |
Differenza tra session.idle e session.task_complete
Entrambi sono segnali di completamento, ma offrono garanzie molto diverse.
session.idle
- Sempre emesso al termine del loop di utilizzo degli strumenti
- Effimero (ephemeral). Non viene persistito su disco e non viene riprodotto alla ripresa della sessione
- Significato: “l’agente ha smesso di elaborare ed è pronto ad accettare il prossimo messaggio”
- Da usare come segnale affidabile di “completato”
sendAndWait() dell’SDK attende questo evento.
session.task_complete
- Emissione facoltativa (solo se il modello lo segnala esplicitamente)
- Persistito (salvato nel log degli eventi della sessione)
- Significato: “l’agente stesso ha giudicato completato l’intero task”
- Può includere un
summaryopzionale
Modalità autopilot: la CLI sollecita task_complete
In modalità autopilot (headless / autonoma), la CLI tiene traccia di se il modello ha chiamato task_complete. Se il loop di utilizzo degli strumenti termina senza task_complete, la CLI inserisce il seguente messaggio utente sintetico per sollecitare il modello.
“You have not yet marked the task as complete using the task_complete tool. If you were planning, stop planning and start implementing. You aren’t done until you have fully completed the task.”Questo di fatto riavvia il loop di utilizzo degli strumenti. Il modello riceve la sollecitazione come nuovo messaggio dell’utente e prosegue il lavoro. La sollecitazione include anche l’indicazione di “non chiamare
task_complete troppo presto”.
- Non chiamarlo se restano domande aperte. Decidi e continua a lavorare
- Non chiamarlo se hai appena incontrato un errore. Prova a risolverlo
- Non chiamarlo se ci sono task residui. Completali prima
- Il modello chiama
task_completecon un summary → la CLI emettesession.task_complete→ completato - Il modello si ferma senza chiamarlo → la CLI sollecita → il modello prosegue oppure chiama
task_complete
Perché task_complete potrebbe non essere emesso
In modalità interattiva (chat normale), la CLI non sollecita task_complete. Il modello può ometterlo. I motivi principali sono i seguenti.
- Q&A conversazionale: risponde alla domanda e termina, senza un “task completato” discreto
- Decisione del modello: restituisce il testo finale senza chiamare
task_complete - Sessione interrotta: la sessione termina prima che il modello raggiunga un punto di completamento
session.idle. Questo perché non è un segnale semantico (il modello ha giudicato completato) ma un segnale meccanico (il loop è terminato).
Quale usare
| Caso d’uso | Segnale |
|---|---|
| ”Attendere la fine dell’elaborazione dell’agente” | session.idle ✅ |
| “Sapere che il task di coding è stato completato” | session.task_complete (best-effort) |
| “Gestione di timeout/errori” | session.idle + session.error ✅ |
Contare il numero di chiamate all’LLM
Il numero di coppieassistant.turn_start / assistant.turn_end nel log degli eventi coincide con il numero totale di chiamate API all’LLM. Non ci sono chiamate nascoste per pianificazione, valutazione o conferma del completamento.
Esempio di verifica del numero di turn di una sessione:
Documenti correlati
- Eventi di streaming — riferimento a livello di campo per ciascun tipo di evento
- Ripresa della sessione — salvataggio e ripresa della sessione
- Hook di sessione — intercettare eventi all’interno del loop (permessi · strumenti)