agent-browser vs Playwright MCP: 12-15× menos tokens en pruebas E2E

10 min de lectura
AITokensE2E TestingBrowser Automationagent-browserPlaywright MCP

Cada vez que tenía que correr los tests E2E de un proyecto Next.js en el que trabajo, sabía que iba a perder buena parte de la sesión de Claude Code. La herramienta que usaba para que Claude Code controlara el browser era Playwright MCP — una integración que le permite a cualquier agente de IA (Cursor, Codex, Copilot, Antigravity, etc.) acceder al browser y operarlo como un usuario: navegar, hacer click, scrollear, sacar screenshots, testear la interactividad de un sitio. El problema era triple: era lento, gastaba decenas de miles de tokens por sesión, y solo podía manejar una instancia de browser a la vez.

El límite de una sola instancia era el peor de los tres. Un flujo no es un único test: al happy path hay que sumarle los edge cases, validaciones y errores — fácilmente diez o quince escenarios para algo como signup. Sin paralelismo cada ejecución de escenarios E2E corría en serie, una atrás de la otra, y testear un flujo completo consumía buena parte de la sesión en tokens y tiempo.

Intenté forzar el paralelismo de varias formas: repos no oficiales, scripts custom, configuraciones que prometían múltiples instancias. Perdí tiempo y no llegué a ningún lado.

Hasta que mi amigo Fache me pasó el dato de agent-browser, una herramienta open source de Vercel. Leyendo la documentación me llamó la atención algo: no era una optimización marginal sobre Playwright MCP, era una arquitectura completamente distinta. Decidí probarlo en serio, con una PoC que corriera el mismo flujo en ambas herramientas y midiera todo — tokens, tiempo, regresiones.

Resultado: 12 a 15× menos tokens para la misma cobertura. Y en menos tiempo del que Playwright MCP tardaba en testear un solo escenario, agent-browser puede correr 6 escenarios en paralelo — que es lo máximo que probé, no el límite real.

Mind blown

Acá van los números, el método y un par de hallazgos que cambiaron el plan a mitad de camino.

El costo escondido de los MCP

Cada MCP (Model Context Protocol — el protocolo que le permite a las herramientas de IA conectarse con tools externas) que tenés cargado inyecta sus definiciones de tools en JSON Schema dentro del system prompt (la instrucción base que se manda al modelo en cada turno). El Playwright MCP por sí solo agrega ~13.700 tokens.

No es un costo de runtime. Es un costo fijo de arranque que se factura como input tokens en cada request al modelo, lo uses o no la tool. Si en una sesión nunca abrís un browser, igual pagaste los 13.700 tokens.

Y hay un efecto compuesto peor: cada token gastado en describir tools que no usás es un token menos para código, historial de conversación o respuestas del modelo. Más MCPs significa system prompt más grueso, ventana útil más chica, compaction (la compresión automática del historial cuando se llega al límite del contexto) más temprana, y respuestas más pobres.

Cada MCP cargado "por si las dudas" es deuda invisible. Si no lo usás activamente, lo estás pagando igual.

El setup que tenía: 36 escenarios en Markdown + qa-agent

El proyecto en el que corro estos tests está armado con Next.js y React. Lo importante para esta historia es cómo tengo armada la capa de E2E: no hay código Playwright real. No hay playwright.config.*, no hay archivos .spec.ts, ni siquiera está @playwright/test en el package.json.

Todo es 100% MCP-driven. Los escenarios viven como documentos en Markdown escritos en lenguaje natural — algo así como "abrir el formulario de signup, completar los campos con datos válidos, verificar que el usuario llega al dashboard". Hay un agente qa-agent definido en .claude/agents/qa-agent.md que lee esos escenarios y los ejecuta contra el browser usando las tools mcp__playwright__browser_*. Y por arriba, un slash command propio que armé en Claude Code, /e2e {flow} (donde {flow} es el nombre del flujo que se quiere testear, pasado como argumento), orquesta todo el proceso: dispara qa-agents en paralelo cuando un flujo tiene varios grupos.

Si te interesa saber cómo llevo a cabo este sistema de automatización de QA con agentes de IA — cómo diseño los escenarios, cómo orquesto los grupos en paralelo — hacémelo saber por cualquiera de mis redes y con gusto te lo explico en otro post.

La pieza estructural son los 36 escenarios en lenguaje natural. Por estar escritos como prosa y no como código, son agnósticos a la herramienta de browser: cambiar de tool no toca los 36 escenarios, solo el agente que los ejecuta. Esa propiedad es lo que hace que la migración sea barata desde el día cero — pero es algo que diseñé antes, no algo que se gana después.

Por qué agent-browser es más barato

agent-browser no usa un motor diferente. Por debajo es Playwright + Chromium, igual que el MCP. La ganancia no viene del browser, viene del canal de comunicación con el LLM.

DimensiónPlaywright MCPagent-browser
Interfaz con el LLMJSON Schema en el system prompt (~13.700 tokens cada turno)Comandos vía Bash (0 tokens de schema)
Snapshot por defaultAccessibility tree completo (la representación de los elementos interactivos de la página, 5-15k tokens)Tree compacto con refs como @e1, @e2 (200-1.000 tokens)
Respuesta tras cada acciónSnapshot completo de la página (cientos de tokens)Solo confirma ejecución con ✓ Done (<10 tokens)
LatenciaCada sesión MCP arranca un browser nuevoBrowser ya corriendo en el daemon

Lo de la "respuesta tras cada acción" es la diferencia más sutil pero la que más pesa en sesiones largas. Cada vez que el LLM ejecuta un comando contra el browser, la herramienta le devuelve algo. Con Playwright MCP esa respuesta es la página entera, incluso si el LLM solo quería confirmar que un click funcionó. Con agent-browser es apenas un OK — y si el LLM necesita ver el resultado, pide un snapshot aparte. Multiplicado por las 20-30 acciones de un escenario E2E, ahí se acumula buena parte del ahorro.

Tres piezas técnicas:

  • CLI (la herramienta de línea de comandos) escrito en Rust que se invoca vía Bash y se comunica con el daemon vía IPC (Inter-Process Communication, comunicación entre procesos en la misma máquina). Arranca en menos de 50ms.
  • Daemon (proceso en background que vive entre comandos) que mantiene el browser abierto. Vive en ~/.agent-browser/ y se apaga solo tras inactividad.
  • Refs como @e1, @e2 en lugar de CSS selectors (los strings tipo div.button > .icon con los que tradicionalmente se identifican elementos en el DOM). Más cortos, más estables, menos tokens.

Misma funcionalidad, canal de transporte mucho más delgado.

La PoC: flujo real, métricas reales

Diseñé un experimento con criterios numéricos antes de migrar nada. Reducción mínima aceptable: 2× menos tokens, ≤1.5× tiempo, cero regresiones funcionales.

Elegí un flujo representativo en desktop (viewport 1280×800): navegar desde la home, ejecutar una búsqueda, ver el listado de resultados, entrar a una vista de detalle y capturar screenshots. Combina navegación + input + render dinámico — un patrón que cubre buena parte de los escenarios E2E que mantengo.

agent-browser open "http://localhost:3000"
agent-browser snapshot                # ~1.000 tokens — ve la home con el listado inicial
agent-browser click @e3                # focus en el searchbox
agent-browser type @e3 "demo"          # devuelve "✓ Done"
agent-browser screenshot poc-01-search.png
agent-browser get count "[role=option]"   # cantidad de resultados visibles
agent-browser click @e8                # navega al primer resultado
agent-browser snapshot                # ve la página de detalle
agent-browser screenshot poc-02-detail.png

~10 comandos, 2 screenshots, ~2 minutos wall clock. Cero regresiones visuales contra lo que devolvería Playwright MCP haciendo el mismo flujo.

Los números: 12-15× menos tokens

DimensiónPlaywright MCP (proyectado)agent-browser (medido)Ratio
Schema overhead inicial~13.700 tokens0 tokens
Snapshot típico5.000–15.000 tokens170–1.000 tokens~10–15×
Respuesta de comando trivial500–1.000 tokens<10 tokens (✓ Done)~80×
Total del flujo PoC~45–60k tokens~3–4k tokens~12–15× menos
Wall clockNo medido lado a lado~2 minsimilar
Regresiones funcionales00OK

El criterio de éxito era 2× menos tokens. Llegué a 12-15×. El criterio de tiempo era ≤1.5×; salió cerca de 1×. Cero regresiones.

Los números públicos de las comparativas hablaban de 4-5× menos tokens. En este proyecto medí 12-15× porque las sesiones largas amortizan más fuerte el schema fijo. El número que midas en tu caso va a depender de cuántos turnos tenga la sesión.

Lo que pensé que faltaba y estaba ahí todo el tiempo

En la primera lectura de la docs de agent-browser anoté como "limitaciones": no tiene network interception (interceptar requests HTTP del browser para inspeccionarlos o mockearlos), no captura console, no soporta multi-tab, no controla viewport, no graba HAR (HTTP Archive — el formato estándar para grabar tráfico de red). Tenía pensado dejar Playwright MCP como fallback para esos casos.

Después corrí agent-browser --help completo y casi todo lo que había descartado estaba ahí, nativo:

Capacidad que creí que faltabaComando real
Network interceptionagent-browser network requests [--filter <pattern>]
Console messagesagent-browser console [--clear]
Page errorsagent-browser errors [--clear]
Multi-tabagent-browser tab [new/list/close]
Viewport controlagent-browser set viewport <w> <h>
Device emulationagent-browser set device <name>
Network mockingagent-browser network route <url> [--abort/--body <json>]
HAR recordingagent-browser network har <start/stop> [path]
Visual regressionagent-browser diff snapshot/screenshot
Video recordingagent-browser record start/stop

Cobertura 1:1 con Playwright MCP. No hace falta fallback.

Antes de diseñar workarounds, leé la docs completa. Casi inventé eval wrappers para capturar console y errors, cuando había un comando dedicado a cada cosa.

Paralelismo nativo: --session

El MCP de Playwright expone un único contexto de browser por instancia. Cuando /e2e signup lanza 4 qa-agents en paralelo (happy-path, signup-page, validate-and-password, edge-cases), todos compiten por la misma pestaña y se pisan. En la práctica, los /e2e con varios grupos tenían que serializarse.

agent-browser resuelve esto con sesiones aisladas vía el flag --session <name>:

  • Cada sesión es un browser independiente con sus propias cookies, localStorage (almacenamiento persistente del browser por dominio), viewport y refs.
  • El daemon mantiene N sesiones en paralelo sin conflictos.
  • agent-browser session list muestra las activas; --session <name> close cierra solo esa.
5 qa-agents corriendo en paralelo con agent-browser

Para aprovecharlo, ajusté el comando /e2e para que el prompt del qa-agent incluya un nombre de sesión derivado del flow + group (por ejemplo signup-happy-path, signup-edge-cases). Y agregué una regla dura en el qa-agent: todo comando agent-browser debe llevar --session, y nunca invocar close --all durante una corrida paralela — mataría las sesiones hermanas.

EscenarioAntes (Playwright MCP)Ahora (agent-browser)
/e2e signup (4 grupos)Los 4 grupos corren uno atrás del otro: total aproximadamente 4× el grupo más largoLos 4 grupos corren en paralelo: total aproximadamente igual al grupo más largo
/e2e signin (4 grupos)Los 4 grupos corren uno atrás del otroLos 4 grupos corren en paralelo
Flow simple (/e2e homepage)Sin diferencia (un solo grupo, no hay paralelismo a aprovechar)Sin diferencia (un solo grupo)

/e2e signup que antes tardaba ~12 minutos (4 grupos × 3 min) ahora termina en ~3-4 minutos. El ahorro de tokens ya era el headline; el de tiempo se sumó gratis.

La migración: 9 archivos, cero src/ tocado

Final de la migración: 9 archivos modificados, ninguno bajo src/ ni en package.json.

  • .claude/agents/qa-agent.md — único archivo con lógica real reescrita. Reemplacé toda la sección de tools mcp__playwright__browser_* por una tabla de mapping 1:1 con comandos de agent-browser, más reglas para sesiones.
  • 5 archivos de comandos y docs (.claude/commands/e2e.md, .claude/commands/generate-e2e.md, docs/automation-reference.md, docs/e2e-scenarios/**/_cleanup.md) — solo menciones textuales actualizadas.
  • 3 archivos de cleanup — paths de la carpeta de logs.

Los 36 escenarios en Markdown no se tocaron. Esa es la pieza estructural que protege del vendor lock-in (la dependencia técnica que te ata a una herramienta específica): si los E2E vivieran en .spec.ts, esta migración hubiera sido una reescritura de cientos de líneas en lugar de una edición de 9 archivos.

El verdadero ahorro no fue cambiar de tool, fue haber escrito los escenarios en lenguaje natural mucho antes. La tool específica se vuelve un detalle de implementación.

Cuándo no migrar (y por qué probablemente igual te conviene)

Hay un puñado de casos donde Playwright MCP puede seguir teniendo sentido: tests que dependen mucho de Lighthouse (la herramienta de Chrome para auditar performance, SEO y accesibilidad), debugging con heap snapshots (capturas del consumo de memoria del browser para encontrar leaks), o setups que ya tienen suite de Playwright en código y no E2E en lenguaje natural.

Pero si tu E2E está escrito como prosa interpretable y solo necesitás navegación + assertions + screenshots + network/console, agent-browser te da cobertura 1:1 con un orden de magnitud menos de tokens.

Si una tool no se usa activamente, removela. "Por si las dudas" es deuda invisible que pagás en cada turno de cada sesión.

Fuentes

  • dev.to — Why Vercel's agent-browser Is Winning the Token Efficiency War
  • Pulumi Blog — Self-Verifying AI Agents: Vercel's Agent-Browser
Alexis Muñoz

Alexis Muñoz

Software Engineer