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.
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:
Observaçã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:
# 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 listConfigure o Potato para usar o backend Ollama:
# 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.
# 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 (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.
# 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: 100O 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."
# Start the server
potato start config.yaml -p 8000O 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:
Interface de anotação PRM para rotulagem de correção em nível de passo junto com o trace de código
# 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:
[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.
# 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
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:
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.
# 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 outcomesFormatos 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:
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"
}Pares de preferência a partir de branches
Exporte pares de branches como dados de preferência para DPO ou RLHF:
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}
]
}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:
potato export \
--format prm_from_branches \
--project ./output/ \
--output ./training_data/prm_live.jsonlAqui 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:
potato export \
--format code_review \
--project ./output/ \
--output ./training_data/code_review.jsonlQuick start completo
A sequência inteira, do nada a uma sessão Ollama rodando:
# 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 browserApó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.