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 Evaluation von Coding-Agenten passiert meist im Nachhinein: Der Agent läuft, erzeugt einen Trace, und Reviewer nehmen die Aufzeichnung später auseinander. Die Live-Beobachtung dreht das um. Der Annotator sieht dem Agenten in Echtzeit bei der Arbeit zu und bekommt jede Dateiänderung, jedes Terminalkommando und jeden Denkschritt mit, während sie passieren.
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. Genau solche Branches sind das, was Präferenzlernen braucht.
Das ersetzt die Annotation statischer Traces nicht. Es ist ein anderer Modus, der eine andere Art von Daten liefert. 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 bauen möchte.
Die vollständige Feature-Referenz steht in der Quelldokumentation.
Die Oberfläche für Live-Coding-Agenten streamt die Aktionen des Agenten 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. Passend, 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
project_name: "Live Agent Observation - Ollama"
port: 8000
live_coding_agent:
enabled: true
backend: "ollama"
ollama:
model: "qwen2.5-coder:32b"
host: "http://localhost:11434"
temperature: 0.2
max_tokens: 4096
num_ctx: 32768 # Context window size
sandbox:
type: "docker" # "docker" or "local"
image: "python:3.11-slim" # Base image for sandboxed execution
workspace: "./workspace/" # Agent's working directory
timeout: 600 # Max seconds per agent session
streaming:
update_interval_ms: 100 # How often to push updates to the UI
buffer_output: true # Buffer terminal output for smoother rendering
checkpoints:
enabled: true
strategy: "git" # Git-based checkpoints
auto_commit_on_file_change: true
commit_message_prefix: "[potato-checkpoint]"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
project_name: "Live Agent Observation - Claude"
port: 8000
live_coding_agent:
enabled: true
backend: "anthropic"
anthropic:
model: "claude-sonnet-4-20250514"
api_key_env: "ANTHROPIC_API_KEY"
max_tokens: 8192
temperature: 0.1
tools:
- "file_read"
- "file_edit"
- "bash_command"
- "directory_list"
- "file_search"
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.
sandbox:
type: "docker"
image: "python:3.11-slim"
workspace: "./workspace/"
timeout: 900
allowed_commands: # Whitelist for bash commands
- "python"
- "pip"
- "pytest"
- "git"
- "ls"
- "cat"
- "find"
- "grep"
streaming:
update_interval_ms: 50
show_thinking: true # Show Claude's thinking in real time
checkpoints:
enabled: true
strategy: "git"
auto_commit_on_file_change: trueClaude 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
project_name: "Live Agent Observation - Claude Agent SDK"
port: 8000
live_coding_agent:
enabled: true
backend: "claude_agent_sdk"
claude_agent_sdk:
api_key_env: "ANTHROPIC_API_KEY"
model: "claude-sonnet-4-20250514"
max_turns: 50 # Maximum number of agent turns
permission_mode: "auto" # "auto", "ask", or "restricted"
allowed_tools:
- "Read"
- "Edit"
- "Write"
- "Bash"
- "Glob"
- "Grep"
restricted_commands: # Bash commands to block
- "rm -rf /"
- "sudo"
- "curl"
- "wget"
sandbox:
type: "docker"
image: "node:20-slim"
workspace: "./workspace/"
timeout: 1200
mount_volumes:
- "./test-repo:/workspace/repo"
streaming:
update_interval_ms: 50
show_thinking: true
show_tool_inputs: true
checkpoints:
enabled: true
strategy: "git"
auto_commit_on_file_change: true
max_checkpoints: 100Der 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, etwa „Fix the failing test in tests/test_parser.py caused by the new config format" oder „Add pagination support to the /api/users endpoint".
# 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 weiter, wenn fortgesetzt wird. Damit lässt sich ein Diff oder eine Terminalausgabe in Ruhe prüfen, bevor der Agent weitermacht.
Anweisung senden: Im pausierten Zustand (oder auch während der Agent läuft) eine Nachricht in natürlicher Sprache eintippen, die in den Kontext des Agenten eingefügt wird. Zum Beispiel: „Don't modify the database schema, use a migration instead" oder „Check the error log at /var/log/app.log before making changes".
Fortsetzen: Setzt die Ausführung nach einer Pause fort.
Stopp: 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
# Control bar configuration
live_coding_agent:
controls:
pause_enabled: true
instruction_enabled: true
stop_enabled: true
rollback_enabled: true
branch_enabled: true
pause_keyboard_shortcut: "Space"
instruction_keyboard_shortcut: "i"Das Git-basierte Checkpoint-System
Das Checkpoint-System ist die Grundlage für alles Weitere. Rollback, Verzweigung und der Export der Trajektorien hängen daran, und es erledigt seine Aufgabe, indem es 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 sich eins zu eins auf die Schritte der Trajektorie abbilden lässt. 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
Ein Klick auf „Rollback", dann 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 auf diesen Schritt gekürztem Kontext.
Das ist der richtige Zug, 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 erneut versuchen, vielleicht mit einer Anweisung, die ihn in eine bessere Richtung schiebt.
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. Fürs Präferenzlernen ist das viel wert, denn jedes Branch-Paar ist bereits ein gelabelter Vergleich: Man hat genau deshalb zurückgesetzt, weil man Branch A als falsch beurteilt hat, womit Branch B ab dem Verzweigungspunkt der bevorzugte Pfad ist.
# Branching configuration
live_coding_agent:
branching:
enabled: true
max_branches_per_session: 10
auto_name_branches: true # "branch-A", "branch-B", etc.
require_reason_on_rollback: true # Annotator must explain why they rolled back
compare_branches_view: true # Side-by-side view of branch outcomesExportformate
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:
potato export \
--format trajectories \
--project ./output/ \
--output ./training_data/trajectories.jsonl \
--flatten_branches true{
"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:
potato export \
--format branch_preferences \
--project ./output/ \
--output ./training_data/branch_preferences.jsonl{
"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:
potato export \
--format prm_from_branches \
--project ./output/ \
--output ./training_data/prm_live.jsonlDer 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:
potato export \
--format code_review \
--project ./output/ \
--output ./training_data/code_review.jsonlVollstä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'
project_name: "Live Agent Observation"
port: 8000
live_coding_agent:
enabled: true
backend: "ollama"
ollama:
model: "qwen2.5-coder:32b"
host: "http://localhost:11434"
temperature: 0.2
num_ctx: 32768
sandbox:
type: "local"
workspace: "./workspace/repo"
timeout: 600
streaming:
update_interval_ms: 100
checkpoints:
enabled: true
strategy: "git"
auto_commit_on_file_change: true
controls:
pause_enabled: true
instruction_enabled: true
rollback_enabled: true
branch_enabled: true
branching:
enabled: true
max_branches_per_session: 5
require_reason_on_rollback: true
annotation_schemes:
- annotation_type: radio
name: outcome
label: "Final outcome"
options:
- value: "resolved"
text: "Task Fully Resolved"
- value: "partial"
text: "Partially Resolved"
- value: "failed"
text: "Failed"
- annotation_type: text_input
name: notes
label: "Session Notes"
placeholder: "Key observations about agent behavior..."
required: false
output:
path: "./output/"
format: "jsonl"
export_formats:
- "trajectories"
- "branch_preferences"
- "prm_from_branches"
annotators:
- username: "observer1"
password: "observer_pw_1"
YAML
# 5. Start Potato
potato start config.yaml -p 8000
# 6. Open http://localhost:8000 in your browserNach dem Login eine Aufgabe wie „Add input validation to the /api/users POST endpoint" 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 mit Docker-Sandbox arbeiten. Der lokale Sandbox-Modus reicht während der Entwicklung, aber Docker hält den Agenten vom Host-System fern. Bei nicht vertrauenswürdigen Modellen immer verwenden.
Rollback-Begründungen erfassen. require_reason_on_rollback einschalten, damit zu jedem Verzweigungspunkt eine menschliche Notiz gehört, 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.