Skip to content
Tutorials6 min read

見る・止める・巻き戻す:Potatoのライブコーディングエージェント観察

Ollama、Anthropic API、Claude Agent SDKでライブコーディングエージェント観察を構築するチュートリアルです。一時停止、ロールバック、分岐、トラジェクトリのエクスポートまで扱います。

Potato Team

ライブ観察は何が違うのか

コーディングエージェントの評価はたいてい事後に行われます。エージェントを走らせ、トレースを出力し、レビュアーが後から録画を見返す形です。ライブ観察は順序が逆になります。アノテーターはエージェントの作業をリアルタイムで見守り、ファイルの編集、ターミナルコマンド、推論ステップを起きた瞬間に確認します。

これでできることが変わります。エージェントが誤った方向に進み始めたら、時間を無駄にする前にアノテーターが割り込めます。エージェントが次に進む前に一時停止してdiffをじっくり読むこともできますし、平易な言葉で指示を送って進路を変えることもできます。私が一番役に立つと思っているのはロールバックです。過去の任意のチェックポイントまで巻き戻して、エージェントに別のアプローチを試させられます。こうして生まれる分岐は、まさに選好学習が欲しがるデータです。

これは静的なトレースアノテーションの代わりではありません。別の種類のデータを生む別のモードです。予測可能なコストで量を集めたいなら静的アノテーションが向いています。狙いを絞ったデータが欲しいとき、エージェントの失敗の仕方を理解したいとき、分岐から選好ペアを作りたいときはライブ観察が向いています。

機能の完全なリファレンスはソースドキュメントを参照してください。

ライブコーディングエージェントのインターフェースはエージェントのアクションをリアルタイムでストリーミングし、作業中のコードdiffとターミナル出力を表示します。

リアルタイムのコードdiffとターミナル出力を表示するライブコーディングエージェントのインターフェースリアルタイムのdiff描画とターミナル出力を備えたライブコーディングエージェント観察

3つのバックエンド

Potatoはライブ観察のために3つのバックエンドを用意しています。いずれもコーディングエージェントをサンドボックス内で実行し、そのアクションを発生と同時にインターフェースへストリーミングします。

Ollama(完全ローカル)

Ollamaバックエンドは、APIキーもネットワーク通信もなしに、すべてを手元のマシンで実行します。コードベースが機微な場合や、API料金をかけずに試したい場合に選んでください。

まずOllamaをインストールし、ツール使用に対応したモデルを取得します。

bash
# 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 list

PotatoがOllamaバックエンドを使うように設定します。

yaml
# 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)

Anthropic APIバックエンドは、ツール使用に対応したClaudeモデルに接続します。ほとんどのローカルモデルより推論とコード生成が強く、その代わりAPI呼び出しの費用がかかります。

bash
# Set your API key
export ANTHROPIC_API_KEY="sk-ant-..."
yaml
# 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: true

Claude Agent SDK(Claude Codeの全機能)

Claude Agent SDKバックエンドは3つの中で最も高機能で、Claude Codeのツール一式と自律的な挙動をそのまま使えます。claude-agent-sdkパッケージが必要です。

bash
# Install the Claude Agent SDK
pip install claude-agent-sdk
yaml
# 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: 100

アノテーションの流れ

サーバーが立ち上がったら、ライブ観察のセッションはいくつかの段階を通ります。

セッションを始める

アノテーターがPotatoのインターフェースを開くと、タスク説明の入力欄が表示されます。エージェントにやらせたいタスクを貼り付けるか入力します。たとえば「新しい設定形式が原因で失敗しているtests/test_parser.pyのテストを直す」や「/api/usersエンドポイントにページネーションを追加する」などです。

bash
# Start the server
potato start config.yaml -p 8000

アノテーターが「Start Agent」をクリックすると、コーディングエージェントが作業を始めます。各アクションはCodingTraceDisplayパネルにリアルタイムで表示されます。

エージェントの作業を見守る

エージェントが動いている間、各ステップがトレースビューアに現れます。

  • 思考ステップは、エージェントの推論を示す折りたたみ可能なグレーのブロックとして表示されます。
  • ファイルの読み取りは、行番号とファイルパス付きのシンタックスハイライトされたコードブロックとして表示されます。
  • ファイルの編集は、赤と緑でハイライトされた統一diffとして表示されます。
  • ターミナルコマンドは、コマンド、出力、終了コードを含む暗色のターミナルブロックとして表示されます。
  • ファイルツリーは、ファイルが作成・変更・読み取りされるたびにサイドバーで更新されます。

上部の進捗表示には、現在のステップ番号と経過時間が出ます。エージェントの状態は「Thinking...」「Editing file...」「Running command...」のように表示されます。

一時停止と指示のコントロール

エージェントの実行中、アノテーターはコントロールバーから介入できます。

Pause:現在のステップが完了した時点でエージェントを止めます。再開するまで次のステップには進みません。エージェントが先に進む前にdiffやターミナル出力をじっくり確認したいときに使います。

Send Instruction:一時停止中(あるいは実行中でも)に、自然言語のメッセージを入力してエージェントのコンテキストに挿入します。たとえば「データベーススキーマは変更せず、マイグレーションを使ってください」や「変更する前に/var/log/app.logのエラーログを確認してください」といった具合です。

Resume:一時停止したエージェントの実行を再開します。

Stop:エージェントのセッションを完全に終了します。そこまでのトラジェクトリは保存されます。

アノテーターは、トレース表示と並べてPRMアノテーションでエージェントの作業を評価できます。

コーディングエージェントのトレースと並べたプロセス報酬アノテーションコーディングトレースと並べてステップ単位の正確性をラベル付けするPRMアノテーションインターフェース

yaml
# 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"

Gitベースのチェックポイントシステム

残りの仕組みを成り立たせているのがチェックポイントシステムです。ロールバック、分岐、トラジェクトリのエクスポートはすべてこれに依存していて、エージェントがファイルを変更するたびにgitへコミットすることで役目を果たしています。

仕組み

セッションが始まると、Potatoはサンドボックスのワークスペースにgitリポジトリを初期化します。既にある場合はそれを使います。ファイルを編集するたびに、構造化されたメッセージを付けて自動でコミットします。

text
[potato-checkpoint] Step 7: Edit src/parser.py
- Modified lines 45-52
- Agent reasoning: Fix the regex pattern to handle escaped quotes

結果として、トラジェクトリのステップと1対1で対応する直線的なコミット履歴ができます。各チェックポイントは、その時点のワークスペースの状態を丸ごと記録しています。

bash
# 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 state

ロールバック

「Rollback」をクリックし、ドロップダウンから過去のチェックポイントを選びます。Potatoはgit checkoutでワークスペースをその状態に戻し、トラジェクトリの表示も合わせて巻き戻します。エージェントはコンテキストをそのステップまで切り詰めた状態で、そこから再開します。

エージェントが誤った方向に進んだのを見たときに使う手です。そのまま走らせて時間を溶かす代わりに、最後に良かった状態まで巻き戻し、必要なら別の方向を促す指示を添えて再挑戦させます。

トラジェクトリの分岐

分岐は、両方の経路を残すロールバックです。巻き戻したあとエージェントが別の道を進むと、Potatoは名前付きのgitブランチを作り、両方のトラジェクトリを追跡します。

text
Step 0 → Step 1 → Step 2 → Step 3 → Step 4 (Branch A: original path)
                          ↘
                           Step 3' → Step 4' → Step 5' (Branch B: after rollback)

任意のチェックポイントから分岐でき、トラジェクトリの木を丸ごと組み上げられます。選好学習にとってこれは貴重です。分岐のペアはそれ自体が既にラベル付きの比較になっているからです。Branch Aが誤りだと判断したからこそ巻き戻したわけで、分岐点から先はBranch Bが選好された経路になります。

yaml
# 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 outcomes

エクスポート形式

ライブセッションは詳細なトラジェクトリデータを生成します。何を訓練したいかに応じて、いくつかの形でエクスポートできます。

直線的なトラジェクトリのエクスポート

各分岐を独立したトラジェクトリとしてエクスポートします。

bash
potato export \
  --format trajectories \
  --project ./output/ \
  --output ./training_data/trajectories.jsonl \
  --flatten_branches true
json
{
  "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"
}

分岐からの選好ペア

分岐のペアを、DPOやRLHF用の選好データとしてエクスポートします。

bash
potato export \
  --format branch_preferences \
  --project ./output/ \
  --output ./training_data/branch_preferences.jsonl
json
{
  "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ラベル

ロールバックした地点はたいてい最初のエラーのステップなので、ライブ観察とPRMラベリングを組み合わせられます。

bash
potato export \
  --format prm_from_branches \
  --project ./output/ \
  --output ./training_data/prm_live.jsonl

ここでは、ロールバックの起点になったステップが最初のエラーとしてラベル付けされ、新しい分岐のステップは受け入れたものなので正しいとラベル付けされます。

コードレビューのデータセット

アノテーターの指示とロールバックの理由を、コードレビューの訓練データとしてエクスポートします。

bash
potato export \
  --format code_review \
  --project ./output/ \
  --output ./training_data/code_review.jsonl

通しのクイックスタート

何もない状態からOllamaのセッションを動かすまでの全手順です。

bash
# 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 browser

ログイン後、「/api/usersのPOSTエンドポイントに入力バリデーションを追加する」のようなタスクを貼り付けて「Start Agent」をクリックします。作業を見守り、おかしいと思ったら一時停止し、指示を送って方向を修正し、ロールバックして別のアプローチを試してください。終わったら結果を評価し、メモを残します。

実践上のコツ

明確で範囲の定まったタスクから始める。 ちょうどよいのは、エージェントが5〜15分で終える程度の作業です。これより短いとアノテーションに値するだけのトラジェクトリが出ませんし、大幅に長いとアノテーターが疲弊します。

本番ではDockerサンドボックスを使う。 開発中はローカルのサンドボックスモードで構いませんが、Dockerを使えばエージェントがホストシステムに触れられなくなります。信頼できないモデルを扱うときは必ず使ってください。

ロールバックの理由を記録する。 require_reason_on_rollbackを有効にすると、分岐点ごとに何がまずかったかの人手によるメモが残ります。このメモ自体が有用な訓練シグナルになりますし、選好データの質も上がります。

複数のバックエンドを比較する。 同じタスクをOllama、Anthropic API、Claude Agent SDKで回すと、エージェント横断の選好データが得られます。設定はバックエンドの部分だけを変えればよいので、準備は簡単です。

こまめにエクスポートする。 最後にまとめてではなく、セッションごとにエクスポートを走らせてください。何かが落ちたときの損失が小さくなりますし、進めながらデータの品質を確認できます。