# Copilot CLI ACP-Server

Erfahren Sie mehr über GitHub Copilot CLIden Agent-Clientprotokollserver.

> \[!NOTE]
> Die ACP-Unterstützung in GitHub Copilot CLI ist in Öffentliche Vorschau und kann geändert werden.

## Übersicht

Das Agent-Client-Protokoll (ACP) ist ein Protokoll, das die Kommunikation zwischen Clients (z. B. Code-Editoren und IDEs) und Agenten (wie Copilot CLI) standardisiert. Weitere Informationen zu diesem Protokoll finden Sie in der [offiziellen Einführung](https://agentclientprotocol.com/get-started/introduction).

## Anwendungsfälle

* **IDE-Integrationen:** Integrieren Sie Copilot Unterstützung in jede Editor- oder Entwicklungsumgebung.
* **CI/CD-Pipelines:** Koordinieren Sie agentische Codierungsaufgaben in automatisierten Workflows.
* **Benutzerdefinierte Frontends:** Erstellen Sie spezielle Schnittstellen für bestimmte Entwicklerworkflows.
* **Multi-Agent-Systeme:** Koordinieren sie Copilot mit anderen KI-Agents mithilfe eines Standardprotokolls.

## Starten des ACP-Servers

Verwenden Sie die `--acp` Option des `copilot` Befehls, um den ACP-Server der CLI zu starten. Sie können den Transportmodus entweder mit den Optionen `--stdio` oder `--port` angeben. Wenn kein Transportmodus angegeben ist, wird der Server standardmäßig im Stdiomodus ausgeführt.

Im ACP-Modus können Sitzungen mit einem konfigurierten BYOK-Anbieter (Bring Your Own Key) (`COPILOT_PROVIDER_*`-Umgebungsvariablen) ohne GitHub-Anmeldung ausgeführt werden, entsprechend dem Verhalten des Modus `-p`/interactive.

### Auf jede Sitzung angewendete Optionen

Mit der ACP-Anforderung `session/new` kann ein Client nur einige Sitzungsparameter festlegen, z. B. das Arbeitsverzeichnis und die MCP-Server. Sie enthält keine Tool-Filter- oder Reasoning-Einstellungen. Um diese zu konfigurieren, übergeben Sie die entsprechenden Optionen, wenn Sie **den Server starten**. Der Server speichert die Werte und wendet sie als Initialkonfiguration für jede Sitzung an, die er erstellt oder lädt, für jeden Client, der eine Verbindung herstellt. Ein Client, der eine Verbindung herstellt, legt diese Werte nicht fest – sondern derjenige, der den Server startet.

| Serveroption                                 | Akzeptierter Wert                                                              | Auswirkung auf jede Sitzung                              |
| -------------------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------- |
| `--available-tools=TOOL ...`                 | Eine in Anführungszeichen gesetzte, durch Kommas getrennte Liste von Toolnamen | Die Sitzung kann nur die aufgelisteten Tools verwenden.  |
| `--excluded-tools=TOOL ...`                  | Eine in Anführungszeichen gesetzte, durch Kommas getrennte Liste von Toolnamen | Die aufgelisteten Tools werden aus der Sitzung entfernt. |
| `--effort=LEVEL`, `--reasoning-effort=LEVEL` |                                                                                |                                                          |
| `low`, `medium`, `high`, `xhigh` oder `max`  | Legt den anfänglichen Argumentationsaufwand der Sitzung fest.                  |                                                          |

Zum Beispiel startet dieser Befehl einen Server, bei dem alle Sitzungen maximale Schlussfolgerungsintensität nutzen und nur die Tools `bash` und `view` bereitstellen:

```bash
copilot --acp --port 3000 --effort=max --available-tools="bash,view"
```

Jede Sitzung, die der verbundene Client mit diesem Server öffnet, erbt diese Einstellungen. Da die Werte beim Starten des Servers behoben sind, kann ein Client sie nicht pro Sitzung durch `session/new`ändern.

### stdio-Modus

Der stdio-Modus wird standardmäßig erkannt, wenn Sie den ACP-Server starten. Sie können auch die Option `--stdio` zur Disambiguierung verwenden.

```bash
copilot --acp --stdio
```

### TCP-Modus

Wenn die `--port` Option in Kombination mit der `--acp` Option bereitgestellt wird, wird der Server im TCP-Modus gestartet.

```bash
copilot --acp --port 3000
```

### Auswahl zwischen Stdio und TCP

Beide Transportmodi übertragen dieselben ACP-Nachrichten, die als newline-delimited JSON (NDJSON) codiert sind. Sie unterscheiden sich nur darin, wie ein Client eine Verbindung mit dem Server herstellt und wie der Lebenszyklus des Servers verwaltet wird. Die beiden Modi schließen einander aus: Die gleichzeitige Übergabe von `--stdio` und `--port` wird abgelehnt.

| Aspect                                       | stdio-Modus                                                                                                                                                                                        | TCP-Modus                                                                                                                                                                      |
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Wie der Client eine Verbindung herstellt** | Der Client startet `copilot --acp` als Kindprozess und tauscht Nachrichten über die Standardeingabe und -ausgabe dieses Prozesses aus.                                                             | Der Server öffnet einen TCP-Listener, mit dem Clients über einen Netzwerksocket eine Verbindung herstellen. Standardmäßig wird sie an die Loopbackadresse `127.0.0.1`gebunden. |
| **Anzahl der Clients**                       | Ein einzelner Client – der Prozess, der den Server erzeugt hat und die Pipe besitzt.                                                                                                               | Der Listener nimmt Socket-Verbindungen an, wobei jede als eigene Agentverbindung behandelt wird.                                                                               |
| **Lebenszyklus**                             | An den übergeordneten Prozess gebunden. Wenn der Eingabestream geschlossen wird, weil der übergeordnete Prozess beendet wird oder die Pipe schließt, wird der Server automatisch heruntergefahren. | Unabhängig von jedem einzelnen Client. Der Server überwacht den Port, bis er beendet wird, z. B. mit <kbd>STRG</kbd>+<kbd>C</kbd>.                                             |
| **Standardausgabe**                          | Reserviert für den NDJSON-Protokolldatenstrom, sodass er nicht für Protokolle oder anderen Text verwendet werden kann.                                                                             | Kostenlos für andere Zwecke, da der Protokolldatenverkehr über den Socket reist.                                                                                               |

Wann jeder Modus verwendet werden soll:

* Verwenden Sie **den Stdiomodus** , wenn ein Editor, eine IDE oder ein Skript direkt als Teilprozess spawnsiert Copilot CLI . Dies ist die Standard- und die empfohlene Konfiguration für die IDE-Integration, da der Transport beim Start des Prozesses automatisch aufgebaut und beim Beenden wieder abgebaut wird.
* Verwenden Sie den **TCP-Modus** , wenn ein Client den Server über einen Socket anstelle einer Pipe erreichen muss , z. B. von einem separaten Prozess oder Container oder beim Herstellen einer Verbindung mit einem längerlebigen Server auf einem bekannten Port.

## Beispiel: Integration mit dem ACP-Server

Das folgende Beispiel ist eine Clientanwendung, die Copilot verwendet, indem sie mit dem ACP-Server von GitHub Copilot CLI interagiert. Es startet den ACP-Server im stdio-Modus, öffnet eine Sitzung, fordert Sie zur Eingabe eines Prompts auf, sendet ihn und gibt die gestreamte Antwort aus.

Es gibt ein wachsendes Ökosystem von Bibliotheken für die programmgesteuerte Interaktion mit ACP-Servern. In diesem Beispiel wird die [ACP TypeScript-Bibliothek verwendet](https://agentclientprotocol.com/libraries/typescript).

Zum Ausführen dieses Beispiels benötigen Sie die folgenden Abhängigkeiten:

* [Node.js](https://nodejs.org) Version 18 oder höher.
* GitHub Copilot CLI, installiert und entweder mit GitHub authentifiziert oder mit einem BYOK-Anbieter konfiguriert (siehe [Starten des ACP-Servers](#starting-the-acp-server)).
* Das `@agentclientprotocol/sdk` Paket, das die ACP TypeScript-Bibliothek bereitstellt. Installieren Sie es, indem Sie ausführen `npm install @agentclientprotocol/sdk`.

```typescript copy
import * as acp from "@agentclientprotocol/sdk";
import { spawn } from "node:child_process";
import { Readable, Writable } from "node:stream";
import * as readline from "node:readline/promises";

async function main() {
  const executable = process.env.COPILOT_CLI_PATH ?? "copilot";

  // ACP uses standard input/output (stdin/stdout) for transport; we pipe these for the NDJSON stream.
  const copilotProcess = spawn(executable, ["--acp", "--stdio"], {
    stdio: ["pipe", "pipe", "inherit"],
  });

  if (!copilotProcess.stdin || !copilotProcess.stdout) {
    throw new Error("Failed to start Copilot ACP process with piped stdio.");
  }

  // Create ACP streams (NDJSON over stdio)
  const output = Writable.toWeb(copilotProcess.stdin) as WritableStream<Uint8Array>;
  const input = Readable.toWeb(copilotProcess.stdout) as ReadableStream<Uint8Array>;
  const stream = acp.ndJsonStream(output, input);

  const client: acp.Client = {
    async requestPermission(params) {
      // This example should not trigger tool calls; if it does, refuse.
      return { outcome: { outcome: "cancelled" } };
    },

    async sessionUpdate(params) {
      const update = params.update;

      if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
        process.stdout.write(update.content.text);
      }
    },
  };

  const connection = new acp.ClientSideConnection((_agent) => client, stream);

  await connection.initialize({
    protocolVersion: acp.PROTOCOL_VERSION,
    clientCapabilities: {},
  });

  const sessionResult = await connection.newSession({
    cwd: process.cwd(),
    mcpServers: [],
  });

  process.stdout.write("Session started!\n");

  // Ask the user to enter a prompt instead of using a hard-coded one.
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  const promptText = await rl.question("Enter a prompt: ");
  rl.close();

  const promptResult = await connection.prompt({
    sessionId: sessionResult.sessionId,
    prompt: [{ type: "text", text: promptText }],
  });

  process.stdout.write("\n");

  if (promptResult.stopReason !== "end_turn") {
    process.stderr.write(`Prompt finished with stopReason=${promptResult.stopReason}\n`);
  }

  // Best-effort cleanup
  copilotProcess.stdin.end();
  copilotProcess.kill("SIGTERM");
  await new Promise<void>((resolve) => {
    copilotProcess.once("exit", () => resolve());
    setTimeout(() => resolve(), 2000);
  });
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
```

So führen Sie das Beispiel aus:

1. Speichern Sie den obigen Code in einer Datei mit dem Namen `acp-client.ts`.
2. Führen Sie die Datei mit `npx tsx` aus, wodurch TypeScript direkt ohne einen separaten Buildschritt ausgeführt wird:

   ```bash
   npx tsx acp-client.ts
   ```

## Verwendung von Slash-Befehlen

Die integrierten Slash-Befehle von GitHub Copilot CLI können über ACP ausgeführt werden. Um einen davon aufzurufen, senden Sie ihn als gewöhnlichen Prompt, dessen Text der Befehl ist, der als einzelner Textinhaltsblock übergeben wird – zum Beispiel `/context` oder `/session info`. Der Server erkennt den Befehl und führt ihn direkt aus: Informationsbefehle wie `/usage` oder `/context` geben ihre Ausgabe zurück, ohne das Modell aufzurufen, während Aktionsbefehle wie `/plan` oder `/review` die entsprechende Agentenaufgabe starten. Auf beide Weise wird der Befehlstext nicht als Frage an das Modell gesendet.

### Ermitteln verfügbarer Befehle

Der Server kündigt die Befehle an, die er über die standardmäßige ACP-Sitzungsbenachrichtigung `available_commands_update` unterstützt. Es wird gesendet, nachdem eine Sitzung erstellt oder geladen wurde, und erneut, wenn sich der Satz ändert – zum Beispiel, wenn die Skills fertig geladen sind. Diese bekannt gegebene Liste ist die maßgebliche, stets aktuelle Liste der Befehle, die Sie über ACP ausführen können, und Clients zeigen sie typischerweise in einem Befehlsmenü an.

Die angekündigte Liste enthält:

* **Integrierte Befehle**, wie z. B. `/compact`, `/context`, `/usage`, `/env`, `/model`, `/mcp`, `/plan`, `/review`, `/research`, `/session` und `/rename`.
* **Aktivierte, benutzerfreundliche Fähigkeiten**, die als `/SKILL-NAME` Befehle angezeigt werden.

Befehle, die der Client selbst registriert, werden ihm nicht zurück bekanntgegeben.

### Zugreifen auf die Liste von Ihrem Client

Da die Liste nicht als Reaktion auf eine Anforderung, sondern als Benachrichtigung eingeht, gibt es keine Methode, sie bei Bedarf abzurufen. Ihr Client greift darauf zu, indem die `session/update` Benachrichtigung verarbeitet und auf Updates reagiert wird, deren Typ lautet `available_commands_update`. Jeder Eintrag verfügt über einen `name` (ohne den führenden Schrägstrich), einen `description`und einen optionalen `input.hint` Eintrag, der die Argumente des Befehls beschreibt. Die Benachrichtigung wird jedes Mal erneut gesendet, wenn sich der Satz ändert. Betrachten Sie daher jede Benachrichtigung als vollständigen Ersatz der Liste, die Sie zwischengespeichert haben.

Der folgende `sessionUpdate` Handler erfasst die angekündigten Befehle und erweitert das `client` Objekt aus dem zuvor gezeigten Beispiel.

```typescript copy
// Track the latest advertised commands for the session.
let availableCommands: acp.AvailableCommand[] = [];

const client: acp.Client = {
  async sessionUpdate(params) {
    const update = params.update;

    if (update.sessionUpdate === "available_commands_update") {
      // This notification is a full snapshot—replace any cached list.
      availableCommands = update.availableCommands;
      for (const command of availableCommands) {
        // command.name has no leading slash; invoke it by sending "/<name>" as a prompt.
        console.log(`/${command.name} — ${command.description}`);
      }
      return;
    }

    // ...handle other updates, such as agent_message_chunk
  },

  // ...other client methods, such as requestPermission
};
```

Um einen der angekündigten Befehle auszuführen, senden Sie den Namen als Eingabeaufforderung in einem einzelnen Textinhaltsblock , `{ type: "text", text: "/context" }`z. B. wie unter [Verwenden von Schrägstrichbefehlen](#using-slash-commands) beschrieben.

### Befehle, die nicht über ACP verwendet werden können

Slash-Befehle, die die interaktive Terminalschnittstelle voraussetzen, werden vom ACP-Server nicht verarbeitet. Dazu gehören Befehle, mit denen eine Auswahl, ein Dialogfeld oder eine Vollbildansicht geöffnet wird, beispielsweise `/diff`, `/resume`, `/theme`, `/settings`, `/login`, `/help`, `/tasks` und `/undo`. Wenn ein Befehl in der `available_commands_update` Liste nicht angezeigt wird, wird er in der Regel nicht über ACP ausgeführt: Der Server behandelt den Text als normale Eingabeaufforderung und leitet ihn an das Modell weiter, anstatt ihn auszuführen.

Da ACP-Clients keine interaktiven Auswahlen haben, gibt ein integrierter Befehl, der normalerweise ein Untermenü öffnet, seine Optionen als Text zurück. Geben Sie den Unterbefehl explizit an, um ein direktes Ergebnis zu erhalten – zum Beispiel `/session info` oder `/mcp list` statt `/session` oder `/mcp` für sich allein.

Eine vollständige Liste der Schrägstrichbefehle für Copilot CLI finden Sie unter [GitHub Copilot CLI-Befehlsreferenz](/de/copilot/reference/copilot-cli-reference/cli-command-reference#slash-commands-in-the-interactive-interface).

## Weiterführende Lektüre

* [Offizielle ACP-Dokumentation](https://agentclientprotocol.com/protocol/overview)