El problema: mi agente no podía ver la web real
Mi agente ya puede hacer bastantes cosas: buscar en la web, leer artículos, ejecutar comandos, gestionar archivos. Pero había una limitación clara: cuando le pedía que revisara algo en X, LinkedIn o GitHub, solo podía obtener texto plano con web_fetch. Sin autenticación, sin interacción, sin ver lo que yo realmente veo.
Lo que necesitaba era que el agente pudiera conectarse a mi navegador real —con mis sesiones activas— y navegar páginas de la misma forma que lo haría yo: haciendo clic, rellenando formularios, tomando capturas de pantalla.
Descubriendo Browser Use CLI
Buscando herramientas de automatización de navegador orientadas a agentes de IA, encontré Browser Use CLI. No es Selenium ni Playwright puro — es una herramienta diseñada específicamente para ser consumida por LLMs.
La clave diferenciadora: el comando browser-use state devuelve los elementos de la página con índices numéricos. En lugar de HTML crudo, obtienes algo así:
[0] <button> Seguir
[1] <a href="/home"> Inicio
[2] <input placeholder="Buscar...">
[3] <div class="tweet-text"> Texto del post...Eso es exactamente lo que un LLM necesita para razonar sobre una página y decidir qué hacer. Nada de parsear HTML, nada de selectores CSS. Solo índices.
Otro detalle importante: corre como un daemon persistente. El navegador se mantiene vivo entre comandos, con una latencia de ~50ms. Nada de lanzar Chrome desde cero en cada operación.
Instalación: un comando
curl -fsSL https://browser-use.com/cli/install.sh | bashEso es todo. El script instala un virtualenv Python en ~/.browser-use-env/, descarga Chromium vía Playwright y deja el binario browser-use disponible en ~/.browser-use/.
Puedes verificar que funciona con:
browser-use --versionEl problema con Brave (y cómo resolverlo con CDP)
Aquí apareció el primer obstáculo real. Browser Use tiene un flag --profile que permite usar un perfil existente de Chrome. El problema: solo funciona con Chrome. Yo uso Brave.
La solución fue usar el Chrome DevTools Protocol (CDP). Es el mismo protocolo que usa el panel de herramientas de desarrollador del navegador (F12), Playwright y Puppeteer. Cuando lanzas Brave con --remote-debugging-port=9222, se crea un servidor local que expone control total del navegador.
# Cerrar Brave si está abierto, luego relanzar con CDP habilitado
open -a "Brave Browser" --args --remote-debugging-port=9222Después, conectar el agente es tan simple como:
browser-use --cdp-url http://localhost:9222Para no tener que recordar estos pasos, creé un script brave-connect.sh:
#!/bin/bash
# Cerrar Brave limpiamente
osascript -e 'quit app "Brave Browser"'
sleep 1
# Relanzar con CDP habilitado
open -a "Brave Browser" --args \
--remote-debugging-port=9222 \
--no-first-run
# Esperar a que el puerto esté listo
echo "Esperando a Brave..."
until curl -s http://localhost:9222/json/version > /dev/null 2>&1; do
sleep 0.5
done
echo "Brave listo en CDP puerto 9222"Una pausa sobre seguridad
El puerto 9222 solo es accesible desde localhost, así que no está expuesto a la red. Pero existe un vector de ataque conocido: DNS rebinding. Una página maliciosa podría intentar redirigir peticiones a localhost:9222 y obtener control del navegador.
¿Es un riesgo real en uso cotidiano? Bajo, pero no cero. Mi postura: lo uso durante sesiones de trabajo activas, no lo dejo habilitado de forma permanente. El daemon de browser-use tampoco es persistente — arranca cuando lo necesito y cierro el CDP cuando termino.
Si trabajas con datos muy sensibles o en un entorno corporativo, considera si este trade-off tiene sentido para ti.
La prueba real: leyendo X con mis sesiones activas
Con Brave corriendo en modo CDP, conecté el agente y le pedí que abriera X:
browser-use --cdp-url http://localhost:9222
browser-use open https://x.com
browser-use screenshotEn lugar de la página de login, apareció mi feed completo. El agente podía ver exactamente lo que vería yo. Le pedí que leyera los posts más recientes:
browser-use stateY ahí estaban: posts de Brad Groux sobre la OpenClaw Foundation, soporte del protocolo kitty keyboard en Warp, el nuevo CLI de Browserbase. Luego navegué a un post específico de @anibal sobre inyección dinámica de skills en Claude Code — algo que me interesaba leer con más detalle.
El flujo completo fue:
# 1. Abrir página
browser-use open https://x.com/@anibal/status/...
# 2. Obtener estado de la página (elementos indexados)
browser-use state
# 3. Si hay algo en lo que hacer clic
browser-use click 4
# 4. Verificar resultado
browser-use screenshotLimpio, predecible, consumible por cualquier LLM.
Integrando todo como un skill de OpenClaw
Con el flujo validado, el siguiente paso era empaquetarlo como un skill propio para OpenClaw. La estructura quedó así:
~/.openclaw/workspace/skills/browser-use/
├── SKILL.md # Instrucciones concisas para el agente
├── references/
│ └── commands.md # Referencia completa de todos los comandos
└── scripts/
└── brave-connect.sh # Helper para conectar Brave con CDPEl SKILL.md es deliberadamente corto: explica el flujo principal (conectar con CDP, abrir URL, usar state para navegar), menciona que Brave es el método primario y apunta a references/commands.md para el detalle completo.
Aplicar el patrón de progressive disclosure fue la decisión clave aquí. El agente no necesita leer 200 líneas de documentación para hacer su tarea. Con el workflow esencial en SKILL.md y la referencia completa separada, el contexto se usa solo cuando realmente hace falta.
El resultado
Mi agente ahora puede:
- Conectarse a mi Brave con mis sesiones activas
- Navegar cualquier sitio autenticado: X, LinkedIn, GitHub, Gmail
- Leer contenido de feeds y páginas protegidas
- Hacer clic, rellenar formularios, tomar capturas de pantalla
- Todo a través de comandos CLI simples
Lo que empezó como "quiero que el agente pueda leer mis tweets" se convirtió en acceso completo a la web autenticada. La herramienta estaba ahí, el protocolo estaba ahí — solo hacía falta conectarlo bien.
Si usas OpenClaw o cualquier agente que soporte herramientas CLI, Browser Use vale mucho la pena explorar. El enfoque de devolver elementos indexados en lugar de HTML crudo es exactamente el tipo de interfaz que los LLMs necesitan para razonar sobre el navegador de forma fiable.