---
title: "Alertas por llamada en Prometheus Alertmanager: suena solo lo crítico"
description: "Alertmanager no tiene receptor de voz. Enruta las alertas de Prometheus a una llamada solo para severidad crítica: config del webhook, condiciones y la trampa del Watchdog."
date: 2026-09-04
author: Nooc
authorAvatarLink: /images/avatars/nooc.webp
authorLink: https://nooc.me
tags:
  - Prometheus
  - Alertmanager
  - alertas por llamada
  - notificaciones webhook
  - Kubernetes
  - guardia
---

# Alertas por llamada en Prometheus Alertmanager: suena solo lo crítico

Alertmanager no tiene receptor de voz. Para recibir una llamada cuando se dispara una alerta de Prometheus, añade un receptor `webhook_configs` que apunte a un canal de Echobell cuyo tipo de suscripción sea **Llamada**. Esta guía cubre el YAML exacto, la condición que evita que las alertas resueltas te llamen, el enrutado por severidad y la alerta Watchdog que, si no, hará sonar tu teléfono cada cuatro horas para siempre.

Prometheus es la pila de métricas por defecto de casi toda la infraestructura construida en la última década, y [Alertmanager](https://prometheus.io/docs/alerting/latest/alertmanager/) es realmente bueno en las partes difíciles: deduplicar alertas, agruparlas, silenciarlas durante el mantenimiento e inhibir el ruido aguas abajo cuando falla una dependencia aguas arriba.

Lo único que no hará es despertar a nadie.

## Por qué Alertmanager no puede hacer sonar tu teléfono

Alertmanager incluye receptores para email, Slack, PagerDuty, OpsGenie, Discord, Telegram, Pushover, Webex, MS Teams y una docena más. Todos entregan un *mensaje*, y los mensajes están sujetos al interruptor de silencio, al modo No molestar y a los modos de Concentración de iOS. A las 03:00 eso significa que la alerta llega y no pasa nada.

No existe `voice_configs`. Las opciones a las que suele llegar la gente son:

- **PagerDuty / OpsGenie / Splunk On-Call**: sí llaman, y son plataformas completas de gestión de incidentes con precio por puesto a juego. La respuesta correcta si necesitas rotaciones y árboles de escalado; excesiva si solo quieres que suene un teléfono. (OpsGenie, además, está [cerrando](/es/blog/opsgenie-end-of-life-alternatives), y por eso tantos equipos están reevaluando esta capa ahora mismo.)
- **Puentes SMS** como [Sachet](https://github.com/messagebird/sachet): ejecutas otro servicio, pagas a una pasarela por mensaje y el SMS sigue llegando como un mensaje. En iOS un texto no rompe el modo Concentración salvo que el remitente esté en tu lista de permitidos.
- **Pegamento sobre Twilio**: escribes un pequeño receptor de webhooks, compras un número, pagas por llamada y ahora eres dueño de una pieza de infraestructura de producción cuyo único trabajo es hacer sonar un teléfono.

El **receptor webhook** genérico es la vía de escape. Publica un JSON documentado en cualquier URL, y eso es todo lo que necesitas.

## Qué necesitas

- Un Prometheus + Alertmanager en marcha y acceso para editar `alertmanager.yml`
- Echobell instalado ([App Store](https://apps.apple.com/app/apple-store/id6743597198?pt=128151925&ct=blog-alertmanager-phone-call-alerts-es&mt=8) / [Google Play](https://play.google.com/store/apps/details?id=one.echobell.echobellandroid))
- Diez minutos

Esta guía está escrita contra Alertmanager 0.31. El payload del webhook lleva años en `version: "4"`, así que las versiones 0.2x se comportan igual.

Tu Alertmanager necesita HTTPS saliente hacia `hook.echobell.one`. **No** necesita ser accesible desde internet, así que un Alertmanager dentro de un clúster, de una VPC o de un homelab funciona perfectamente.

## Paso 1 — Crea un canal que te llame

En Echobell, crea un canal llamado algo como `Prometheus Critical`. Pon su tipo de notificación de suscripción en **Llamada**. Este es el ajuste que importa: las alertas de tipo Llamada llegan como una pantalla de llamada entrante y suenan a través del modo Concentración y No molestar de iOS, cosa que una notificación push no hace.

Configura las plantillas para leer el payload de Alertmanager directamente:

```
Title: 🔴 {{commonLabels.alertname}} on {{commonLabels.instance}}
Body: {{commonAnnotations.summary}}
{{commonAnnotations.description}}
```

Y, en Ajustes avanzados, una **plantilla de enlace** para que el registro de la notificación salte directo a la gráfica:

```
{{alerts[0].generatorURL}}
```

Después copia la **URL del webhook** del canal:

```
https://hook.echobell.one/t/<channel-token>
```

Trata esa URL como un secreto: cualquiera que la tenga puede hacer sonar tu teléfono.

## Paso 2 — Añade un receptor webhook

En `alertmanager.yml`:

```yaml
route:
  group_by: ["alertname", "cluster", "service"]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: echobell-critical

receivers:
  - name: echobell-critical
    webhook_configs:
      - url: "https://hook.echobell.one/t/<channel-token>"
        send_resolved: false
```

Recarga con `curl -X POST http://localhost:9093/-/reload` o con `SIGHUP`.

Fíjate en `send_resolved: false`. **El valor por defecto de un receptor webhook es `true`**, a diferencia de la mayoría de receptores de Alertmanager, así que omitirlo significa que tu teléfono suena cuando el servicio se rompe *y* vuelve a sonar cuando se arregla solo. Esa segunda llamada es la que enseña a la gente a ignorar la primera. El paso 4 muestra cómo recuperar el aviso de recuperación sin el timbre.

## Paso 3 — Entiende qué llega realmente

Alertmanager agrupa las alertas y luego hace un POST por grupo:

```json
{
  "version": "4",
  "groupKey": "{}:{alertname=\"HighErrorRate\"}",
  "truncatedAlerts": 0,
  "status": "firing",
  "receiver": "echobell-critical",
  "groupLabels": { "alertname": "HighErrorRate" },
  "commonLabels": { "alertname": "HighErrorRate", "severity": "critical" },
  "commonAnnotations": { "summary": "Error rate above 5% for 10m" },
  "externalURL": "http://alertmanager.internal:9093",
  "alerts": [
    {
      "status": "firing",
      "labels": { "alertname": "HighErrorRate", "instance": "api-7d9f:8080" },
      "annotations": { "summary": "Error rate above 5% for 10m" },
      "startsAt": "2026-09-04T02:41:07.351Z",
      "endsAt": "0001-01-01T00:00:00Z",
      "generatorURL": "http://prometheus:9090/graph?g0.expr=...",
      "fingerprint": "a1b2c3d4e5f60718"
    }
  ]
}
```

Echobell lee el cuerpo JSON tal cual, así que todos esos campos están disponibles en plantillas y condiciones. El acceso anidado funciona con cualquiera de las dos sintaxis: `{{commonLabels.severity}}` o `{{alerts[0].labels["instance"]}}`.

Dos propiedades de este payload gobiernan todo lo que viene después:

**El `status` de nivel superior es `firing` si *alguna* alerta del grupo está activa.** Solo pasa a `resolved` cuando todas las alertas del grupo se han resuelto. Eso lo convierte en algo limpio sobre lo que filtrar.

**`commonLabels` contiene solo las etiquetas compartidas por todas las alertas del grupo.** Esta es la sorpresa más común. Si `group_by` es lo bastante amplio como para que un webhook lleve `HighErrorRate` de tres instancias distintas, `commonLabels.instance` no existe y `{{commonLabels.instance}}` se renderiza como cadena vacía. Más abajo hay una sección sobre cómo manejarlo.

## Paso 4 — Envía las recuperaciones como push silencioso

Sigues queriendo saber cuándo se recupera algo; simplemente no quieres que te llamen por ello. Añade un segundo canal de Echobell llamado `Prometheus Recovered`, ponlo en tipo **Normal**, dale estas plantillas:

```
Title: ✅ {{commonLabels.alertname}} resolved
Body: {{commonAnnotations.summary}}
```

y, en Ajustes avanzados, esta **condición**:

```
status == "resolved"
```

Las condiciones son expresiones que se evalúan antes de entregar nada. Si la expresión es falsa, Echobell acepta la petición y no envía nada.

Después apunta el mismo receptor a ambos canales: un receptor puede tener varios `webhook_configs`.

```yaml
receivers:
  - name: echobell-critical
    webhook_configs:
      # Hace sonar el teléfono. Solo cuando está activa.
      - url: "https://hook.echobell.one/t/<calling-channel-token>"
        send_resolved: false
      # Push silencioso. La condición del canal descarta la mitad "firing".
      - url: "https://hook.echobell.one/t/<recovery-channel-token>"
        send_resolved: true
```

El canal de recuperación recibe payloads tanto de firing como de resolved y descarta los primeros. Resultado: la caída suena, la recuperación llega como un push que lees por la mañana.

## Paso 5 — Enruta por severidad, no por todo

Una ruta que lo manda todo a un canal de llamada es una máquina de producir llamadas ignoradas. Divide por severidad en Alertmanager, que es donde pertenece el árbol de enrutado:

```yaml
route:
  group_by: ["alertname", "cluster", "service"]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: echobell-warning

  routes:
    # Watchdog nunca llega a un humano. Ver Paso 6.
    - matchers:
        - alertname = "Watchdog"
      receiver: "null"

    - matchers:
        - severity = "critical"
      receiver: echobell-critical
      group_wait: 10s
      repeat_interval: 1h

receivers:
  - name: "null"

  - name: echobell-critical
    webhook_configs:
      - url: "https://hook.echobell.one/t/<calling-channel-token>"
        send_resolved: false

  - name: echobell-warning
    webhook_configs:
      - url: "https://hook.echobell.one/t/<normal-channel-token>"
        send_resolved: true
```

Las rutas se evalúan de arriba abajo y **gana la primera coincidencia**: `continue` es `false` por defecto. Por eso el orden importa: la ruta de `Watchdog` tiene que ir por encima de cualquier cosa que pudiera tragársela.

Si prefieres quedarte con un solo canal y filtrar del lado de Echobell, la condición equivalente es:

```
status == "firing" && commonLabels.severity == "critical"
```

Normalmente es mejor hacerlo en Alertmanager, porque así `severity` también gobierna `group_wait` y `repeat_interval`. Hacerlo en Echobell es mejor cuando hoy no puedes mergear un cambio de configuración.

## Paso 6 — La trampa del Watchdog

Si usas [kube-prometheus-stack](https://github.com/prometheus-operator/kube-prometheus), tienes una alerta llamada `Watchdog` cuya expresión es `vector(1)`. Está *diseñada* para dispararse siempre: existe para que un sistema externo pueda notar que Prometheus se ha parado. La configuración por defecto la enruta a un receptor `null`.

Apunta una ruta catch-all a un canal de llamada sin excluirla y Watchdog llamará a tu teléfono cada `repeat_interval`, para siempre, empezando de inmediato. Esta es la razón número uno por la que la gente concluye que las alertas telefónicas "no funcionan".

Mantén la ruta `null` del paso 5. Y luego, opcionalmente, haz con ella algo útil: convierte Watchdog en un verdadero dead man's switch.

```yaml
    - matchers:
        - alertname = "Watchdog"
      receiver: deadmansswitch
      group_wait: 0s
      group_interval: 1m
      repeat_interval: 50s

receivers:
  - name: deadmansswitch
    webhook_configs:
      - url: "https://hc-ping.com/<your-check-uuid>"
        send_resolved: false
```

Echobell no puede ser el dead man's switch: alerta cuando *llega* una petición, no cuando dejan de llegar. Así que envía el ping del Watchdog a un servicio hecho para detectar silencios ([Healthchecks.io](https://healthchecks.io), Cronitor, Dead Man's Snitch), y luego apunta el webhook de "check caído" *de ese servicio* a tu canal de llamada de Echobell. Ahora una llamada significa "la monitorización está muerta", que es la alerta por la que más quieres que te despierten y la que nadie configura.

## Ajustes para que no sea el cuento del lobo

Tres ajustes de Alertmanager hacen casi todo el trabajo, más uno de Prometheus:

| Ajuste | Dónde | Qué hace |
| --- | --- | --- |
| `for:` | Regla de alerta | Cuánto debe mantenerse la condición antes de dispararse. Tu primera defensa frente a un parpadeo de dos segundos. |
| `group_wait` | Ruta | Cuánto esperar a más alertas antes de la primera notificación. 30s por defecto; bájalo a `10s` para crítico. |
| `group_interval` | Ruta | Intervalo mínimo antes de notificar sobre alertas *nuevas* de un grupo existente. 5m por defecto. |
| `repeat_interval` | Ruta | Cada cuánto se vuelve a notificar una alerta sin resolver. **4h por defecto**, así que una caída nocturna te llama a las 03:00 y otra vez a las 07:00. |

`repeat_interval` es el que merece reflexión. Cuatro horas es mucho tiempo para dejar algo roto; veinte minutos es una máquina para que acabes desactivando el canal. Una hora en crítico es un buen punto de partida.

Si quieres que una llamada no atendida se reintente de inmediato en lugar de esperar al siguiente `repeat_interval`, activa **Reintentar llamada fallida** en los ajustes de la app de Echobell.

## Sonar solo fuera del horario laboral

Durante la jornada probablemente ya estés mirando un panel. Las variables de tiempo del sistema de Echobell (todas en UTC) permiten que un canal se comporte distinto según la hora, sin una segunda ruta en Alertmanager:

```
status == "firing" && (hour >= 17 || hour < 9)
```

Eso te llama solo fuera de 09:00–17:00 UTC. Apunta un segundo canal, de tipo Normal, a la franja inversa para los push diurnos:

```
status == "firing" && hour >= 9 && hour < 17
```

Añade `dayOfWeek >= 1 && dayOfWeek <= 5` para tratar también el fin de semana como fuera de horario. Recuerda que siempre se calculan en UTC: compensa según tu zona horaria. Hay un tratamiento más completo en [notificaciones por ventana de tiempo con condiciones UTC](/es/blog/time-window-notifications-using-utc-conditions).

## Cómo manejar el problema de `commonLabels` vacío

Cuando un grupo contiene alertas de varias instancias, `commonLabels.instance` desaparece y el título de tu notificación queda como `🔴 HighErrorRate on `.

Tres salidas, por orden de preferencia:

1. **Mete la etiqueta en `group_by`.** Si `group_by` incluye `instance`, todas las alertas de un grupo la comparten y `commonLabels.instance` está siempre presente. El coste son más notificaciones: una por instancia en lugar de una por nombre de alerta.
2. **Lee la primera alerta.** `{{alerts[0].labels.instance}}` siempre tiene valor. Es solo una de posiblemente muchas, así que acompáñala de un recuento: `{{alerts[0].labels.instance}} (+{{alerts.length}} alertas)`.
3. **Diseña la etiqueta para que se lea bien vacía.** Echobell no tiene operador de valor por defecto —`{{a || "unknown"}}` renderiza el texto literal `true`, no un fallback—, así que escribe `Instance: {{commonLabels.instance}}` en su propia línea, donde un valor vacío se ve obviamente vacío en vez de romper una frase.

## Mantener pequeño el payload

Un grupo que cubra cien pods produce un cuerpo JSON grande, y Echobell rechaza cuerpos de más de 1 MiB con HTTP 413. Limítalo en Alertmanager:

```yaml
      - url: "https://hook.echobell.one/t/<channel-token>"
        send_resolved: false
        max_alerts: 20
```

Alertmanager enviará entonces como mucho veinte alertas y pondrá en `truncatedAlerts` el número que descartó, que puedes mostrar en el cuerpo:

```
Body: {{commonAnnotations.summary}}
Alerts: {{alerts.length}} (+{{truncatedAlerts}} truncadas)
```

## Compartir la alerta con tu equipo

Un canal de Echobell se puede compartir mediante un enlace de suscripción, y cada suscriptor elige su propio tipo de notificación. Así, la misma ruta puede hacer sonar el teléfono del ingeniero de guardia y llegar como push normal para el resto, sin precio por puesto y sin reglas de enrutado extra en Alertmanager.

También encaja con la razón por la que muchos equipos autoalojan Prometheus: tus métricas y reglas de alerta se quedan en tu infraestructura, y Echobell guarda el contenido y el historial de notificaciones en el dispositivo, no en sus servidores.

## Lo que esta configuración no te da

Ser honesto sobre el límite te ahorra una mala migración más adelante. Echobell es una capa de entrega, no una plataforma de gestión de incidentes. No tiene:

- Calendarios de guardia ni relevos follow-the-sun
- Árboles de escalado que avisen a una segunda persona si la primera no responde
- Líneas temporales de incidentes, seguimiento de reconocimiento ni herramientas de postmortem

Si tu equipo necesita eso, necesitas PagerDuty, Grafana Cloud IRM o similar. Lo que esto cubre es el hueco concreto que deja Alertmanager: convertir una alerta activa en un teléfono que suena de verdad. Para operadores en solitario, equipos pequeños y homelabs, eso suele ser todo el requisito.

## Resolución de problemas

**No llega absolutamente nada.** Mira primero los logs del propio Alertmanager (`level=error component=dispatcher`) y luego confirma que la ruta resuelve a tu receptor: `amtool config routes test severity=critical alertname=HighErrorRate` te dice en qué receptor caería una alerta sin esperar a que se dispare una.

**Echobell devuelve HTTP 404.** El token del canal es incorrecto o el canal fue eliminado. Un token desconocido es un 404, no un éxito silencioso.

**Echobell devuelve 200 con `"notificationTriggered": false`.** Tu condición evaluó a falso. El cuerpo de la respuesta también lleva `"conditionsMet": false`, que es la forma más rápida de distinguir "mi condición está mal" de "mi webhook nunca llegó". Comprueba `status == "firing"` contra lo que Alertmanager envió realmente: el status de nivel superior, no `alerts[0].status`.

**HTTP 413.** El payload superó 1 MiB. Configura `max_alerts` como arriba.

**HTTP 405.** El canal tiene **POST Only** activado y algo envió un GET. Alertmanager hace POST, así que esto suele significar que probaste la URL en un navegador.

**El título tiene un hueco vacío.** `commonLabels` no contenía esa etiqueta para ese grupo. Ver la sección anterior.

**No suena, pero la notificación llega.** El tipo de notificación de la suscripción es Normal o Urgente, no Llamada. El tipo se elige por suscriptor, así que revísalo en el dispositivo que no suena.

**Probar sin romper producción.** Añade una regla con `expr: vector(1)`, un `alertname` distintivo y `severity: critical`, deja que se dispare una vez y bórrala. O lanza una a mano:

```bash
curl -X POST http://localhost:9093/api/v2/alerts -H 'Content-Type: application/json' -d '[
  {"labels":{"alertname":"EchobellTest","severity":"critical"},
   "annotations":{"summary":"Testing the phone call path"}}
]'
```

## Preguntas frecuentes

### ¿Prometheus Alertmanager puede hacer una llamada de forma nativa?

No. Alertmanager tiene receptores para email, Slack, PagerDuty, OpsGenie y muchos más, pero no hay receptor de voz ni de SMS. Las llamadas requieren enrutar el receptor webhook genérico a un servicio que pueda hacerlas, como Echobell, o pagar una plataforma de gestión de incidentes.

### ¿La llamada sortea el modo No molestar?

Sí. El tipo de notificación Llamada de Echobell se presenta como una llamada entrante, que suena a través del modo Concentración y No molestar de iOS. Los detalles y ajustes están en [cómo superar iOS Focus Mode para alertas críticas](/es/blog/how-to-bypass-ios-focus-mode-for-critical-alerts).

### ¿Funciona con Alertmanager tras un cortafuegos o dentro de Kubernetes?

Sí. El webhook es una petición HTTPS saliente desde Alertmanager, así que solo necesita alcanzar `hook.echobell.one`. Tu Alertmanager no necesita dirección pública ni ingress.

### ¿Cómo dejo de recibir llamadas cuando una alerta se resuelve?

Pon `send_resolved: false` en la config del webhook que apunta a tu canal de llamada. El receptor webhook usa `true` por defecto, a diferencia de la mayoría de receptores de Alertmanager, así que es opt-out y no opt-in. Para seguir recibiendo recuperaciones en silencio, añade un segundo canal con la condición `status == "resolved"`.

### ¿Por qué mi teléfono suena cada cuatro horas por la misma alerta?

Es `repeat_interval`, que por defecto vale `4h`. Alertmanager vuelve a notificar una alerta aún activa con esa cadencia. Ajústalo por ruta: `1h` en crítico es una elección habitual. Si las llamadas empezaron justo tras añadir una ruta catch-all, lo más probable es que el culpable sea la alerta `Watchdog`, siempre activa; ver el paso 6.

### ¿Pueden llamar a varias personas por la misma alerta?

Sí. Comparte el canal con tus compañeros y cada suscriptor elige su tipo de notificación. Todos los suscritos al canal de llamada reciben el timbre, sin coste por puesto.

### ¿Filtro la severidad en Alertmanager o en las condiciones de Echobell?

Mejor en Alertmanager: enrutar allí también te permite ajustar `group_wait` y `repeat_interval` por severidad, y el árbol de rutas queda en control de versiones con el resto de la configuración. Usa condiciones de Echobell cuando no puedas cambiar la config de Alertmanager, o para filtros que Alertmanager no contempla, como la hora del día.

## Cierre

La configuración es un receptor, un `send_resolved: false` y un árbol de rutas que mantiene todo lo que no sea `severity: critical` lejos del canal de llamada. Deja tus reglas de alerta, agrupaciones, silencios e inhibiciones exactamente como están, y cierra el hueco entre "Prometheus se dio cuenta" y "una persona se dio cuenta".

[Descarga Echobell para iPhone](https://apps.apple.com/app/apple-store/id6743597198?pt=128151925&ct=blog-alertmanager-phone-call-alerts-es&mt=8) o [consíguelo en Google Play](https://play.google.com/store/apps/details?id=one.echobell.echobellandroid), y lanza la alerta `EchobellTest` de arriba antes de confiar en este camino para algo real.

---

## Relacionado

- [Documentación de la integración con Prometheus](/es/docs/developer/prometheus)
- [Referencia de condiciones de canal](/es/docs/conditions)
- [Notificaciones de llamada telefónica para alertas de Grafana](/es/blog/grafana-call-notification)
- [Alertas por llamada en Uptime Kuma](/es/blog/uptime-kuma-phone-call-alerts)
- [La fatiga de alertas es real: cómo la resuelven los desarrolladores inteligentes](/es/blog/fix-alert-fatigue-developer-guide)
