Documentar cambio a Telegram, pausa nocturna y costo estimado
Actualiza docs/arquitectura/agente-monitoreo.md: canal de notificación cambiado de ntfy a Telegram Bot API (con la evidencia de la prueba de entrega), horario activo 06:00-23:00 con su justificación de costo, la tensión sin resolver con la ventana de medusa-deploy (00:00-06:00, no se solapa con el horario activo del agente), y la estimación de costo mensual (~US$60-65, basada en las corridas reales medidas).
This commit is contained in:
1 parent
5014903c51
commit
e493f7d39e
1 file changed
+70
-11
@@ -172,20 +172,79 @@ no se purgaron.
|
||||
|
||||
## Notificaciones
|
||||
|
||||
Canal: [ntfy](https://ntfy.sh) — sin sistema de notificación previo en
|
||||
el lab, se eligió la opción sin infraestructura nueva (tópico público
|
||||
de ntfy.sh, nombre privado difícil de adivinar) para validar la prueba
|
||||
end-to-end sin bloquear en instalar y exponer un contenedor propio.
|
||||
Migrar a un ntfy self-hosted (mismo patrón que gitea/nginxproxymanager/
|
||||
cloudflared) es un cambio de una sola variable (`NTFY_URL`) cuando se
|
||||
decida.
|
||||
**Canal: Telegram Bot API** (reemplaza a ntfy, cambiado 2026-08-26 por
|
||||
preferencia — no por costo, ver sección de costo abajo). Bot creado
|
||||
manualmente vía [@BotFather](https://t.me/BotFather); el token vive en
|
||||
`TELEGRAM_BOT_TOKEN_FILE` (dueño `devops`, `600` — **no** root-only,
|
||||
mismo criterio que `GITEA_TOKEN_FILE`: el servicio corre como `devops`
|
||||
por el login de suscripción, un archivo `root:root` le sería ilegible).
|
||||
`TELEGRAM_CHAT_ID` no es secreto, va directo en `lab-agent.env`.
|
||||
|
||||
El mensaje se manda como texto plano, sin `parse_mode`: el motivo que
|
||||
devuelve Claude es texto libre y puede traer `_`, `*`, `[`, `]` — con
|
||||
Markdown/MarkdownV2 esos caracteres rompen el parser de Telegram (`400
|
||||
Bad Request`) si no se escapan con cuidado. Se prioriza entrega
|
||||
confiable sobre formato.
|
||||
|
||||
**Validado en vivo 2026-08-26** con el mismo código que usa
|
||||
`notify_send()` (lectura del token, `sendMessage` vía `curl
|
||||
--data-urlencode`, formato `[title]\nmessage`): entrega confirmada
|
||||
(`"ok":true`) y contenido recibido tal cual en Telegram. Gotcha
|
||||
encontrado durante la prueba: el primer intento falló con `400 chat not
|
||||
found` porque el `chat_id` pegado correspondía a otro bot — el `chat_id`
|
||||
de un usuario es el mismo across bots, pero Telegram igual devuelve
|
||||
`chat not found` si *ese bot puntual* nunca recibió un mensaje de esa
|
||||
persona. Se resolvió confirmando el `chat_id` real vía `getUpdates` del
|
||||
bot correcto.
|
||||
|
||||
## Horario activo y costo
|
||||
|
||||
**Pausa nocturna (`ACTIVE_HOURS_START`/`END`, hora local del host):**
|
||||
activo `06:00`–`23:00`, pausado `23:00`–`06:00`. El script chequea esto
|
||||
como lo primero que hace tras inicializar logging — si está fuera de
|
||||
horario, sale **antes** de tocar `kubectl`/`docker`/`curl` o invocar
|
||||
`claude -p`, así que la pausa ahorra el costo completo de la corrida,
|
||||
no solo la notificación. El timer de systemd además solo dispara dentro
|
||||
de esa ventana (`OnCalendar=*-*-* 06..22:00/15:00`) — la doble
|
||||
verificación es deliberada: si alguien edita la unidad de systemd sin
|
||||
tocar `lab-agent.env` (o corre el script a mano), el chequeo interno
|
||||
sigue protegiendo.
|
||||
|
||||
**Tensión sin resolver con la ventana de `medusa-deploy`:** la ventana
|
||||
de auto-restart para `medusa-deploy` (`COMMERCE_BACKEND_WINDOW_*`,
|
||||
`00:00`–`06:00`) **no se solapa** con el horario activo del agente
|
||||
(`06:00`–`23:00`). Esto significa que, en la práctica, `medusa-deploy`
|
||||
nunca es candidato real a auto-restart: la única ventana en la que la
|
||||
política lo permitiría es exactamente cuando el agente está pausado y
|
||||
ni siquiera corre. La regla sigue viva en el código (por si el horario
|
||||
activo cambia más adelante) pero hoy es efectivamente inalcanzable.
|
||||
Pendiente de decisión: mover la ventana de `medusa-deploy` a que caiga
|
||||
dentro del horario activo, o aceptar que ese recurso queda cubierto
|
||||
solo por diagnóstico/notificación manual.
|
||||
|
||||
**Estimación de costo mensual:**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Corridas/día (17h activas ÷ 15 min) | 68 |
|
||||
| Costo por corrida (medido en la prueba e2e, Sonnet) | ~US$0.018–0.045 con cache tibia; ~US$0.12 en frío (primera corrida del día, tras 7h de pausa el cache de prompt ya expiró) |
|
||||
| Estimado diario (1 corrida fría + 67 tibias) | ~US$2.10 |
|
||||
| **Estimado mensual (× 30 días)** | **~US$60–65** (rango US$35–90 según variación real de cache) |
|
||||
|
||||
Basado en solo ~7 corridas reales medidas durante la prueba — no es un
|
||||
promedio estadísticamente robusto, es una primera estimación para
|
||||
decidir si el timer se activa. Revisar el costo real después de la
|
||||
primera semana en producción y ajustar frecuencia/modelo si hace falta.
|
||||
|
||||
## Pendiente antes de activar el timer en continuo
|
||||
|
||||
- **Confirmación explícita del propietario del lab** para habilitar el
|
||||
timer de systemd (Paso 4 original) — no se activa automáticamente
|
||||
solo por haber pasado la prueba end-to-end.
|
||||
- Unidad systemd corriendo como `devops` (no root), con límites de
|
||||
CPU/memoria.
|
||||
timer de systemd — no se activa automáticamente solo por haber
|
||||
pasado la prueba end-to-end ni por tener el costo estimado.
|
||||
- Unidad systemd de usuario (`systemctl --user`, corre como `devops`,
|
||||
no `root`), con límites de CPU/memoria (`CPUQuota`, `MemoryMax`).
|
||||
Requiere `loginctl enable-linger devops` (una vez, con sudo) para que
|
||||
seguir corriendo sin sesión interactiva activa.
|
||||
- Opcional: `GITEA_TOKEN_FILE` para activar la señal de "runner
|
||||
atascado" vía API de Gitea Actions (hoy se omite, degradación segura).
|
||||
- Decidir la tensión con la ventana de `medusa-deploy` (ver arriba).
|
||||
Reference in new issue
Block a user