Skip to content
Guides12 min read

Anotando agentes de navegação web: de traços do WebArena à avaliação humana

Como usar a exibição de traços de agentes web do Potato para avaliar agentes autônomos de navegação web, com capturas de tela passo a passo, sobreposições SVG e esquemas de anotação por etapa.

Potato Team

Converta o traço do agente para o formato de agente web do Potato, exiba-o com o visualizador web_agent_trace para que cada captura de tela traga uma sobreposição mostrando onde o agente clicou, e avalie as etapas com um esquema trajectory_eval.

Um agente de navegação web é julgado pelas ações que executa sobre uma página, então a avaliação precisa das duas metades de cada etapa, o estado da página que o agente viu e a ação que ele executou nela. Um log de ações sozinho não sustenta o julgamento. "Clicked element product-101" não diz ao revisor se aquele era o notebook mais barato da página, e uma captura de tela sem marcador o deixa adivinhando qual de uma dúzia de links era o alvo.

Este guia monta essa avaliação para traços do WebArena. O mesmo caminho funciona para VisualWebArena, Mind2Web, logs do Anthropic Computer Use e gravações brutas de navegador, já que um único conversor cobre todos eles. Para a referência completa de configuração, veja a documentação de origem.

O que você precisa

bash
pip install potato-annotation

Você também precisa dos próprios traços, que no WebArena são capturas de tela mais um log de ações em JSON por episódio. O VisualWebArena registra a mesma estrutura com informações extras de ancoragem visual, e as gravações brutas de navegador trazem, em vez disso, dados de viewport e do caminho do mouse.

O que um traço bruto do WebArena contém

Um episódio do WebArena traz a descrição da tarefa, a sequência de ações e o caminho de cada captura de tela:

json
{
  "trace_id": "wa_001",
  "task": "Find the cheapest laptop on the electronics store and add it to the cart",
  "website": "shopping",
  "steps": [
    {
      "step": 0,
      "url": "http://shop.example.com/",
      "action_type": "click",
      "action_target": "Electronics category link",
      "element_id": "nav-electronics",
      "coordinates": [245, 82],
      "screenshot": "screenshots/wa_001_step_00.png"
    },
    {
      "step": 1,
      "url": "http://shop.example.com/electronics",
      "action_type": "click",
      "action_target": "Laptops subcategory",
      "element_id": "cat-laptops",
      "coordinates": [180, 310],
      "screenshot": "screenshots/wa_001_step_01.png"
    }
  ],
  "success": true
}

Convertendo o traço

O visualizador do Potato lê um formato de etapas normalizado, e não o formato próprio de cada framework, então os episódios brutos passam primeiro pelo conversor:

bash
python -m potato.trace_converter -i traces.json -f web_agent -o data/web_traces.jsonl

Isso grava uma instância por episódio, e cada etapa traz step_index, screenshot_url, action_type, o element alvo e sua caixa delimitadora, coordinates, um mouse_path opcional, e o thought e a observation do agente quando o log de origem os registrou. Trocar -f web_agent por --auto-detect faz o conversor identificar o formato sozinho, e essa é a opção a usar quando um diretório contém traços de mais de um framework.

A configuração do projeto

O visualizador é um tipo de exibição, e não um tipo de anotação, então ele vai em instance_display.fields e os esquemas de anotação ficam separados dele. O tamanho da captura de tela é a configuração que vale decidir primeiro. Com 900 pixels de largura, uma página de desktop inteira continua legível sem empurrar os controles de anotação para fora da parte de baixo da tela.

yaml
annotation_task_name: "WebArena Agent Evaluation"
task_dir: "."
 
data_files:
  - "data/web_traces.jsonl"
 
item_properties:
  id_key: id
  text_key: task_description
 
output_annotation_dir: "output/"
export_annotation_format: "jsonl"
 
instance_display:
  layout:
    direction: vertical
    gap: 16px
  fields:
    - key: task_description
      type: text
      label: "Task"
 
    - key: steps
      type: web_agent_trace
      label: "Agent Browsing Trace"
      display_options:
        show_overlays: true
        show_filmstrip: true
        show_thought: true
        show_observation: true
        show_element_info: true
        screenshot_max_width: 900
        screenshot_max_height: 600
        filmstrip_size: 80
 
annotation_schemes:
  - annotation_type: radio
    name: task_success
    description: "Did the agent complete the task?"
    labels:
      - "Success"
      - "Partial success"
      - "Failure"
    label_requirement:
      required: true
 
  - annotation_type: radio
    name: task_efficiency
    description: "Was the agent's path to the goal efficient?"
    labels:
      - "Optimal path"
      - "Reasonable but not optimal"
      - "Inefficient, unnecessary steps"
      - "Completely wrong direction"
    label_requirement:
      required: true
 
  - annotation_type: trajectory_eval
    name: step_evaluation
    description: "Judge each action against the task"
    steps_key: steps
    step_text_key: action_type
    correctness_options:
      - correct
      - acceptable
      - incorrect
      - unnecessary
    error_types:
      - name: wrong_element_clicked
      - name: wrong_page_navigated_to
      - name: missed_better_option
      - name: incorrect_form_input
      - name: premature_completion
      - name: unnecessary_navigation
      - name: failed_to_scroll
      - name: wrong_page_section
      - name: other
    severities:
      - name: minor
        weight: -1
      - name: major
        weight: -5
      - name: critical
        weight: -10
    show_score: true
    max_score: 100
 
user_config:
  allow_all_users: true

Um único esquema trajectory_eval cobre toda a passagem por etapa. Ele exibe cada etapa como um cartão e coleta em cada uma a correção, um tipo de erro, uma gravidade e uma justificativa escrita, e depois calcula uma pontuação de qualidade do traço a partir dos pesos de gravidade. Com os pesos acima, um erro grave custa ao traço cinco pontos e um erro crítico custa dez. Defina esses pesos de propósito, porque eles decidem como um traço com uma falha séria se classifica em relação a um traço com quatro falhas pequenas.

O que o anotador vê

Visualizador de traços de agente web no Potato

A captura de tela da etapa atual ocupa o painel principal, com sobreposições SVG desenhadas por cima. Cada sobreposição marca uma parte diferente da etapa, e as cores são fixas:

SobreposiçãoMarca
Círculo vermelho com miraAs coordenadas do clique
Destaque amareloO campo em que o agente digitou
Seta verdeA direção e a magnitude de uma rolagem
Retângulo azul tracejadoA caixa delimitadora do elemento alvo
Linha curva laranjaO caminho do mouse até o alvo

Uma tira de filme com miniaturas corre ao longo da parte de baixo, e clicar em uma delas leva àquela etapa. Em traços com mais de umas dez etapas, a tira de filme é a diferença entre um revisor que enxerga a forma da execução e um que rola às cegas. O painel de detalhes da etapa mostra as informações do elemento, o raciocínio do próprio agente e a observação que ele registrou, e cada um deles pode ser desligado em display_options quando o log de origem não tem nada útil ali.

Uma fileira de caixas de seleção abaixo do visualizador liga e desliga as sobreposições:

ControleSobreposição
ClicksA mira vermelha do clique
Bounding BoxesO retângulo azul tracejado
Mouse PathA linha curva laranja
ScrollA seta verde de rolagem

Desligar sobreposições faz diferença em páginas densas, onde um marcador de clique pode ficar em cima justamente do texto que diz se o clique estava certo. Observe que o destaque amarelo de digitação não tem controle próprio. Quatro das cinco sobreposições podem ser ligadas e desligadas individualmente, e o destaque do campo digitado é sempre desenhado. Este visualizador não tem atalhos de teclado, então a navegação entre etapas é feita pela tira de filme e pelos controles de etapa.

A passagem de anotação

Um revisor trabalha um traço em cinco movimentos:

  1. Leia a descrição da tarefa. Tudo o que vem depois é um julgamento em relação a ela.
  2. Percorra a tira de filme. Entenda a forma da execução antes de avaliar qualquer coisa, para que uma etapa inicial não seja marcada como correta com base em evidências que só aparecem depois.
  3. Percorra as etapas. Em cada uma, leia o estado da página, confira a sobreposição para ver sobre o que o agente agiu e avalie a ação. Se estiver errada, escolha o tipo de erro e uma gravidade, e diga na justificativa o que o agente deveria ter feito.
  4. Avalie o traço. Julgue o sucesso geral e a eficiência depois de ver todas as etapas.
  5. Envie e siga para o próximo.

As quatro opções de correção dividem as etapas pela linha que importa para dados de treinamento. Ações corretas avançam em direção ao objetivo da forma esperada. Ações aceitáveis fazem progresso por um caminho mais lento, como navegar até uma página de categoria em vez de usar a caixa de busca. Ações incorretas são erros, como um elemento errado, uma página irrelevante ou um texto errado em um formulário. Ações desnecessárias nem ajudam nem atrapalham, como um clique seguido imediatamente de uma volta à página anterior, e vale separá-las dos erros porque um agente que vagueia é um problema diferente de um agente que erra.

A taxonomia de erros

São os tipos de erro que transformam uma pilha de traços com falha em algo sobre o qual quem desenvolve o agente pode agir, então as categorias devem corresponder a causas distinguíveis, e não a graus de erro:

Tipo de erroO que significaExemplo
Elemento errado clicadoO agente agiu sobre o elemento de interface erradoClicou em "Tablets" em vez de "Laptops"
Página errada acessadaO agente foi parar em um lugar irrelevanteNavegou para "About Us" em vez da listagem de produtos
Opção melhor ignoradaHavia uma ação melhor disponívelNavegou pelas categorias quando a caixa de busca estava ali
Entrada de formulário incorretaO agente digitou o texto erradoBuscou "labtop" em vez de "laptop"
Conclusão prematuraO agente declarou sucesso cedo demaisAdicionou o item errado ao carrinho e parou
Navegação desnecessáriaA etapa não contribui para o objetivoVisitou a página inicial entre duas páginas de categoria
Falha ao rolarO alvo estava abaixo do viewportO elemento nunca ficou visível e o agente nunca rolou
Seção errada da páginaPágina certa, área erradaClicou no cabeçalho em vez do conteúdo principal

Trabalhando traços difíceis

Em um traço com mais de quinze etapas, avaliar todas as etapas com a mesma profundidade gasta a maior parte do esforço nas etapas que obviamente estavam certas. Percorra a tira de filme em busca dos três padrões que indicam um problema e concentre o esforço ali. Os padrões são uma URL que muda inesperadamente, uma etapa em que o agente retrocede e uma sequência de capturas de tela quase idênticas, o que geralmente significa que o agente está preso em um loop.

Em um traço com falha, a primeira etapa incorreta é a anotação que precisa sair certa. Tudo o que vem depois acontece em um estado que o agente nunca deveria ter alcançado, então os erros posteriores descrevem as consequências, e não a causa.

Algumas ações não podem ser julgadas só pela captura de tela, geralmente quando vários elementos se sobrepõem no ponto do clique. As informações do elemento no painel da etapa trazem a tag, o texto e a caixa delimitadora do alvo, o que normalmente basta para resolver o que foi de fato clicado; show_element_info mantém esse painel visível.

VisualWebArena

Os traços do VisualWebArena passam pelo mesmo conversor, que reconhece os dois formatos pelos campos action_type e element nas etapas de ação. As informações de ancoragem que esses traços trazem aparecem como a sobreposição de caixa delimitadora, então uma passagem focada em ancoragem depende do que os anotadores mantêm na tela, e não de uma edição na configuração. Deixar Bounding Boxes marcado e desmarcar Clicks dá a visão que mostra se o agente mirou o elemento certo, e não apenas o pixel certo.

Lendo os resultados

Os erros de agentes web tendem a se concentrar em pontos específicos de um traço, e a taxa de erro por posição da etapa é o jeito mais rápido de ver onde. Cada anotação trajectory_eval guarda uma lista de registros por etapa, cada um com seu step_index e sua correctness:

python
import json
 
annotations = []
with open("output/exports/jsonl/annotations.jsonl") as f:
    for line in f:
        annotations.append(json.loads(line))
 
step_counts = {}
for ann in annotations:
    evaluation = ann["labels"].get("step_evaluation", {})
    for step in evaluation.get("steps", []):
        pos = step["step_index"]
        counts = step_counts.setdefault(pos, {})
        label = step.get("correctness", "unrated")
        counts[label] = counts.get(label, 0) + 1
 
print("Error rate by step position:")
for pos in sorted(step_counts):
    counts = step_counts[pos]
    total = sum(counts.values())
    errors = counts.get("incorrect", 0) + counts.get("unnecessary", 0)
    print(f"  Step {pos}: {errors / total:.1%} error rate ({total} observations)")

A distribuição dos tipos de erro responde à outra pergunta, que é o que o agente erra, e não quando:

python
error_counts = {}
for ann in annotations:
    evaluation = ann["labels"].get("step_evaluation", {})
    for step in evaluation.get("steps", []):
        error = step.get("error_type")
        if error:
            error_counts[error] = error_counts.get(error, 0) + 1
 
for error, count in sorted(error_counts.items(), key=lambda x: -x[1]):
    print(f"  {error}: {count}")

Escalando a avaliação

Para um resultado que você pretende publicar, um revisor por traço não basta, porque os julgamentos por etapa trazem exatamente o tipo de ambiguidade que as estatísticas de concordância existem para medir. Defina a meta de cobertura e a ordem de atribuição no nível superior da configuração:

yaml
num_annotators_per_item: 3
assignment_strategy: random

Depois compare os anotadores no rótulo do traço, que é onde uma discordância não tem ambiguidade. Exporte primeiro para Parquet, para que a comparação rode sobre colunas e não sobre JSON a ser analisado:

bash
python -m potato.export -c config.yaml -f parquet -o ./parquet_export/
python
from sklearn.metrics import cohen_kappa_score
import pandas as pd
 
df = pd.read_parquet("parquet_export/annotations.parquet")
success = df[df["schema_name"] == "task_success"]
pivot = success.pivot(index="instance_id", columns="annotator", values="value")
 
annotators = pivot.columns.tolist()
for i in range(len(annotators)):
    for j in range(i + 1, len(annotators)):
        pair = pivot[[annotators[i], annotators[j]]].dropna()
        kappa = cohen_kappa_score(pair[annotators[i]], pair[annotators[j]])
        print(f"Kappa ({annotators[i]} vs {annotators[j]}): {kappa:.3f}")

Em avaliações com centenas de traços, o Solo Mode coloca um modelo na mesma fila do revisor humano: o modelo propõe rótulos e o humano os corrige até que os dois concordem com frequência suficiente para o modelo terminar o restante:

yaml
solo_mode:
  enabled: true
  labeling_models:
    - endpoint_type: "anthropic"
      model: "claude-sonnet-4-20250514"
      api_key: "${ANTHROPIC_API_KEY}"
  thresholds:
    end_human_annotation_agreement: 0.90
    minimum_validation_sample: 50

A configuração que merece reflexão é o limiar de concordância, não a escolha do modelo. Em 0.90, o humano continua anotando até que nove em cada dez rótulos do modelo coincidam com os seus, medidos sobre pelo menos cinquenta comparações, e baixar esse valor troca qualidade dos rótulos por horas de revisão de um jeito difícil de detectar depois.

Leitura adicional