Skip to content
Guías13 min de lectura

Anotación de agentes de navegación web: de las trazas de WebArena a la evaluación humana

Cómo usar la visualización de trazas de agentes web de Potato para evaluar agentes autónomos de navegación web, con capturas paso a paso, superposiciones SVG y esquemas de anotación por paso.

Potato Team

Convierte la traza del agente al formato de agente web de Potato, muéstrala con el visor web_agent_trace para que cada captura lleve una superposición que indique dónde hizo clic el agente, y califica los pasos con un esquema trajectory_eval.

Un agente de navegación web se juzga por las acciones que realiza sobre una página, así que la evaluación necesita las dos mitades de cada paso: el estado de la página que vio el agente y la acción que realizó sobre ella. Un registro de acciones por sí solo no basta para juzgar. "Clicked element product-101" no le dice al revisor si ese era el portátil más barato de la página, y una captura sin marcador lo deja adivinando cuál de una docena de enlaces era el objetivo.

Esta guía monta esa evaluación para trazas de WebArena. El mismo camino sirve para VisualWebArena, Mind2Web, los registros de Anthropic Computer Use y las grabaciones de navegador sin procesar, porque un único conversor los cubre todos. Para la referencia completa de configuración, consulta la documentación fuente.

Qué necesitas

bash
pip install potato-annotation

También necesitas las propias trazas, que en WebArena son capturas de pantalla más un registro de acciones en JSON por episodio. VisualWebArena registra la misma estructura con información adicional de anclaje visual, y las grabaciones de navegador sin procesar llevan en su lugar datos del viewport y de la trayectoria del ratón.

Qué contiene una traza de WebArena sin procesar

Un episodio de WebArena contiene la descripción de la tarea, la secuencia de acciones y la ruta de cada captura:

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
}

Convertir la traza

El visor de Potato lee un formato de pasos normalizado y no el propio de cada framework, así que los episodios sin procesar pasan antes por el conversor:

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

Eso escribe una instancia por episodio, y cada paso lleva step_index, screenshot_url, action_type, el element objetivo y su caja delimitadora, coordinates, un mouse_path opcional, y el thought y la observation del agente cuando el registro de origen los recogió. Si cambias -f web_agent por --auto-detect, el conversor identifica el formato por sí mismo, que es la opción adecuada cuando un directorio contiene trazas de más de un framework.

La configuración del proyecto

El visor es un tipo de visualización y no un tipo de anotación, así que va bajo instance_display.fields y los esquemas de anotación quedan separados de él. El tamaño de la captura es el ajuste que conviene decidir primero. Con 900 píxeles de ancho, una página de escritorio completa sigue siendo legible sin empujar los controles de anotación fuera de la parte inferior de la pantalla.

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

Un solo esquema trajectory_eval cubre toda la pasada por pasos. Muestra cada paso como una tarjeta y recoge en cada una la corrección, un tipo de error, una gravedad y una justificación escrita, y luego calcula una puntuación de calidad de la traza a partir de los pesos de gravedad. Con los pesos de arriba, un error grave le cuesta a la traza cinco puntos y uno crítico, diez. Fíjalos con intención, porque deciden cómo se clasifica una traza con un fallo serio frente a una con cuatro pequeños.

Lo que ve el anotador

Visor de trazas de agentes web en Potato

La captura del paso actual ocupa el panel principal, con superposiciones SVG dibujadas encima. Cada superposición marca una parte distinta del paso, y sus colores son fijos:

SuperposiciónMarca
Círculo rojo con retículaLas coordenadas del clic
Resaltado amarilloEl campo en el que escribió el agente
Flecha verdeLa dirección y la magnitud de un desplazamiento
Rectángulo azul discontinuoLa caja delimitadora del elemento objetivo
Línea curva naranjaLa trayectoria del ratón hasta el objetivo

A lo largo de la parte inferior corre una tira de miniaturas, y al hacer clic en una se salta a ese paso. En trazas de más de unos diez pasos, la tira separa al revisor que ve la forma de la ejecución del que se desplaza a ciegas. El panel de detalles del paso muestra la información del elemento, el propio razonamiento del agente y la observación que registró; cada uno se puede desactivar en display_options cuando el registro de origen no tiene nada útil en él.

Una fila de casillas bajo el visor activa y desactiva las superposiciones:

ControlSuperposición
ClicksLa retícula roja del clic
Bounding BoxesEl rectángulo azul discontinuo
Mouse PathLa línea curva naranja
ScrollLa flecha verde de desplazamiento

Desactivar superposiciones importa en páginas densas, donde un marcador de clic puede quedar encima del texto que te dice si el clic fue correcto. Ten en cuenta que el resaltado amarillo de escritura no tiene control propio. Cuatro de las cinco superposiciones se pueden activar por separado, y el resaltado del campo escrito siempre se dibuja. Este visor no tiene atajos de teclado, así que la navegación entre pasos se hace con la tira de miniaturas y los controles de paso.

La pasada de anotación

Un revisor trabaja una traza en cinco movimientos:

  1. Lee la descripción de la tarea. Todo lo que sigue es un juicio respecto a ella.
  2. Recorre la tira de miniaturas. Hazte una idea de la forma de la ejecución antes de calificar nada, para no marcar como correcto un paso temprano con pruebas que solo aparecen después.
  3. Recorre los pasos. En cada uno, lee el estado de la página, mira la superposición para ver sobre qué actuó el agente y califica la acción. Si es incorrecta, elige el tipo de error y una gravedad, y explica en la justificación qué debería haber hecho el agente.
  4. Califica la traza. Juzga el éxito general y la eficiencia una vez vistos todos los pasos.
  5. Envía y pasa a la siguiente.

Las cuatro opciones de corrección dividen los pasos según la línea que importa para los datos de entrenamiento. Las acciones correctas avanzan hacia la meta de la forma esperada. Las aceptables progresan por una ruta más lenta, como ir a una página de categoría en lugar de usar el cuadro de búsqueda. Las incorrectas son errores, como un elemento equivocado, una página irrelevante o un texto erróneo en un formulario. Las innecesarias ni ayudan ni perjudican, como un clic seguido de inmediato por una navegación hacia atrás, y vale la pena separarlas de los errores, porque un agente que deambula es un problema distinto de un agente que se equivoca.

La taxonomía de errores

Los tipos de error son lo que convierte un montón de trazas fallidas en algo sobre lo que un desarrollador de agentes puede actuar, así que las categorías deben corresponder a causas distinguibles y no a grados de error:

Tipo de errorQué significaEjemplo
Elemento equivocadoEl agente actuó sobre el elemento de interfaz equivocadoHizo clic en "Tablets" en lugar de "Laptops"
Página equivocadaEl agente acabó en un sitio irrelevanteFue a "About Us" en lugar del listado de productos
Mejor opción ignoradaHabía una acción mejor disponibleRecorrió categorías teniendo el cuadro de búsqueda a la vista
Entrada de formulario incorrectaEl agente escribió un texto erróneoBuscó "labtop" en lugar de "laptop"
Finalización prematuraEl agente declaró el éxito demasiado prontoAñadió el artículo equivocado al carrito y se detuvo
Navegación innecesariaEl paso no contribuye a la metaVisitó la página de inicio entre dos páginas de categoría
No se desplazóEl objetivo estaba por debajo del viewportEl elemento nunca fue visible y el agente nunca se desplazó
Sección equivocada de la páginaPágina correcta, zona equivocadaHizo clic en la cabecera en lugar del contenido principal

Trabajar con trazas difíciles

En una traza de más de quince pasos, calificar cada paso con la misma profundidad gasta la mayor parte del esfuerzo en los pasos que obviamente estaban bien. Recorre la tira de miniaturas buscando los tres patrones que señalan un problema y concentra ahí el esfuerzo. Los patrones son una URL que cambia de forma inesperada, un paso en el que el agente retrocede y una serie de capturas casi idénticas, que suele indicar que el agente está atrapado en un bucle.

En una traza fallida, la anotación que vale la pena acertar es el primer paso incorrecto. Todo lo que viene después ocurre en un estado al que el agente nunca debería haber llegado, así que los errores posteriores describen las consecuencias y no la causa.

Algunas acciones no se pueden juzgar solo con la captura, normalmente cuando varios elementos se solapan en el punto del clic. La información del elemento en el panel del paso da la etiqueta, el texto y la caja delimitadora del objetivo, lo que por lo general basta para saber qué se pulsó realmente; show_element_info mantiene visible ese panel.

VisualWebArena

Las trazas de VisualWebArena pasan por el mismo conversor, que reconoce ambos formatos por los campos action_type y element de sus pasos de acción. La información de anclaje que llevan esas trazas aparece como la superposición de caja delimitadora, así que una pasada centrada en el anclaje depende de lo que los anotadores mantengan en pantalla y no de editar la configuración. Dejar marcada Bounding Boxes y desmarcar Clicks da la vista que muestra si el agente apuntó al elemento correcto y no solo al píxel correcto.

Leer los resultados

Los errores de los agentes web tienden a agruparse en puntos concretos de una traza, y la tasa de error por posición del paso es la forma más rápida de ver dónde. Cada anotación trajectory_eval guarda una lista de registros por paso, cada uno con su step_index y su 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)")

La distribución de tipos de error responde a la otra pregunta, que es en qué se equivoca el agente y no cuándo:

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

Escalar la evaluación

Para un resultado que piensas publicar, un revisor por traza no basta, porque los juicios por paso tienen justo el tipo de ambigüedad que las estadísticas de acuerdo existen para medir. Fija el objetivo de cobertura y el orden de asignación en el nivel superior de la configuración:

yaml
num_annotators_per_item: 3
assignment_strategy: random

Luego compara a los anotadores en la etiqueta de nivel de traza, que es aquella en la que un desacuerdo no tiene ambigüedad. Exporta primero a Parquet, para que la comparación se haga sobre columnas y no sobre JSON analizado:

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

En evaluaciones de cientos de trazas, Solo Mode pone un modelo en la misma cola que el revisor humano: el modelo propone etiquetas y el humano las corrige hasta que ambos coinciden con la frecuencia suficiente para que el modelo termine el resto:

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

El ajuste en el que hay que pensar es el umbral de acuerdo, no la elección del modelo. Con 0,90, el humano sigue anotando hasta que nueve de cada diez etiquetas del modelo coinciden con las suyas, medido sobre al menos cincuenta comparaciones, y bajarlo cambia calidad de etiquetas por horas de revisión de una forma difícil de detectar después.

Lecturas adicionales