Zusehen, pausieren, zurückspulen: Live-Beobachtung von Coding-Agenten in Potato
Anleitung zur Einrichtung der Live-Beobachtung von Coding-Agenten mit Ollama, der Anthropic API oder dem Claude Agent SDK, samt Pause, Rollback, Verzweigung und Export der Trajektorien.
Was die Live-Beobachtung anders macht
Die meiste Evaluation von Coding-Agenten passiert im Nachhinein. Der Agent läuft, erzeugt einen Trace, und Reviewer nehmen die Aufzeichnung später auseinander. Die Live-Beobachtung funktioniert andersherum. Der Annotator sieht dem Agenten in Echtzeit bei der Arbeit zu und bekommt jede Dateiänderung, jedes Terminalkommando und jeden Denkschritt mit, sobald er ankommt.
Damit ändert sich, was möglich ist. Schlägt der Agent den falschen Weg ein, kann der Annotator eingreifen, bevor dort Zeit verloren geht. Er kann pausieren, um ein Diff in Ruhe zu lesen, bevor der Agent weitermacht, oder ihn mit einer Anweisung in Alltagssprache umlenken. Am nützlichsten finde ich den Rollback. An jedem früheren Checkpoint lässt sich zurückspulen, und der Agent kann einen anderen Ansatz versuchen. Solche Branches sind die Art von Daten, die Präferenzlernen braucht.
Das ersetzt die Annotation statischer Traces nicht, es liefert eine andere Art von Daten. Statische Annotation gewinnt, wenn man viel davon zu vorhersagbaren Kosten braucht. Die Live-Beobachtung gewinnt, wenn es um gezielte Daten geht, wenn man verstehen will, wie ein Agent scheitert, oder wenn man verzweigte Präferenzpaare aufbaut.
Die vollständige Feature-Referenz steht in der Quelldokumentation.
Die Oberfläche für Live-Coding-Agenten streamt die Aktionen des Agenten in Echtzeit und zeigt Code-Diffs und Terminalausgaben, während der Agent arbeitet:
Live-Beobachtung eines Coding-Agenten mit Diff-Darstellung und Terminalausgabe in Echtzeit
Drei Backends
Potato bietet drei Backends für die Live-Beobachtung. Jedes davon führt einen Coding-Agenten in einer Sandbox aus und streamt seine Aktionen in die Oberfläche, sobald sie passieren.
Ollama (vollständig lokal)
Das Ollama-Backend läuft komplett auf dem eigenen Rechner, ohne API-Keys und ohne Netzwerkanfragen. Es passt, wenn die Codebasis sensibel ist oder wenn man einfach experimentieren will, ohne eine API-Rechnung anwachsen zu lassen.
Zuerst Ollama installieren und ein Modell mit Tool-Nutzung laden:
# Install Ollama
curl -fsSL https://ollama.ai/install.sh | sh
# Pull a coding-capable model
ollama pull qwen2.5-coder:32b
# Verify the model is available
ollama listPotato für das Ollama-Backend konfigurieren:
# config.yaml
annotation_task_name: "Live Agent Observation - Ollama"
port: 8000
live_coding_agent:
backend_type: ollama_tool_use
ai_config:
model: "qwen2.5-coder:32b"
base_url: "http://localhost:11434"
temperature: 0.2
max_tokens: 4096
working_dir: ./workspace # Agent's working directory
max_turns: 50
sandbox_mode: container # container (default) | bubblewrap | trusted
sandbox_image: "python:3.11-slim"Anthropic API (Claude mit Tool-Nutzung)
Das Anthropic-API-Backend verbindet sich mit Claude-Modellen samt Tool-Nutzung. Man bekommt stärkeres Reasoning und bessere Codegenerierung als bei den meisten lokalen Modellen und zahlt dafür die API-Aufrufe.
# Set your API key
export ANTHROPIC_API_KEY="sk-ant-..."# config.yaml
annotation_task_name: "Live Agent Observation - Claude"
port: 8000
live_coding_agent:
backend_type: anthropic_tool_use
ai_config:
model: "claude-sonnet-4-20250514"
max_tokens: 8192
temperature: 0.1
system_prompt: >
You are a coding agent. You will be given a task description and
access to a codebase. Use the provided tools to read files, make
edits, and run commands to complete the task. Think step by step
and verify your changes by running tests.
working_dir: ./workspace
max_turns: 50
sandbox_mode: container
sandbox_image: "python:3.11-slim"Claude Agent SDK (voller Funktionsumfang von Claude Code)
Das Backend mit dem Claude Agent SDK ist das leistungsfähigste der drei, mit dem vollständigen Werkzeugsatz von Claude Code und autonomem Verhalten. Es setzt das Paket claude-agent-sdk voraus.
# Install the Claude Agent SDK
pip install claude-agent-sdk# config.yaml
annotation_task_name: "Live Agent Observation - Claude Agent SDK"
port: 8000
live_coding_agent:
backend_type: claude_sdk
ai_config:
model: "claude-sonnet-4-20250514"
working_dir: ./workspace
max_turns: 50 # Maximum number of agent turns
sandbox_mode: container
sandbox_image: "node:20-slim"Der Annotationsablauf
Sobald der Server läuft, durchläuft eine Live-Beobachtungssitzung ein paar Phasen.
Eine Sitzung starten
Der Annotator öffnet die Potato-Oberfläche und sieht ein Eingabefeld für die Aufgabenbeschreibung. Dort fügt er die Aufgabe ein, die der Agent erledigen soll, oder tippt sie ein, etwa „Behebe den fehlschlagenden Test in tests/test_parser.py, den das neue Konfigurationsformat verursacht“ oder „Füge dem Endpunkt /api/users Paginierung hinzu“.
# Start the server
potato start config.yaml -p 8000Der Annotator klickt auf „Start Agent“, und der Coding-Agent legt los. Jede Aktion erscheint in Echtzeit im Panel der CodingTraceDisplay.
Dem Agenten bei der Arbeit zusehen
Während der Agent läuft, taucht jeder Schritt im Trace-Viewer auf:
- Denkschritte erscheinen als einklappbare graue Blöcke mit dem Reasoning des Agenten.
- Dateilesevorgänge erscheinen als syntaxhervorgehobene Codeblöcke mit Zeilennummern und Dateipfad.
- Dateiänderungen erscheinen als Unified Diffs mit roter und grüner Hervorhebung.
- Terminalkommandos erscheinen als dunkle Terminalblöcke mit Kommando, Ausgabe und Exit-Code.
- Der Dateibaum in der Seitenleiste aktualisiert sich, sobald Dateien angelegt, geändert oder gelesen werden.
Eine Fortschrittsanzeige oben zeigt die aktuelle Schrittnummer und die verstrichene Zeit. Der Status des Agenten erscheint als „Thinking...“, „Editing file...“, „Running command...“ und so weiter.
Pause und Anweisungen
Während der Agent läuft, kann der Annotator über die Steuerleiste eingreifen:
Pause: Friert den Agenten ein, sobald der aktuelle Schritt abgeschlossen ist. Der Agent geht erst zum nächsten Schritt weiter, wenn er fortgesetzt wird. Damit lässt sich ein Diff oder eine Terminalausgabe gründlich prüfen, bevor der Agent weitermacht.
Anweisung senden: Im pausierten Zustand (oder sogar während der Agent läuft) eine Nachricht in natürlicher Sprache eintippen, die in den Kontext des Agenten eingefügt wird. Zum Beispiel „Ändere das Datenbankschema nicht, verwende stattdessen eine Migration“ oder „Sieh dir vor den Änderungen das Fehlerprotokoll unter /var/log/app.log an“.
Resume: Setzt die Ausführung des Agenten nach einer Pause fort.
Stop: Beendet die Agent-Sitzung vollständig. Die Trajektorie bis zu diesem Punkt wird gespeichert.
Annotatoren können die Arbeit des Agenten mit PRM-Annotation neben der Trace-Anzeige bewerten:
PRM-Oberfläche für Korrektheitslabels pro Schritt neben dem Coding-Trace
Die Steuerleiste gehört zum Viewer für Live-Coding-Agenten. Pause, Fortsetzen, Einfügen von Anweisungen, Stopp, Rollback und Wechsel zwischen Branches sind Sitzungsaktionen, die die Oberfläche über die Live-Agent-Endpunkte auslöst. In der Konfiguration muss also nichts eingeschaltet werden.
Das Git-basierte Checkpoint-System
Rollback, Verzweigung und der Export der Trajektorien beruhen alle auf dem Checkpoint-System, das nach jeder Dateiänderung des Agenten in Git committet.
So funktioniert es
Beim Start einer Sitzung initialisiert Potato ein Git-Repository im Sandbox-Workspace oder nutzt das bereits vorhandene. Nach jeder Dateiänderung committet es automatisch mit einer strukturierten Nachricht:
[potato-checkpoint] Step 7: Edit src/parser.py
- Modified lines 45-52
- Agent reasoning: Fix the regex pattern to handle escaped quotes
Daraus entsteht eine lineare Commit-Historie, die eins zu eins den Schritten der Trajektorie entspricht. Jeder Checkpoint hält den vollständigen Zustand des Workspace zu diesem Zeitpunkt fest.
# You can inspect checkpoints directly with git
cd workspace/
git log --oneline
# Output:
# f8a2c1d [potato-checkpoint] Step 12: Edit tests/test_parser.py
# 3b7e9f0 [potato-checkpoint] Step 10: Edit src/parser.py
# a1c4d8e [potato-checkpoint] Step 8: Edit src/parser.py
# 9e2f6b3 [potato-checkpoint] Step 5: Edit src/config.py
# 7d0a3c1 [potato-checkpoint] Step 0: Initial stateRollback
Auf „Rollback“ klicken und einen beliebigen früheren Checkpoint aus dem Dropdown wählen. Potato setzt den Workspace per git checkout auf diesen Zustand zurück und spult die Trajektorienanzeige passend zurück, danach macht der Agent von dort aus weiter, mit einem auf diesen Schritt gekürzten Kontext.
Das bietet sich an, wenn man sieht, wie der Agent falsch abbiegt. Statt ihn laufen und Zeit verbrennen zu lassen, spult man auf den letzten guten Zustand zurück und lässt ihn es erneut versuchen, vielleicht mit einer Anweisung, die ihn in eine bessere Richtung lenkt.
Verzweigte Trajektorien
Verzweigung ist Rollback, bei dem beide Pfade erhalten bleiben. Setzt man zurück und der Agent geht einen anderen Weg, legt Potato einen benannten Git-Branch an und verfolgt beide Trajektorien:
Step 0 → Step 1 → Step 2 → Step 3 → Step 4 (Branch A: original path)
↘
Step 3' → Step 4' → Step 5' (Branch B: after rollback)
Verzweigen lässt sich von jedem Checkpoint aus, sodass ein ganzer Baum von Trajektorien entsteht. Das ist fürs Präferenzlernen nützlich, denn jedes Branch-Paar ist bereits ein gelabelter Vergleich. Man hat zurückgesetzt, weil man Branch A als falsch beurteilt hat, und damit ist Branch B ab dem Verzweigungspunkt der bevorzugte Pfad.
Auch das Verzweigen braucht keine Konfiguration. Potato legt den Branch an, wenn man zurücksetzt und der Agent danach einen anderen Weg nimmt, und verfolgt beide Trajektorien für den Rest der Sitzung.
Exportformate
Eine Live-Sitzung liefert detaillierte Trajektoriendaten, die sich je nach Trainingsziel in verschiedenen Formen exportieren lassen.
Export linearer Trajektorien
Jeden Branch als eigenständige Trajektorie exportieren:
python -m potato.export \
-c config.yaml \
-f trajectory_correction \
-o ./training_data/{
"session_id": "session_001",
"branch": "branch-A",
"task": "Fix the failing test in tests/test_parser.py",
"steps": [
{"step_idx": 0, "type": "file_read", "path": "tests/test_parser.py", "...": "..."},
{"step_idx": 1, "type": "thinking", "content": "The test expects..."},
{"step_idx": 2, "type": "file_edit", "path": "src/parser.py", "diff": "..."},
{"step_idx": 3, "type": "bash_command", "command": "pytest tests/test_parser.py"}
],
"human_interventions": [
{"after_step": 2, "type": "instruction", "content": "Use a migration instead"}
],
"rollback_from_step": null,
"outcome": "resolved"
}Präferenzpaare aus Branches
Branch-Paare als Präferenzdaten für DPO oder RLHF exportieren:
Derselbe Exporter schreibt auch diese. Im Ausgabeverzeichnis enthält trajectory_dpo.jsonl die Branch-Vergleiche als Präferenzpaare, daneben liegen trajectory_sft.jsonl und trajectory_corrections.json.
python -m potato.export \
-c config.yaml \
-f trajectory_correction \
-o ./training_data/{
"session_id": "session_001",
"task": "Fix the failing test in tests/test_parser.py",
"branch_point_step": 2,
"branch_point_reason": "Agent started modifying the wrong file",
"rejected_branch": "branch-A",
"rejected_steps": [
{"step_idx": 3, "type": "file_edit", "path": "src/wrong_file.py", "...": "..."},
{"step_idx": 4, "type": "bash_command", "command": "pytest", "exit_code": 1}
],
"chosen_branch": "branch-B",
"chosen_steps": [
{"step_idx": 3, "type": "file_edit", "path": "src/parser.py", "...": "..."},
{"step_idx": 4, "type": "bash_command", "command": "pytest", "exit_code": 0}
]
}PRM-Labels aus der Live-Beobachtung
Live-Beobachtung lässt sich mit PRM-Labeling koppeln, denn der Punkt, an dem zurückgesetzt wurde, ist meist der Schritt mit dem ersten Fehler:
python -m potato.export \
-c config.yaml \
-f coding_eval \
-o ./training_data/ \
--option types=prmDer Schritt, von dem aus zurückgesetzt wurde, wird hier als erster Fehler gelabelt, und die Schritte des neuen Branch als korrekt, weil man sie akzeptiert hat.
Datensätze für Code-Review
Anweisungen der Annotatoren und Rollback-Begründungen als Trainingsdaten für Code-Review exportieren:
python -m potato.export \
-c config.yaml \
-f coding_eval \
-o ./training_data/ \
--option types=code_reviewVollständiger Schnelleinstieg
Der komplette Ablauf, von null bis zur laufenden Ollama-Sitzung:
# 1. Install Potato with live agent support
pip install potato-annotation[live-agents]
# 2. Install and start Ollama
curl -fsSL https://ollama.ai/install.sh | sh
ollama pull qwen2.5-coder:32b
# 3. Set up a workspace with a repo to work on
mkdir -p workspace/
git clone https://github.com/example/test-project workspace/repo
# 4. Create the config file
cat > config.yaml << 'YAML'
annotation_task_name: "Live Agent Observation"
port: 8000
live_coding_agent:
backend_type: ollama_tool_use
ai_config:
model: "qwen2.5-coder:32b"
base_url: "http://localhost:11434"
temperature: 0.2
working_dir: ./workspace/repo
max_turns: 50
sandbox_mode: trusted
annotation_schemes:
- annotation_type: radio
name: outcome
description: "Final outcome"
labels:
- name: "resolved"
text: "Task Fully Resolved"
- name: "partial"
text: "Partially Resolved"
- name: "failed"
text: "Failed"
- annotation_type: text
name: notes
description: "Session Notes"
placeholder: "Key observations about agent behavior..."
label_requirement:
required: false
output_annotation_dir: "./output/"
export_annotation_format: jsonl
user_config:
allow_all_users: false
users:
- "observer1"
YAML
# 5. Start Potato
potato start config.yaml -p 8000
# 6. Open http://localhost:8000 in your browserNach dem Login eine Aufgabe wie „Füge dem POST-Endpunkt /api/users eine Eingabevalidierung hinzu“ einfügen und auf „Start Agent“ klicken. Dem Agenten zusehen, pausieren, wenn etwas seltsam aussieht, mit Anweisungen nachsteuern und zurücksetzen, um andere Ansätze auszuprobieren. Am Ende das Ergebnis bewerten und Notizen festhalten.
Bewährte Vorgehensweisen
Mit klar umrissenen Aufgaben anfangen. Am besten funktioniert Arbeit, für die der Agent 5 bis 15 Minuten braucht. Alles darunter liefert zu wenig Trajektorie, um die Annotation zu lohnen. Alles deutlich darüber ermüdet den Annotator.
Im Produktivbetrieb die Sandbox eingeschaltet lassen. sandbox_mode: container ist die Voreinstellung und hält den Agenten vom Host fern. bubblewrap ist die leichtere Alternative unter Linux. trusted führt die Tool-Aufrufe des Agenten direkt auf der Maschine aus, was nur vertretbar ist, solange man mit einem vertrauenswürdigen Modell entwickelt.
Festhalten, warum zurückgesetzt wurde. Die Konfiguration erzwingt das nicht, also sollte es eine Regel für die Annotatoren sein, an jedem Verzweigungspunkt kurz zu notieren, was schiefgelaufen ist. Diese Notizen sind für sich genommen brauchbares Trainingssignal und machen die Präferenzdaten besser.
Mehrere Backends vergleichen. Dieselben Aufgaben durch Ollama, die Anthropic API und das Claude Agent SDK schicken, um agentenübergreifende Präferenzdaten zu bekommen. Da sich nur der Backend-Abschnitt der Konfiguration ändert, ist das schnell aufgesetzt.
Früh und oft exportieren. Nach jeder Sitzung exportieren, statt alles bis zum Schluss aufzuheben. Bei einem Absturz geht weniger verloren, und die Datenqualität lässt sich laufend im Blick behalten.