Zum Hauptinhalt springen

Agent-Loop

Hier wird beschrieben, wie die Copilot CLI eine Benutzernachricht Ende-zu-Ende verarbeitet (vom Senden des Prompts bis session.idle).

Architektur

Das SDK ist die Transportschicht. Es sendet Prompts per JSON-RPC an die Copilot CLI und leitet Ereignisse an die Anwendung weiter. Die agentische Tool-Nutzungsschleife und die Orchestrierung eines oder mehrerer LLM-API-Aufrufe bis zum Abschluss der Aufgabe werden auf Seiten der CLI ausgeführt.

Tool-Nutzungsschleife

Wenn Sie session.send({ prompt }) aufrufen, tritt die CLI in die folgende Schleife ein. Das Modell berücksichtigt bei jedem Aufruf den gesamten Konversationsverlauf (System-Prompt / User-Message / alle bisherigen Tool-Aufrufe und Ergebnisse). Wichtig: Eine Iteration dieser Schleife entspricht exakt einem LLM-API-Aufruf und ist im Ereignis-Log als ein Paar assistant.turn_start / assistant.turn_end sichtbar. Es gibt keine versteckten Aufrufe.

Was ist ein Turn?

Ein Turn ist ein einzelner LLM-API-Aufruf und dessen Ergebnis.
  1. Die CLI sendet den Konversationsverlauf an das LLM
  2. Das LLM antwortet (ggf. mit Tool-Anfragen)
  3. Falls Tool-Anfragen vorliegen, führt die CLI sie aus
  4. assistant.turn_end wird ausgelöst
Aus einer einzigen Benutzernachricht ergeben sich üblicherweise mehrere Turns. Bei einer Frage wie „Wie funktioniert X in diesem Codebase?” könnte es beispielsweise so aussehen:
TurnVerhalten des ModellstoolRequests?
1Codebase mit grep und glob durchsuchen✅ Yes
2Auf Basis der Suchergebnisse bestimmte Dateien lesen✅ Yes
3Für tieferen Kontext weitere Dateien lesen✅ Yes
4Endgültige Textantwort erzeugen❌ No → loop ends
In jedem Turn entscheidet das Modell, ob es „weitere Tools nutzt” oder „zur endgültigen Antwort übergeht”. Da jeder Aufruf den gesamten akkumulierten Kontext (einschließlich vergangener Tool-Aufrufe und deren Ergebnisse) sieht, kann es beurteilen, ob genügend Informationen vorliegen.

Ereignisfluss bei mehreren Turns

Wer startet welchen Turn

ActorResponsibility
Your appSendet den initialen Prompt via session.send()
Copilot CLIFührt die Tool-Nutzungsschleife aus und gibt Tool-Ergebnisse als Eingabe des nächsten Turns an das LLM zurück
LLMEntscheidet, ob es mit Tool-Anfragen fortfährt oder mit einer endgültigen Antwort abschließt
SDKLeitet nur Ereignisse weiter. Es steuert die Schleife nicht
Das Verhalten der CLI ist mechanisch („Modell fordert Tool an → Ausführung → erneuter Modellaufruf”). Die Entscheidung über den Abbruch trifft das Modell.

Unterschied zwischen session.idle und session.task_complete

Beide sind Abschlusssignale, ihre Garantien unterscheiden sich jedoch deutlich.

session.idle

  • Wird beim Beenden der Tool-Nutzungsschleife immer ausgelöst
  • Flüchtig (ephemeral). Wird nicht auf die Festplatte persistiert und beim Fortsetzen der Session nicht wiedergegeben
  • Bedeutung: „Der Agent hat die Verarbeitung angehalten und kann die nächste Nachricht entgegennehmen”
  • Verwenden Sie dieses Signal als zuverlässiges „Fertig”-Signal
sendAndWait() des SDK wartet auf dieses Ereignis.
// Warten, bis session.idle ausgelöst wird
const response = await session.sendAndWait({ prompt: "Fix the bug" });

session.task_complete

  • Optional (wird nur ausgelöst, wenn das Modell dies explizit signalisiert)
  • Persistiert (wird im Session-Event-Log gespeichert)
  • Bedeutung: „Der Agent selbst hat die Gesamtaufgabe als erledigt bewertet”
  • Kann eine optionale summary enthalten
session.on("session.task_complete", (event) => {
    console.log("Task done:", event.data.summary);
});

Autopilot-Modus: Die CLI drängt zu task_complete

Im Autopilot-Modus (headless / autonom) verfolgt die CLI, ob das Modell task_complete aufgerufen hat. Endet die Tool-Nutzungsschleife ohne task_complete, fügt die CLI die folgende synthetische Benutzernachricht ein, um das Modell dazu zu bewegen.
“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.”
Dadurch wird die Tool-Nutzungsschleife praktisch wieder aufgenommen. Das Modell empfängt diese Aufforderung als neue Benutzernachricht und setzt die Arbeit fort. Die Aufforderung enthält auch den Hinweis, „task_complete nicht zu früh aufzurufen”.
  • Rufen Sie es nicht auf, wenn offene Fragen bestehen. Entscheiden Sie und setzen Sie die Arbeit fort
  • Rufen Sie es nicht auf, wenn Sie lediglich auf einen Fehler gestoßen sind. Versuchen Sie, ihn zu lösen
  • Rufen Sie es nicht auf, wenn noch Aufgaben ausstehen. Erledigen Sie diese zuerst
Im Autopilot-Modus ergibt sich daraus folgender zweistufiger Abschlussmechanismus:
  1. Das Modell ruft task_complete mit Summary auf → Die CLI löst session.task_complete aus → Abschluss
  2. Das Modell stoppt ohne Aufruf → Die CLI drängt → Das Modell setzt fort oder ruft task_complete auf

Warum task_complete ausbleibt

Im Interactive-Modus (normaler Chat) drängt die CLI nicht zu task_complete. Das Modell kann es weglassen. Die Hauptgründe sind:
  • Konversationelle Q&A: Frage beantworten und beenden, ohne diskrete „erledigte Aufgabe”
  • Modellentscheidung: Endgültigen Text zurückgeben, ohne task_complete aufzurufen
  • Unterbrochene Sessions: Die Session endet, bevor das Modell einen Abschlusspunkt erreicht
Die CLI löst dagegen immer session.idle aus. Dies ist kein semantisches Signal (Modell bewertet als abgeschlossen), sondern ein mechanisches Signal (Schleife beendet).

Welches sollten Sie verwenden?

Use caseSignal
„Auf das Ende der Agent-Verarbeitung warten”session.idle
„Wissen, dass eine Coding-Aufgabe abgeschlossen ist”session.task_complete (best-effort)
„Timeout-/Fehlerbehandlung”session.idle + session.error

Anzahl der LLM-Aufrufe zählen

Die Anzahl der Paare assistant.turn_start / assistant.turn_end im Event-Log stimmt mit der Gesamtzahl der LLM-API-Aufrufe überein. Es gibt keine versteckten Aufrufe für Planung, Bewertung oder Abschlussprüfung. Beispiel zum Prüfen der Anzahl der Turns in einer Session:
# Anzahl der Turns im Session-Event-Log zählen
grep -c "assistant.turn_start" ~/.copilot/session-state/<sessionId>/events.jsonl

Verwandte Dokumentation

Zuletzt geändert am 13. Juli 2026