Große Sprachmodelle (Large Language Models, kurz LLMs) können Programmcode erzeugen, komplexe Aufgaben analysieren und technische Probleme lösen. Ein Sprachmodell allein kann jedoch normalerweise weder Dateien auf unserem Computer verändern noch Programme ausführen oder Softwaretests durchführen.
Erst durch eine geeignete Ausführungsumgebung wird aus einem Sprachmodell ein handlungsfähiger KI-Agent.
An dieser Stelle kommt das sogenannte KI-Harness ins Spiel.
In diesem Beitrag erkläre ich, was sich hinter diesem Begriff verbirgt, wie ein KI-Harness funktioniert und warum eine isolierte Ausführungsumgebung für den sicheren Einsatz von KI-Agenten so wichtig ist.
Anschließend bauen wir unter Ubuntu eine praktische Entwicklungsumgebung auf, in der OpenCode und die OpenAI-CLI innerhalb eines Docker-Containers ausgeführt werden.
1. Was ist ein KI-Harness?
Ein Large Language Model ist zunächst ein System, das Eingaben verarbeitet und daraus Ausgaben generiert.
Es erhält beispielsweise die Aufforderung:
Erstelle ein Python-Programm, das eine CSV-Datei einliest, die enthaltenen Werte auswertet und das Ergebnis als Diagramm darstellt.
Das Modell kann den entsprechenden Programmcode erzeugen. Ohne zusätzliche Werkzeuge kann es diesen Code jedoch nicht automatisch auf unserem Computer speichern, ausführen oder testen.
Ein KI-Harness stellt die Infrastruktur bereit, die das Sprachmodell mit seiner Arbeitsumgebung verbindet.
Ein solches Harness kann beispielsweise folgende Funktionen übernehmen:
- Kontextverwaltung: Bereitstellung von Aufgabenbeschreibungen, Projektdateien und bisherigen Arbeitsergebnissen.
- Werkzeugverwaltung: Zugriff auf Dateisystem, Terminal, Compiler oder andere Programme.
- Ausführungssteuerung: Verarbeitung und Ausführung der vom Modell angeforderten Aktionen.
- Sicherheitskontrolle: Begrenzung von Berechtigungen, Verzeichniszugriffen und Netzwerkverbindungen.
- Ergebnisverarbeitung: Rückgabe von Ausgaben, Fehlermeldungen und Testergebnissen an das Modell.
- Protokollierung: Dokumentation der ausgeführten Aktionen.
- Ablaufsteuerung: Wiederholung von Arbeitsschritten, bis eine Aufgabe abgeschlossen ist oder eine festgelegte Grenze erreicht wurde.
Der Begriff Harness stammt ursprünglich aus dem Englischen und bezeichnet unter anderem eine Vorrichtung, mit der etwas geführt oder kontrolliert wird.
In der KI-Entwicklung beschreibt er die technische Umgebung, die ein Sprachmodell bei der Ausführung konkreter Aufgaben unterstützt.
Dabei ist ein Harness nicht zwangsläufig ein einzelnes Programm. Es kann aus mehreren Komponenten bestehen.
2. Vom Sprachmodell zum KI-Agenten
Der Unterschied zwischen einem reinen LLM und einem KI-Agenten lässt sich anhand einer einfachen Programmieraufgabe verdeutlichen.
Ein Sprachmodell kann einen Programmcode generieren.
Ein KI-Agent mit entsprechendem Harness kann dagegen einen vollständigen Arbeitsablauf durchführen:
- Die Aufgabenstellung analysieren.
- Vorhandene Projektdateien untersuchen.
- Neue Dateien erstellen oder bestehende Dateien verändern.
- Das Programm ausführen.
- Fehlermeldungen auswerten.
- Den Programmcode korrigieren.
- Die Anwendung erneut testen.
- Das Ergebnis dokumentieren.
Daraus entsteht ein wiederholbarer Arbeitszyklus:
Aufgabe → LLM → Werkzeugaufruf → Ausführung → Rückmeldung → LLM
Dieser Ablauf ist eine der wesentlichen Grundlagen moderner KI-Agenten.
Ein Beispiel:
Wir beauftragen einen Agenten, eine Webanwendung zu erstellen.
Das Modell entscheidet, welche Dateien benötigt werden. Das Harness ermöglicht das Schreiben der Dateien und führt anschließend einen Build aus.
Schlägt der Build fehl, erhält das Modell die Fehlermeldung und kann auf dieser Grundlage versuchen, das Problem zu beheben.
Dieser Prozess kann so lange wiederholt werden, bis die Anwendung erfolgreich erstellt wurde oder eine festgelegte Grenze erreicht wird.
Allerdings bedeutet ein erfolgreicher Build nicht automatisch, dass eine Anwendung korrekt, sicher oder vollständig ist. Dafür sind weitere Tests und gegebenenfalls eine menschliche Prüfung notwendig.
3. Warum benötigt ein KI-Agent eine Sandbox?
Je mehr Werkzeuge einem KI-Agenten zur Verfügung stehen, desto größer sind seine Möglichkeiten.
Gleichzeitig steigt jedoch das Risiko unerwünschter Aktionen.
Ein Agent mit Terminalzugriff könnte beispielsweise:
- Wichtige Projektdateien überschreiben.
- Verzeichnisse versehentlich löschen.
- Nicht vertrauenswürdige Software installieren.
- Vertrauliche Informationen auslesen.
- Externe Netzwerkverbindungen herstellen.
- Fehlerhafte Skripte ausführen, die große Mengen an Rechenleistung verbrauchen.
Solche Probleme müssen nicht aus böser Absicht entstehen. Schon fehlerhaft generierte Befehle können unerwünschte Auswirkungen haben.
Auch sogenannte Prompt-Injection-Angriffe sind zu berücksichtigen. Dabei enthalten beispielsweise eingelesene Dateien oder externe Webseiten Anweisungen, die den Agenten zu einer unerwünschten Handlung verleiten sollen.
Eine wichtige Gegenmaßnahme ist die Sandbox.
Eine Sandbox ist eine begrenzte Ausführungsumgebung, in der Programme mit kontrollierten Berechtigungen ausgeführt werden.
Im Idealfall kann ein KI-Agent darin seine Aufgaben erledigen, ohne uneingeschränkten Zugriff auf das Betriebssystem des Benutzers zu erhalten.
4. Docker als Grundlage einer KI-Sandbox
Docker bietet eine praktische Möglichkeit, Anwendungen in Containern auszuführen.
Ein Container erhält ein eigenes Dateisystem und eine vom Host teilweise isolierte Prozess- und Netzwerkumgebung.
Dadurch lassen sich die Möglichkeiten eines Agenten gezielt begrenzen.
Beispielsweise können wir festlegen:
- Welche Verzeichnisse ein Container bearbeiten darf.
- Unter welchem Benutzer die Prozesse ausgeführt werden.
- Wie viel Arbeitsspeicher und CPU-Leistung zur Verfügung stehen.
- Welche Linux-Berechtigungen entfernt werden.
- Ob Netzwerkverbindungen erlaubt sind.
Für unsere Beispielumgebung verwenden wir einen Docker-Container, in dem zwei Kommandozeilenprogramme installiert sind: OpenCode und die OpenAI-CLI.
Wichtig: Ein Docker-Container ist keine vollständige Sicherheitsgrenze wie eine entsprechend gehärtete virtuelle Maschine. Für die Verarbeitung nicht vertrauenswürdiger Software oder besonders sensibler Daten können zusätzliche Isolationstechniken erforderlich sein.
5. Die Werkzeuge unserer Beispielumgebung
Docker und Docker Compose
Docker übernimmt die Ausführung und Isolation des Containers.
Docker Compose beschreibt dessen Konfiguration, Ressourcenbegrenzungen und Verzeichniszuordnungen.
OpenCode
OpenCode ist ein quelloffener Coding-Agent, der über ein Terminal bedient werden kann.
Das Programm kann mit verschiedenen Sprachmodellen verbunden werden und stellt Funktionen bereit, mit denen ein KI-Agent unter anderem Dateien bearbeiten und Kommandozeilenbefehle ausführen kann.
OpenCode bildet in unserer Beispielumgebung einen wesentlichen Teil des eigentlichen Agent-Harness.
OpenAI-CLI
Die offizielle OpenAI-CLI ist ein Kommandozeilenwerkzeug für die OpenAI-API.
Damit können API-Anfragen unmittelbar aus dem Terminal gesendet werden.
Anders als OpenCode ist diese CLI nicht automatisch ein vollständiger autonomer Coding-Agent.
Sie ist jedoch nützlich, um das Verhalten eines Sprachmodells unabhängig vom Agenten zu untersuchen oder eigene Harness-Komponenten zu entwickeln.
6. Architektur unserer Sandbox
Die geplante Umgebung besteht aus einem Ubuntu-Rechner mit Docker und einem eigenen Container für die KI-Werkzeuge.
Der grundlegende Aufbau:
Ubuntu-Host
│
├── Docker Engine
│ │
│ └── KI-Sandbox
│ │
│ ├── OpenCode
│ │ └── Agentensteuerung
│ │
│ ├── OpenAI-CLI
│ │ └── Direkte API-Anfragen
│ │
│ ├── Werkzeuge
│ │ ├── Shell
│ │ ├── Git
│ │ └── Dateisystem
│ │
│ └── /workspace
│ └── Entwicklungsprojekt
│
└── sandbox/
├── Dockerfile
├── compose.yaml
├── .env
└── workspace/
Die Sprachmodelle selbst laufen in diesem Beispiel nicht im Container.
Stattdessen stellen OpenCode und die OpenAI-CLI über das Netzwerk Verbindungen zu den entsprechenden OpenAI-API-Endpunkten her.
Der Container stellt die lokale Ausführungsumgebung zur Verfügung, während die Modellberechnung beim API-Anbieter stattfindet.
Das hat einen Vorteil: Auf dem Ubuntu-Rechner wird keine leistungsfähige GPU für die eigentliche Modellausführung benötigt.
Allerdings setzt dieser Aufbau einen Netzwerkzugang voraus und API-Anfragen können zusätzliche Kosten verursachen.
7. Voraussetzungen
Für die folgenden Schritte benötigen wir:
- Einen Ubuntu-Rechner oder eine Ubuntu-VM.
- Eine funktionsfähige Installation von Docker Engine.
- Das Docker-Compose-Plugin.
- Einen OpenAI-API-Schlüssel mit entsprechendem API-Zugang.
- Ausreichend freien Speicherplatz zum Erstellen des Container-Images.
Die folgenden Befehle werden in einem Terminal auf dem Ubuntu-Rechner ausgeführt.
Zunächst prüfen wir, ob Docker installiert und erreichbar ist:
docker --version
docker compose version
Anschließend prüfen wir den Zugriff auf den Docker-Dienst:
docker info
Bei einer korrekten Installation sollten die Docker-Informationen ausgegeben werden.
8. Projektverzeichnis erstellen
Zunächst erstellen wir ein eigenes Verzeichnis für unsere KI-Sandbox.
mkdir -p ~/ki-sandbox/workspace
cd ~/ki-sandbox
Darin legen wir später die folgenden Dateien an:
ki-sandbox/
├── Dockerfile
├── compose.yaml
├── .env
├── .env.example
├── .gitignore
└── workspace/
Das Verzeichnis workspace dient als Arbeitsbereich für den KI-Agenten.
Nur dieses Verzeichnis wird für die eigentliche Projektbearbeitung in den Container eingebunden.
Andere persönliche Verzeichnisse, SSH-Schlüssel oder das gesamte Home-Verzeichnis des Ubuntu-Benutzers werden nicht eingebunden.
9. Das Dockerfile erstellen
Das Dockerfile beschreibt den Aufbau unseres Container-Images.
Wir benötigen Node.js für OpenCode sowie die offizielle OpenAI-CLI, die in diesem Beispiel aus ihrem Go-Quellcode erstellt wird.
Dafür verwenden wir einen mehrstufigen Docker-Build.
Erstellen wir zunächst die Datei:
nano Dockerfile
Mit folgendem Inhalt:
# Build-Stufe für die OpenAI-CLI
FROM golang:1.26-bookworm AS openai-builder
RUN go install github.com/openai/openai-cli/cmd/openai@latest
# Ausführungsumgebung
FROM node:22-bookworm
# Werkzeuge installieren
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
git \
ca-certificates \
bash \
curl \
&& rm -rf /var/lib/apt/lists/*
# OpenCode installieren
RUN npm install -g @opencode/cli
# OpenAI-CLI aus der Build-Stufe übernehmen
COPY --from=openai-builder \
/go/bin/openai /usr/local/bin/openai
# Eigenes Arbeitsverzeichnis
WORKDIR /workspace
# Nicht privilegierten Benutzer verwenden
USER node
ENV HOME=/home/node
CMD ["bash"]
Was passiert beim Image-Build?
In der ersten Stufe wird die OpenAI-CLI mit dem Go-Compiler erstellt.
Die zweite Stufe basiert auf einem Node.js-Image.
Darin werden die benötigten Werkzeuge installiert. Anschließend wird die fertig kompilierte OpenAI-CLI aus der ersten Build-Stufe übernommen.
Der Go-Compiler muss dadurch nicht im endgültigen Container vorhanden sein.
OpenCode wird über npm installiert.
Zum Schluss wird festgelegt, dass die Programme standardmäßig unter dem unprivilegierten Benutzer node ausgeführt werden.
Hinweis: Dieses Beispiel orientiert sich an den zum Zeitpunkt der Erstellung verfügbaren Installationswegen. Für langfristig reproduzierbare Builds sollten feste, geprüfte Versionen statt @latest verwendet werden. Bei einer späteren Neuinstallation sind außerdem die dann gültigen Versionsanforderungen zu überprüfen.
10. Docker Compose konfigurieren
Nun erstellen wir die Datei compose.yaml.
nano compose.yaml
Inhalt:
services:
ai-sandbox:
build:
context: .
dockerfile: Dockerfile
image: local/ki-sandbox:dev
working_dir: /workspace
stdin_open: true
tty: true
environment:
OPENAI_API_KEY: ${OPENAI_API_KEY:?OPENAI_API_KEY fehlt}
HOME: /home/node
volumes:
- ./workspace:/workspace
user: "1000:1000"
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
pids_limit: 256
mem_limit: 4g
cpus: 2.0
Schauen wir uns die sicherheitsrelevanten Einstellungen an.
Begrenzter Arbeitsbereich
volumes:
- ./workspace:/workspace
Diese Anweisung verbindet das lokale Verzeichnis workspace mit dem Verzeichnis /workspace innerhalb des Containers.
Der Agent kann dadurch auf die dort enthaltenen Dateien zugreifen und sie verändern.
Das übrige Dateisystem des Ubuntu-Hosts wird nicht automatisch als Arbeitsverzeichnis eingebunden.
Allerdings sind Änderungen innerhalb dieses Verzeichnisses unmittelbar auf dem Host sichtbar.
Nicht privilegierter Benutzer
user: "1000:1000"
Damit werden Prozesse unter der numerischen Benutzer-ID 1000 und Gruppen-ID 1000 ausgeführt.
Auf vielen Ubuntu-Installationen entspricht dies dem ersten regulären Benutzer.
Die tatsächliche UID und GID lassen sich mit dem Befehl id prüfen. Gegebenenfalls muss die Compose-Datei entsprechend angepasst werden.
Linux-Berechtigungen entfernen
cap_drop:
- ALL
Hierdurch werden die Linux-Capabilities des Containers entfernt.
Für normale Dateibearbeitungen und viele Entwicklungstätigkeiten werden diese erweiterten Berechtigungen nicht benötigt.
Zusätzliche Privilegien verhindern
security_opt:
- no-new-privileges:true
Diese Einstellung verhindert, dass Containerprozesse über bestimmte Mechanismen zusätzliche Privilegien erhalten.
Ressourcen begrenzen
pids_limit: 256
mem_limit: 4g
cpus: 2.0
Mit diesen Einstellungen begrenzen wir die Anzahl der Prozesse, den Arbeitsspeicher und die CPU-Leistung.
Dies verhindert nicht sämtliche Formen einer Überlastung, reduziert aber das Risiko, dass ein fehlerhafter Agentenprozess die Ressourcen des Hosts unbegrenzt beansprucht.
Netzwerkzugriff
In unserem Beispiel ist der ausgehende Netzwerkzugriff grundsätzlich möglich.
Dieser wird benötigt, damit OpenCode und die OpenAI-CLI die jeweiligen API-Endpunkte erreichen können.
Das bedeutet allerdings auch, dass ein Agent innerhalb der Sandbox grundsätzlich andere erreichbare Netzwerkziele kontaktieren könnte.
Für höhere Sicherheitsanforderungen sollte deshalb zusätzlich eine restriktive Netzwerkregelung eingesetzt werden.
Ganz wichtig: Wir binden den Docker-Socket des Hosts nicht in den Container ein. Dadurch verhindern wir, dass der Agent unmittelbar die Docker-Verwaltung des Hostsystems verwenden kann.
11. API-Schlüssel konfigurieren
Damit die KI-Werkzeuge mit OpenAI kommunizieren können, benötigen wir einen entsprechenden API-Schlüssel.
Diesen können wir im OpenAI-API-Dashboard erstellen.
Anschließend legen wir im Projektverzeichnis eine .env-Datei an:
nano .env
Inhalt:
OPENAI_API_KEY=HIER_DEN_EIGENEN_API_SCHLUESSEL_EINTRAGEN
Aus dieser Datei liest Docker Compose den Schlüssel und übergibt ihn als Umgebungsvariable an den Container.
Damit steht er grundsätzlich sowohl der OpenAI-CLI als auch dem entsprechend konfigurierten OpenCode-Provider zur Verfügung.
Die Datei sollte nur für den eigenen Benutzer lesbar sein:
chmod 600 .env
Außerdem erstellen wir eine .gitignore:
.env
workspace/
Damit werden die Zugangsdaten und die lokalen Arbeitsdateien bei einer normalen Git-Verwendung nicht versehentlich als neue Dateien aufgenommen.
Zusätzlich können wir eine .env.example ohne echten Schlüssel erstellen:
OPENAI_API_KEY=HIER_API_SCHLUESSEL_EINTRAGEN
Sicherheitshinweis: Die Übergabe von API-Schlüsseln als Container-Umgebungsvariablen ist einfach, aber nicht ideal. Die Werte können für entsprechend berechtigte Personen oder Prozesse sichtbar sein. Auch die Anwendung selbst kann auf den Schlüssel zugreifen.
Bei einer produktiven Agentenplattform sollten bevorzugt ein geeigneter Secret-Manager oder ein vermittelnder API-Dienst mit eingeschränkten Berechtigungen verwendet werden.
12. Sandbox erstellen und starten
Nachdem alle Dateien angelegt wurden, können wir unser Container-Image erstellen.
docker compose build
Docker lädt die benötigten Basis-Images, installiert die Werkzeuge und erstellt unser eigenes Image.
Anschließend starten wir eine interaktive Shell:
docker compose run --rm ai-sandbox
Mit --rm wird der gestartete Container nach dem Beenden wieder entfernt.
Die Dateien im eingebundenen workspace bleiben erhalten.
Wir befinden uns nun innerhalb der Docker-Sandbox.
Zur Kontrolle können wir einige Befehle ausführen:
whoami
pwd
git --version
opencode --version
openai --help
Als Benutzer sollte node angezeigt werden.
Das Arbeitsverzeichnis sollte /workspace sein.
Damit ist die grundlegende Containerumgebung eingerichtet.
13. Die OpenAI-CLI testen
Zunächst wollen wir überprüfen, ob das Sprachmodell über die OpenAI-API erreichbar ist.
Dazu führen wir innerhalb des Containers eine einfache Anfrage aus:
openai responses create \
--model gpt-5.5 \
--input "Erkläre in drei Sätzen, was ein KI-Harness ist."
Die OpenAI-CLI überträgt die Anfrage an die API und gibt die Antwort im Terminal aus.
Voraussetzung ist, dass der angegebene Modellname für den verwendeten API-Zugang verfügbar ist.
Alternativ kann ein anderes verfügbares Modell angegeben werden.
Dieser Vorgang zeigt zunächst die direkte Kommunikation zwischen unserem Programm und einem LLM.
Das Sprachmodell beantwortet unsere Anfrage, verändert aber noch keine Dateien.
Hier haben wir also eine direkte Modellinteraktion, noch keinen vollständigen autonomen Arbeitsablauf.
14. OpenCode als KI-Agent einsetzen
Nun starten wir innerhalb des Containers OpenCode:
opencode
OpenCode öffnet seine terminalbasierte Benutzeroberfläche.
Bei der erstmaligen Verwendung kann es notwendig sein, den gewünschten Modellanbieter und ein passendes Modell auszuwählen.
Für unser Beispiel verwenden wir OpenAI als Modellanbieter.
Anschließend geben wir dem Agenten eine konkrete Aufgabe:
Erstelle ein Python-Programm, das eine CSV-Datei mit den Spalten Datum und Temperatur einliest und die durchschnittliche Temperatur berechnet. Erstelle zusätzlich eine Beispieldatei mit zehn Messwerten und dokumentiere die Verwendung in einer README.md.
OpenCode kann daraufhin die Aufgabenstellung analysieren und die entsprechenden Dateien erzeugen.
Im Gegensatz zur vorherigen direkten API-Anfrage stehen dem Agenten nun Werkzeuge zur Dateibearbeitung und Befehlsausführung zur Verfügung.
Beispielsweise könnte er folgende Dateien erstellen:
/workspace/
├── analyse.py
├── temperaturen.csv
└── README.md
Da das Verzeichnis /workspace mit unserem lokalen Arbeitsverzeichnis verbunden ist, erscheinen diese Dateien auch auf unserem Ubuntu-Rechner.
Der Agent kann außerdem versuchen, das Programm auszuführen und eventuell auftretende Fehler zu beheben.
In unserem Container sind allerdings nur die zuvor installierten Werkzeuge garantiert verfügbar. Für dieses konkrete Python-Beispiel muss Python gegebenenfalls zusätzlich im Dockerfile installiert werden.
Eine Alternative ist, dem Agenten eine Aufgabe zu stellen, die ausschließlich mit den bereits verfügbaren Werkzeugen gelöst werden kann.
15. Der eigentliche Harness-Ablauf
Betrachten wir, was hinter den Kulissen geschieht, wenn OpenCode eine Entwicklungsaufgabe übernimmt.
Schritt 1: Der Benutzer stellt eine Aufgabe
Der Benutzer beschreibt das gewünschte Ergebnis.
Beispiel:
Erstelle ein Shell-Skript, das alle Textdateien im Arbeitsverzeichnis zählt und die Gesamtzahl ausgibt.
Schritt 2: Der Agent erstellt einen Arbeitsplan
OpenCode verarbeitet die Anfrage und stellt dem angebundenen Sprachmodell den entsprechenden Kontext zur Verfügung.
Das Modell entscheidet, welche Arbeitsschritte erforderlich sind.
Schritt 3: Das Modell fordert ein Werkzeug an
Das Modell kann beispielsweise einen Dateischreibvorgang anfordern.
OpenCode verarbeitet diesen Werkzeugaufruf und erstellt die entsprechende Datei, sofern die geltenden Berechtigungen dies erlauben.
Schritt 4: Der Agent führt das Programm aus
Anschließend kann das Modell die Ausführung eines Terminalbefehls anfordern:
bash dateien_zaehlen.sh
Das Harness führt diesen Befehl über seine Werkzeugumgebung aus.
In unserem Beispiel findet die Ausführung innerhalb des Docker-Containers statt.
Schritt 5: Das Ergebnis wird zurückgegeben
Das Programm liefert entweder eine reguläre Ausgabe oder eine Fehlermeldung.
Diese Informationen werden dem Sprachmodell als neuer Kontext übergeben.
Schritt 6: Das Modell bewertet das Ergebnis
Falls ein Fehler aufgetreten ist, kann das Modell eine Korrektur vornehmen und das Programm erneut ausführen lassen.
Dieser Ablauf wiederholt sich gegebenenfalls.
Hier zeigt sich der entscheidende Unterschied zu einer einfachen Chat-Anwendung:
Das Modell erzeugt nicht nur eine Antwort, sondern kann über das Harness einen kontrollierten Arbeitsprozess mit Werkzeugen durchführen.
16. Wo endet das Harness und wo beginnt die Sandbox?
Diese beiden Begriffe sollten klar voneinander unterschieden werden.
Das Harness ist für die Steuerung der Agenteninteraktion zuständig.
Es stellt dem Sprachmodell Werkzeuge zur Verfügung, verarbeitet Werkzeugaufrufe und organisiert den wiederholten Ablauf.
Die Sandbox begrenzt dagegen, welche Auswirkungen die ausgeführten Aktionen auf das System haben können.
In unserem Beispiel übernimmt OpenCode einen großen Teil der Harness-Funktionalität.
Docker stellt die Ausführungsumgebung und einen Teil der technischen Isolation bereit.
Die OpenAI-CLI ermöglicht ergänzend den direkten Zugriff auf die Modell-API.
Dabei erzwingt Docker nicht automatisch sämtliche Sicherheitsregeln, die wir möglicherweise benötigen.
Beispielsweise müssen Freigaberegeln für bestimmte Werkzeugaufrufe innerhalb des Agenten-Harness oder durch zusätzliche Infrastruktur umgesetzt werden.
Ein sorgfältig aufgebautes Agentensystem benötigt deshalb beide Ebenen:
Ein Harness zur Steuerung der Aktionen und eine Sandbox zur Begrenzung ihrer Auswirkungen.
17. Sandbox beenden und bereinigen
Nach der Arbeit können wir die interaktive Sitzung beenden:
exit
Der mit docker compose run --rm gestartete Container wird dadurch entfernt.
Das Docker-Image und die Dateien im lokalen Arbeitsverzeichnis bleiben erhalten.
Bei Bedarf können wir einen neuen Container mit derselben Konfiguration starten:
docker compose run --rm ai-sandbox
Damit erhalten wir wieder eine Umgebung mit den zuvor installierten Werkzeugen.
Das lokale Arbeitsverzeichnis bleibt dabei unverändert.
Soll auch der Arbeitsbereich zurückgesetzt werden, müssen dessen Dateien separat entfernt werden.
Ein möglicher Ansatz ist, statt eines direkt eingebundenen Arbeitsverzeichnisses für jede Aufgabe ein neues temporäres Arbeitsverzeichnis oder einen eigenen Git-Worktree zu verwenden.
18. Grenzen unserer Beispiel-Sandbox
Unsere Docker-Konfiguration reduziert verschiedene Risiken, bietet aber keine vollständige Sicherheitsgarantie.
Insbesondere bleiben folgende Punkte zu beachten:
Netzwerkzugriff: Der Container kann ausgehende Verbindungen herstellen. Ohne zusätzliche Regeln ist der Netzwerkzugriff nicht auf die OpenAI-API begrenzt.
API-Zugangsdaten: Der Agentenprozess kann grundsätzlich auf die übergebenen Umgebungsvariablen zugreifen.
Arbeitsverzeichnis: Dateien im eingebundenen Workspace können verändert oder gelöscht werden.
Host-Isolation: Docker teilt sich den Linux-Kernel mit dem Host. Kernel-Sicherheitslücken oder Konfigurationsfehler können die Isolation gefährden.
Automatische Befehlsausführung: Fehlende Bestätigungsmechanismen können dazu führen, dass vom Modell angeforderte Aktionen unmittelbar ausgeführt werden.
Kostenkontrolle: Wiederholte Modellaufrufe können API-Kosten verursachen. CPU- und Speicherbegrenzungen des Containers verhindern dies nicht.
Für produktive Systeme mit höheren Sicherheitsanforderungen sollte die Architektur daher erweitert werden.
Geeignete Maßnahmen sind beispielsweise separate virtuelle Maschinen, restriktive Netzwerkregeln, ein API-Proxy, kurzlebige Zugangsdaten, getrennte Arbeitsverzeichnisse und unabhängige Prüfmechanismen.
19. Mögliche Erweiterungen
Die hier gezeigte Umgebung stellt eine einfache Grundlage für weitere Experimente dar.
Darauf aufbauend könnten wir beispielsweise:
- Jedem Agenten einen eigenen temporären Container zuweisen.
- Für jede Aufgabe einen separaten Git-Worktree erstellen.
- Werkzeugaufrufe protokollieren.
- Bestimmte Befehle nur nach manueller Bestätigung ausführen.
- Automatische Unit-Tests und Build-Prüfungen integrieren.
- Netzwerkzugriffe über einen Proxy kontrollieren.
- Mehrere spezialisierte Agenten koordinieren.
- Die Anzahl der Modellaufrufe oder die Kosten einer Aufgabe begrenzen.
- Ein lokales LLM statt einer externen API verwenden.
Besonders interessant ist die Trennung zwischen der eigentlichen Agentensteuerung und einer kurzlebigen Ausführungsumgebung.
Ein übergeordnetes System könnte für jede neue Aufgabe eine frische Sandbox bereitstellen und sie anschließend wieder entfernen.
Dadurch ließen sich mehrere unabhängige Entwicklungsaufgaben parallel bearbeiten, ohne dass alle Agenten dieselbe Arbeitsumgebung teilen.
Fazit
Ein KI-Harness ist eine der wesentlichen technischen Grundlagen moderner KI-Agenten.
Erst durch die Verbindung eines Sprachmodells mit Werkzeugen, Kontextverwaltung und einer geeigneten Ablaufsteuerung wird aus einer reinen Textgenerierung ein System, das Aufgaben praktisch bearbeiten kann.
Dabei ist eine wichtige Unterscheidung notwendig:
Das LLM liefert die Entscheidungen und generierten Inhalte. Das Harness organisiert die Werkzeuginteraktion. Die Sandbox begrenzt die Ausführungsumgebung.
Mit Docker, OpenCode und der OpenAI-CLI lässt sich dieses Prinzip relativ einfach nachvollziehen.
OpenCode übernimmt dabei die wesentlichen Funktionen eines Coding-Agenten. Die OpenAI-CLI ermöglicht direkte Modellanfragen und Experimente mit der API. Docker stellt den technischen Rahmen für eine begrenzte lokale Ausführungsumgebung bereit.
Die vorgestellte Konfiguration ist bewusst als Lern- und Entwicklungsumgebung ausgelegt. Sie zeigt die grundlegende Architektur, ersetzt jedoch keine umfassend abgesicherte Infrastruktur für die unbeaufsichtigte Ausführung nicht vertrauenswürdiger KI-Agenten.
Wer diese Grundlagen verstanden hat, kann darauf aufbauend eigene KI-Agenten entwickeln, bestehende Frameworks besser beurteilen und die Möglichkeiten autonomer Softwareentwicklung wesentlich gezielter einsetzen.
