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.
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
pip install potato-annotationTambié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:
{
"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:
python -m potato.trace_converter -i traces.json -f web_agent -o data/web_traces.jsonlEso 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.
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: trueUn 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

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ón | Marca |
|---|---|
| Círculo rojo con retícula | Las coordenadas del clic |
| Resaltado amarillo | El campo en el que escribió el agente |
| Flecha verde | La dirección y la magnitud de un desplazamiento |
| Rectángulo azul discontinuo | La caja delimitadora del elemento objetivo |
| Línea curva naranja | La 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:
| Control | Superposición |
|---|---|
| Clicks | La retícula roja del clic |
| Bounding Boxes | El rectángulo azul discontinuo |
| Mouse Path | La línea curva naranja |
| Scroll | La 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:
- Lee la descripción de la tarea. Todo lo que sigue es un juicio respecto a ella.
- 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.
- 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.
- Califica la traza. Juzga el éxito general y la eficiencia una vez vistos todos los pasos.
- 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 error | Qué significa | Ejemplo |
|---|---|---|
| Elemento equivocado | El agente actuó sobre el elemento de interfaz equivocado | Hizo clic en "Tablets" en lugar de "Laptops" |
| Página equivocada | El agente acabó en un sitio irrelevante | Fue a "About Us" en lugar del listado de productos |
| Mejor opción ignorada | Había una acción mejor disponible | Recorrió categorías teniendo el cuadro de búsqueda a la vista |
| Entrada de formulario incorrecta | El agente escribió un texto erróneo | Buscó "labtop" en lugar de "laptop" |
| Finalización prematura | El agente declaró el éxito demasiado pronto | Añadió el artículo equivocado al carrito y se detuvo |
| Navegación innecesaria | El paso no contribuye a la meta | Visitó la página de inicio entre dos páginas de categoría |
| No se desplazó | El objetivo estaba por debajo del viewport | El elemento nunca fue visible y el agente nunca se desplazó |
| Sección equivocada de la página | Página correcta, zona equivocada | Hizo 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:
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:
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:
num_annotators_per_item: 3
assignment_strategy: randomLuego 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:
python -m potato.export -c config.yaml -f parquet -o ./parquet_export/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:
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: 50El 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
- Anotación agéntica, para la referencia completa del conversor y la visualización
- Anotación de agentes web, para las opciones de visualización del visor
- Evaluación de agentes de IA, para la evaluación de agentes más allá del navegador
- Exportación a Parquet, para las columnas que lee el análisis anterior