Bot de seguimiento de recitales indie en Buenos Aires
Hermes es un agente de IA que vive corriendo en un servidor y se comunica conmigo (Mati) principalmente por WhatsApp. No es un chatbot común: además de "hablar", hace cosas concretas.
Imaginate un asistente que está todo el día en la compu. Le podés pedir cosas por WhatsApp, pero también hace cosas solo: cada tanto revisa si hay recitales nuevos, y si encuentra, te avisa al grupo. Eso es Hermes con este bot.
Las Skills son manuales de instrucciones que le damos a Hermes para que sepa cómo manejar tareas específicas. Cada skill es un archivo de texto (SKILL.md) que describe:
Cuando alguien manda un mensaje al grupo de WhatsApp, Hermes carga la skill indie-shows-tracker. Esa skill le dice: "No busques en Google para responder. Toda la info está en la DB local. Consultala con el script."
Las skills se asocian a grupos de WhatsApp vía channel_skill_bindings en el config. Es como decirle: "Si te hablan desde este grupo, primero leé este manual".
Rastrea shows en vivo de artistas indie en Buenos Aires y alrededores (CABA, La Plata, Bernal, Quilmes) y manda notificaciones a un grupo de WhatsApp.
El sistema tiene 5 componentes principales que trabajan juntos:
Archivo /home/mati/indie_shows.db con todos los show: artista, fecha, venue, hora, precio, link de entradas y estado de notificación.
indie_shows.py)El "cerebro operativo". Se llama desde la línea de comandos con modos: list, daily, weekly, monthly, add-json, cleanup. Opera sobre la DB y manda WhatsApp.
Cuando un cron lo dispara, carga la skill indie-shows-tracker, hace web scraping y usa add-json para insertar datos. También responde consultas del grupo de WA.
5 tareas automáticas: notificación diaria, resumen semanal, resumen mensual, scraping 2×/semana, y cleanup mensual.
Baileys (Node.js) en http://127.0.0.1:3000. El script manda un POST con chatId + message y el bridge lo envía al grupo.
Dos veces por semana (miércoles y sábado a las 11:00), se dispara un cron job que despierta al agente para buscar shows nuevos.
El scheduler ejecuta el prompt: "Cargá la skill, consultá la DB, buscá shows para los 16 artistas."
Ejecuta indie_shows.py list para ver qué shows ya existen y evitar duplicados.
web_search para cada artista. Agrupa cuando puede. Fuentes: Passline, Venti, Ticketek, Bandsintown, Instagram, Indiehoy.
web_extract para entrar a cada página y sacar fecha, hora, venue, precio y el link para comprar entradas.
Descarta shows fuera de CABA y alrededores. Córdoba, Rosario, MDQ no.
Arma JSON y ejecuta add-json. El UPSERT inserta o actualiza sin duplicar.
SQLite guarda todo en un solo archivo (indie_shows.db). No necesita servidor. Python lo accede con el módulo sqlite3 que viene built-in.
showsCREATE TABLE shows (
id INTEGER PRIMARY KEY,
artista TEXT NOT NULL, -- "Pérez"
fecha DATE NOT NULL, -- "2026-11-01"
titulo TEXT NOT NULL, -- "Pérez presenta..."
venue TEXT DEFAULT '', -- "Club Social 911 (CABA)"
hora TEXT DEFAULT '', -- "21:00"
precio TEXT DEFAULT '', -- "12000"
link TEXT DEFAULT '', -- URL de entradas
fuente TEXT DEFAULT '', -- URL de dónde salió
detalle TEXT DEFAULT '', -- Info adicional
notif_dia INT DEFAULT 0, -- 1=ya se avisó
notif_sem INT DEFAULT 0, -- 1=ya se avisó
creado_en DATETIME,
actualizado DATETIME,
UNIQUE(fecha, artista, titulo) -- Sin duplicados
);
La restricción UNIQUE(fecha, artista, titulo) evita duplicados. Si el agente encuentra un show que ya existe pero cambió la hora, el ON CONFLICT ... DO UPDATE actualiza los campos existentes en vez de crear un duplicado.
El script manda el mensaje haciendo un HTTP POST al bridge de Baileys:
curl -s -X POST http://127.0.0.1:3000/send \
-H "Content-Type: application/json" \
-d '{"chatId":"120363428208084868@g.us",
"message":"🎵 ¡Shows indie mañana! ..."}'
El bridge es Baileys, una biblioteca de Node.js que se conecta a WhatsApp Web y expone una API HTTP local. Así podemos enviar mensajes programáticamente desde cualquier script.
whatsapp:
channel_prompts:
"120363428208084868@g.us": |
GRUPO DE SHOWS INDIE BAIRES.
REGLAS: 1) NUNCA busques en Google.
2) TODA la info está en la DB local.
3) Cargá la skill ANTES de responder.
channel_skill_bindings:
- id: "120363428208084868@g.us"
skills:
- indie-shows-tracker
Cuando alguien manda un mensaje al grupo, Hermes carga la skill y limita su comportamiento a lo que la skill define.
Un cron job es una tarea que se ejecuta automáticamente en un horario determinado. Es como poner una alarma, pero en vez de sonar, ejecuta un programa.
| Horario | Nombre | Qué hace |
|---|---|---|
| Todos los días 21:00 | daily | Avisa si hay shows mañana |
| Lunes 10:00 | weekly | Resumen semanal (7 días) |
| 1er lunes 10:30 | monthly | Resumen mensual (30 días) |
| Mié + Sáb 11:00 | scrape | Busca shows nuevos en internet |
| Día 1 del mes 09:00 | cleanup | Borra shows pasados (>7 días) |
SELECT * FROM shows
WHERE fecha >= date('now')
AND fecha <= date('now', '+90 days')
ORDER BY fecha, hora;
SELECT * FROM shows
WHERE fecha = date('now', '+1 day')
AND notificado_dia_anterior = 0
ORDER BY hora;
INSERT INTO shows (artista, fecha, titulo, venue, ...)
VALUES (?, ?, ?, ?, ...)
ON CONFLICT(fecha, artista, titulo) DO UPDATE SET
venue = excluded.venue,
hora = excluded.hora,
link = excluded.link,
actualizado_en = CURRENT_TIMESTAMP;
UPDATE shows
SET notificado_dia_anterior = 1
WHERE id = ?;
python3 /home/mati/indie_shows.py <modo>
init → Crear/actualizar la tabla
add-json → Agregar shows desde JSON (batch)
list → Listar próximos shows (90 días)
daily → Notificación día anterior
weekly → Resumen semanal (7 días)
monthly → Resumen mensual (30 días)
mark-sent → Marcar shows como notificados
cleanup → Borrar shows pasados
artists → Listar artistas rastreados
python3 /home/mati/indie_shows.py add-json '[
{"artista":"Toe", "fecha":"2026-09-13",
"titulo":"Toe - Latin America Tour 2026",
"venue":"Niceto Club (CABA)", "hora":"20:00",
"precio":"55000", "link":"https://venti.com.ar/...",
"fuente":"https://venti.com.ar/...",
"detalle":"Banda japonesa, tour latinoamericano"}
]'
Así funciona el sistema de punta a punta cuando busca nuevos shows:
Cada miérc + sáb a las 11:00, el scheduler de Hermes ejecuta el prompt del cron job.
Hermes carga la skill indie-shows-tracker como primer paso.
indie_shows.py list para ver qué shows ya existen.
web_search para buscar cada artista en Passline, Venti, Bandsintown, Instagram.
web_extract para entrar a cada página y sacar fecha, hora, venue, precio y link de entradas.
Descarta shows fuera de CABA y alrededores.
Arma JSON y ejecuta add-json. UPSERT evita duplicados.
indie_shows.py list otra vez para confirmar.
notif_dia=1.notif_sem=1.