Es verano en San Francisco, y cada semana la autora olvidaba participar en la lotería del Stern Grove Music Festival. La solución, por supuesto, no fue poner un recordatorio en el calendario — sino construir un script en Python que corre semanalmente vía GitHub Actions, scrapea el sitio del festival con Playwright, y se registra automáticamente en la lotería.

Lo interesante es cómo lo construyó. Describió lo que quería a un agente de codificación (con experiencia previa automatizando reservas de canchas de tenis y visualizaciones de datos), y Entire registró cada prompt, tool call y output, generando un registro completo y auditable de cómo surgió todo el proyecto.

“Lo que cualquier desarrollador razonable haría en lugar de poner un simple recordatorio: construir un bot que lo haga por ti.”

Comenzó con un solo mensaje

Todo el proyecto comenzó con un único mensaje al agente de codificación (usó Claude Code, pero cualquier agente funciona). Le entregó las reglas del juego:

La lotería de Stern Grove abre seis semanas antes de cada concierto a las 10:00 AM y permanece abierta durante una semana completa…

También le pasó el HTML exacto del botón de inscripción. Stern Grove maneja sus entradas a través de Tixologi, así que el agente necesitaba saber con qué estaba lidiando.

Luego le indicó las variables secretas que tendría disponible su GitHub Action:

  • Nombre
  • Ciudad
  • Email
  • Una API key de Resend (para notificaciones)
  • Dirección de email “from”
  • Código postal

Todo esto vive como secretos encriptados en GitHub Actions — nunca se suben al repositorio — y el agente entendió esa restricción desde el principio.

La arquitectura propuesta

Antes de escribir una sola línea de implementación, el agente exploró el spec, hizo una pregunta aclaratoria y propuso un diseño limpio:

  • lottery.py — punto de entrada, ejecutado por un cron schedule de GitHub Actions
  • browser.py — toda la lógica de Playwright: web scraping y automatización del navegador
  • state.py — carga y guarda entered_lotteries.json para evitar dobles inscripciones
  • notify.py — emails de éxito y fallo vía Resend

La persistencia de estado fue la jugada maestra. En lugar de montar una base de datos para un trabajo que corre una vez por semana, las loterías ingresadas se rastrean en un archivo JSON que se sube de vuelta al repositorio después de cada ejecución.

Inspeccionar antes de automatizar

Antes de tocar cualquier lógica del navegador, el agente hizo una inspección en vivo de la página real de Stern Grove — específicamente window.tixologiWidget.concerts — para aprender la forma real de los datos en lugar de suponer.

Esa inspección documentó los nombres de campos precisos, el formato de fecha ISO 8601 y la estructura de IDs de eventos. Un solo console.log capturado ahorró mucho debugging después:

// Lo que la página realmente expone
window.tixologyWidget.concerts
// → [{ eventId, name, startDate: "2025-07-13T19:00:00Z", ... }]

Basar la implementación en datos reales observados en lugar de suposiciones es un diferenciador clave entre el código que funciona en la primera ejecución real y el que falla silenciosamente en producción.

Subir estado al repositorio

state.py no solo lee el JSON — después de una inscripción exitosa, hace commit y push de la actualización usando un Personal Access Token (PAT) de GitHub, para que la siguiente ejecución sepa qué ya se hizo:

def commit_state(token: str) -> None:
    subprocess.run(["git", "add", "entered_lotteries.json"], check=True)
    subprocess.run(["git", "commit", "-m", "Update entered lotteries"], check=True)
    subprocess.run(["git", "push"], check=True)

El ciclo de revisión atrapó un bug real

Cuando el agente agregó notify.py, un agente revisor identificó inmediatamente dos problemas en el diff:

  1. Estaba usando print() en lugar del módulo logging.
  2. Había duplicado la inicialización de la API key de Resend.

El agente corrigió ambos antes de pasar a la siguiente tarea. Ese ciclo tarea → revisión funcionó exactamente como debería — atrapando el tipo de descuido que normalmente solo aparece semanas después.

import logging

logger = logging.getLogger(__name__)
resend.api_key = os.environ["RESEND_API_KEY"]  # inicializado una vez

def notify_success(show: str) -> None:
    logger.info("Entered lottery for %s", show)
    resend.Emails.send({ ... })

No funcionó al primer intento

La primera ejecución real falló. Dos problemas de entorno:

1. Deriva de versión de Ubuntu. Tuvo que fijar el runner a Ubuntu 22.04 para compatibilidad con Playwright. ubuntu-latest se había convertido silenciosamente en Ubuntu 24.04, y el paquete libasound2 fue renombrado en el proceso.

2. Dependencias de Chromium. Terminó instalando las dependencias de Chromium manualmente con los nombres correctos de paquetes de Ubuntu 24.04 en lugar de confiar en el instalador empaquetado de Playwright.

La solución pasó de esto:

# antes
- run: playwright install --with-deps chromium

a instalaciones explícitas con apt más un paso Playwright más ligero:

# después
- run: |
    sudo apt-get update
    sudo apt-get install -y libasound2t64 libnss3 libnspr4
- run: playwright install chromium

Stack final

El stack quedó muy bien armado:

  • Playwright para la automatización del navegador
  • GitHub Actions para el cron semanal y gestión de secretos
  • Resend para notificaciones de éxito/fallo
  • Un agente de codificación (Claude Code) para construirlo, con un ciclo de revisión que atrapó bugs reales
  • Entire capturando cada prompt, tool call y output, vinculado a los commits

La próxima vez que necesites automatizar un proceso repetitivo, recuerda: no necesitas un calendario, necesitas un bot. Y con herramientas como Playwright, GitHub Actions y agentes de IA, puedes tenerlo funcionando en cuestión de horas.


¿Quieres automatizar procesos en tu negocio? Prueba las herramientas de automatización que mencionamos y acelera tus flujos de trabajo.