Skip to content
Tutorials13 min read

Observe, Pause e Retroceda: Observação ao Vivo de Agentes de Código no Potato

Tutorial para configurar a observação ao vivo de agentes de código com Ollama, API da Anthropic ou Claude Agent SDK. Inclui pausa, rollback, ramificação e exportação de trajetórias.

Potato Team

O que torna a observação ao vivo diferente

A maior parte da avaliação de agentes de código acontece depois do fato: o agente roda, produz um trace e os revisores analisam a gravação mais tarde. A observação ao vivo funciona ao contrário. O anotador acompanha o agente trabalhando em tempo real e vê cada edição de arquivo, comando de terminal e passo de raciocínio assim que acontece.

Isso muda o que você pode fazer. Se o agente começa a seguir por um caminho errado, o anotador pode intervir antes que ele desperdice tempo ali. Ele pode pausar para ler um diff com calma antes de o agente seguir adiante, ou enviar uma instrução em linguagem simples para redirecioná-lo. A parte que considero mais útil é o rollback: em qualquer checkpoint anterior, você pode retroceder e deixar o agente tentar uma abordagem diferente. Essas ramificações são exatamente o tipo de dado que o aprendizado por preferência quer.

Isto não substitui a anotação estática de traces. É um modo diferente que produz um tipo diferente de dado. A anotação estática vence quando você quer muito dado a um custo previsível. A observação ao vivo vence quando você busca dados específicos, tenta entender como um agente falha ou constrói pares de preferência ramificados.

Para a referência completa do recurso, veja a documentação de origem.

A interface de agente de código ao vivo transmite as ações do agente em tempo real, mostrando diffs de código e a saída do terminal enquanto o agente trabalha:

Interface de agente de código ao vivo mostrando diffs de código e saída do terminal em tempo realObservação ao vivo de agente de código com renderização de diff em tempo real e saída do terminal

Três backends

O Potato oferece três backends para observação ao vivo. Cada um executa um agente de código em um sandbox e transmite suas ações para a interface conforme elas acontecem.

Ollama (totalmente local)

O backend Ollama roda inteiramente na sua máquina, sem chaves de API e sem chamadas de rede. Recorra a ele quando a base de código for sensível ou quando você apenas quiser experimentar sem acumular uma conta de API.

Primeiro, instale o Ollama e baixe um modelo com capacidade de uso de ferramentas:

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

Configure o Potato para usar o backend 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]"

API da Anthropic (Claude com uso de ferramentas)

O backend da API da Anthropic conecta-se aos modelos Claude com uso de ferramentas. Você obtém um raciocínio e uma geração de código mais fortes do que a maioria dos modelos locais oferece e, em troca, paga pelas chamadas de 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 (capacidades completas do Claude Code)

O backend do Claude Agent SDK é o mais capaz dos três, com o conjunto completo de ferramentas do Claude Code e comportamento autônomo. Ele requer o pacote 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

O fluxo de trabalho de anotação

Assim que o servidor está no ar, uma sessão de observação ao vivo passa por alguns estágios.

Iniciando uma sessão

O anotador abre a interface do Potato e vê um campo de entrada para a descrição da tarefa. Ele cola ou digita a tarefa que o agente deve concluir, como "Corrigir o teste que falha em tests/test_parser.py causado pelo novo formato de configuração" ou "Adicionar suporte a paginação ao endpoint /api/users."

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

O anotador clica em "Start Agent" e o agente de código começa a trabalhar. Cada ação aparece em tempo real no painel CodingTraceDisplay.

Acompanhando o agente trabalhar

Conforme o agente roda, cada passo aparece no visualizador de trace:

  • Passos de raciocínio aparecem como blocos cinzas recolhíveis mostrando o raciocínio do agente.
  • Leituras de arquivo aparecem como blocos de código com realce de sintaxe, números de linha e o caminho do arquivo.
  • Edições de arquivo aparecem como diffs unificados com realce em vermelho/verde.
  • Comandos de terminal aparecem como blocos de terminal escuros com o comando, a saída e o código de saída.
  • Árvore de arquivos atualiza na barra lateral conforme os arquivos são criados, modificados ou lidos.

Um indicador de progresso no topo mostra o número do passo atual e o tempo decorrido. O status do agente é exibido como "Thinking...", "Editing file...", "Running command...", etc.

Controles de pausa e instrução

Enquanto o agente está rodando, o anotador pode intervir pela barra de controle:

Pause: Congela o agente após o passo atual ser concluído. O agente não avança para o próximo passo até ser retomado. Use isto para examinar com cuidado um diff ou a saída do terminal antes de o agente seguir adiante.

Send Instruction: Enquanto pausado (ou mesmo enquanto roda), digite uma mensagem em linguagem natural que é injetada no contexto do agente. Por exemplo: "Don't modify the database schema, use a migration instead" ou "Check the error log at /var/log/app.log before making changes."

Resume: Continua a execução do agente após uma pausa.

Stop: Encerra a sessão do agente por completo. A trajetória até este ponto é salva.

Os anotadores podem avaliar o trabalho do agente usando anotação PRM junto com a exibição do trace:

Anotação de recompensa de processo junto com o trace do agente de códigoInterface de anotação PRM para rotulagem de correção em nível de passo junto com o trace de código

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"

Sistema de checkpoints baseado em git

O sistema de checkpoints é o que faz o resto disto funcionar. Rollback, ramificação e exportação de trajetórias dependem todos dele, e ele faz seu trabalho commitando no git após cada mudança de arquivo que o agente faz.

Como funciona

Quando uma sessão começa, o Potato inicializa um repositório git no workspace do sandbox, ou usa o que já está lá. Após cada edição de arquivo, ele commita automaticamente com uma mensagem estruturada:

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

O resultado é um histórico de commits linear que se alinha um a um com os passos da trajetória. Cada checkpoint captura o estado completo do workspace naquele momento.

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

Clique em "Rollback" e escolha qualquer checkpoint anterior no menu suspenso. O Potato reseta o workspace para aquele estado com git checkout e retrocede a exibição da trajetória para corresponder, então o agente retoma a partir dali com seu contexto cortado de volta àquele passo.

Este é o movimento para quando você vê o agente tomar um caminho errado. Em vez de deixá-lo rodar e queimar tempo, você retrocede para o último bom estado e o deixa tentar de novo, talvez com uma instrução empurrando-o para um lugar melhor.

Trajetórias ramificadas

A ramificação é um rollback que mantém ambos os caminhos. Quando você retrocede e o agente segue por outro caminho, o Potato cria um branch git nomeado e rastreia ambas as trajetórias:

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)

Você pode ramificar a partir de qualquer checkpoint, construindo uma árvore inteira de trajetórias. Para o aprendizado por preferência isto é ouro, porque cada par de branches já é uma comparação rotulada: você retrocedeu justamente porque julgou o Branch A errado, o que torna o Branch B o caminho preferido a partir do ponto de ramificação em diante.

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

Formatos de exportação

Uma sessão ao vivo produz dados detalhados de trajetória, e você pode exportá-los em alguns formatos dependendo do que você está treinando.

Exportação de trajetória linear

Exporte cada branch como uma trajetória independente:

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"
}

Pares de preferência a partir de branches

Exporte pares de branches como dados de preferência para DPO ou 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}
  ]
}

Rótulos PRM a partir de observação ao vivo

Você pode combinar a observação ao vivo com rotulagem PRM, já que um ponto de rollback costuma ser o passo do primeiro erro:

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

Aqui o passo do qual você retrocedeu é rotulado como o primeiro erro, e os passos do novo branch são rotulados como corretos, já que você os aceitou.

Conjuntos de dados de revisão de código

Exporte as instruções do anotador e os motivos de rollback como dados de treinamento para revisão de código:

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

Quick start completo

A sequência inteira, do nada a uma sessão Ollama rodando:

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

Após fazer login, cole uma tarefa como "Add input validation to the /api/users POST endpoint" e clique em "Start Agent." Acompanhe-o trabalhar, pause quando algo parecer errado, envie instruções para guiá-lo e retroceda para tentar outras abordagens. Quando terminar, avalie o resultado e anote suas observações.

Boas práticas

Comece com tarefas claras e delimitadas. O ponto ideal é um trabalho que leva de 5 a 15 minutos para o agente. Algo mais curto não produz trajetória suficiente para valer a anotação; algo muito mais longo cansa o anotador.

Use o sandbox Docker em produção. O modo de sandbox local serve enquanto você está desenvolvendo, mas o Docker impede o agente de tocar no seu sistema host. Sempre use-o com modelos não confiáveis.

Registre os motivos de rollback. Ative require_reason_on_rollback para que cada ponto de ramificação venha com uma nota humana sobre o que deu errado. Essas notas são um sinal de treinamento útil por si só, e tornam os dados de preferência melhores.

Compare múltiplos backends. Rode as mesmas tarefas pelo Ollama, pela API da Anthropic e pelo Claude Agent SDK para obter dados de preferência entre agentes. Como apenas a seção do backend na configuração muda, é fácil de montar.

Exporte cedo e com frequência. Rode uma exportação após cada sessão em vez de guardar tudo para o final. Você perde menos se algo travar, e pode acompanhar a qualidade dos dados conforme avança.