Skip to main content
Para obtener una guía más detallada sobre la integración con PagerDuty, haz clic aquí.
1

Implementar un puente de webhooks

Crea un pequeño servicio que escuche los eventos incident.resolved de PagerDuty e inicie una sesión de Devin para redactar el postmortem. Despliega esto como una función serverless (AWS Lambda, Cloudflare Worker) o un contenedor ligero:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());

function verifySignature(req) {
  const secret = Buffer.from(req.headers['x-webhook-secret'] || '');
  const expected = Buffer.from(process.env.WEBHOOK_SECRET || '');
  if (!expected.length) throw new Error('WEBHOOK_SECRET environment variable is not set');
  if (secret.length !== expected.length) return false;
  return crypto.timingSafeEqual(secret, expected);
}

app.post('/pagerduty-resolved', async (req, res) => {
  if (!verifySignature(req)) return res.status(401).send('Bad signature');

  const event = req.body?.event;
  if (!event || event.event_type !== 'incident.resolved') {
    return res.sendStatus(200);
  }

  const incident = event.data;
  const title = incident.title || 'Unknown incident';
  const service = incident.service?.summary || 'unknown-service';
  const urgency = incident.urgency || 'high';
  const incidentUrl = incident.html_url || '';
  const createdAt = incident.created_at || '';
  const resolvedAt = incident.resolved_at || new Date().toISOString();

  const orgId = process.env.DEVIN_ORG_ID;
  const response = await fetch(
    `https://api.devin.ai/v3/organizations/${orgId}/sessions`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.DEVIN_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      prompt: [
        `A PagerDuty incident has been resolved. Draft a postmortem.`,
        ``,
        `Incident: "${title}"`,
        `Service: ${service}`,
        `Urgency: ${urgency}`,
        `Created: ${createdAt}`,
        `Resolved: ${resolvedAt}`,
        `Incident URL: ${incidentUrl}`,
        ``,
        `Write a structured postmortem:`,
        `1. Use the Datadog MCP to pull logs and metrics for ${service} during the incident window`,
        `2. Identify the root cause — check for deploys, config changes, or upstream failures`,
        `3. Build a detailed timeline from first alert to resolution`,
        `4. List action items to prevent recurrence`,
        `5. Post the postmortem as a PR to our docs/postmortems/ directory`,
      ].join('\n'),
      tags: ['pagerduty-postmortem', `service:${service}`],
    }),
  });

  const { session_id } = await response.json();
  console.log(`Started postmortem session ${session_id} for: ${title}`);
  res.sendStatus(200);
});

app.listen(3000);
Crea un usuario de servicio en Settings > Service Users de app.devin.ai con el permiso ManageOrgSessions. Copia el token de API que se muestra tras la creación y guárdalo como DEVIN_API_KEY en tu servicio puente. Configura DEVIN_ORG_ID con el ID de tu organización; para obtenerlo, llama a GET https://api.devin.ai/v3/enterprise/organizations con tu token. Configura WEBHOOK_SECRET con un secreto compartido que también configurarás en PagerDuty.
2

Configurar PagerDuty

  1. En PagerDuty, ve a Services > [your service] > Integrations
  2. Haz clic en Add Integration y selecciona Generic Webhooks (v3)
  3. Establece la Webhook URL como el endpoint de tu bridge (p. ej., https://your-bridge.example.com/pagerduty-resolved)
  4. En Custom Headers, agrega X-Webhook-Secret con el mismo valor que almacenaste como WEBHOOK_SECRET
  5. En Event Subscription, filtra por el tipo de evento incident.resolved para que el postmortem se active solo después de que se cierre el incidente
También puedes suscribirte a incident.acknowledged si quieres que Devin empiece a recopilar datos mientras el incidente aún está en curso y luego finalice el postmortem cuando se resuelva.
3

Conectar MCPs de observabilidad (opcional)

Devin redacta mejores postmortems cuando puede acceder a tus datos de telemetría. Habilita uno o más MCP para que Devin pueda extraer datos reales del período del incidente:Datadog MCP — Ve a Settings > MCP Marketplace, busca Datadog, haz clic en Enable e ingresa tus claves de API y de aplicación. Devin consultará registros, métricas, eventos de despliegue y el historial de monitores.Sentry MCP — Busca Sentry en el MCP Marketplace, haz clic en Enable y completa el flujo de OAuth. Devin extraerá detalles de errores, trazas de pila y etiquetas de versión.Una vez conectados, Devin correlaciona automáticamente la telemetría con la cronología del incidente para compilar un postmortem respaldado por evidencias. Obtén más información sobre cómo conectar servidores MCP.
4

Qué genera Devin

Cuando se resuelve un incidente de PagerDuty, Devin analiza el periodo del incidente y redacta un postmortem estructurado:Ejemplo de postmortem que produce Devin:
# Postmortem: Agotamiento del Pool de Conexiones de Base de Datos — orders-service
**Fecha:** 2026-02-10 | **Duración:** 46 minutos | **Severidad:** P1

## Resumen
orders-service experimentó agotamiento del pool de conexiones entre
las 14:32 y las 15:18 UTC, causando errores 502 en aproximadamente el 12% de las
solicitudes de creación de pedidos.

## Cronología
- 14:15 UTC — Deploy #387 publicado (commit e4f29a1)
- 14:28 UTC — El uso del pool de conexiones aumentó del 60% al 92%
- 14:32 UTC — Pool agotado; incidente de PagerDuty activado
- 14:38 UTC — Ingeniero de guardia notificado
- 14:45 UTC — Se identificó que el Deploy #387 agregó una nueva verificación
              de inventario que abre una conexión de BD por línea de pedido
              sin liberarla en el bloque finally
- 15:02 UTC — Reversión al Deploy #386 iniciada
- 15:18 UTC — Pool de conexiones recuperado; incidente resuelto

## Causa Raíz
El Deploy #387 introdujo `checkInventoryAvailability()` en
`src/services/orders.ts:142`. La función abre una nueva conexión de BD
por cada línea de pedido, pero solo la libera en la ruta de éxito.
Cuando las verificaciones de inventario fallan (por tiempo de espera
o falta de stock), las conexiones quedan en fuga.

Los pedidos con 5 o más líneas agotaban el pool de forma consistente en
15 minutos tras el deploy.

## Elementos de Acción
- [ ] Corregir la fuga de conexiones: agregar bloque `finally` para liberar
      la conexión (PR #388 abierto)
- [ ] Agregar monitor de uso del pool de conexiones con alerta al 80%
- [ ] Agregar prueba de integración para pedidos con múltiples líneas con
      fallos de inventario simulados
- [ ] Revisar otros patrones de acceso a BD en busca de fugas similares
5

Personaliza el postmortem

Adapta el pipeline al proceso de postmortem de tu equipo:Usa un Playbook para definir tu plantilla de postmortem: secciones, clasificación por gravedad, campos obligatorios y dónde almacenar el resultado. Pasa un playbook_id en la solicitud a la API para estandarizar cada postmortem.Enruta por gravedad. Agrega lógica en tu bridge para generar postmortems solo para incidentes P1/P2. Es posible que los incidentes de menor gravedad no requieran un informe completo.Agrega Knowledge sobre tu arquitectura, los responsables de los servicios y los incidentes anteriores para que Devin pueda conectar los puntos; por ejemplo, “orders-service depende de inventory-service, que es conocido por problemas de tiempo de espera bajo carga.”Publica en tu wiki. En lugar de hacer commit en un repo, haz que Devin publique el postmortem en Confluence, Notion o tu wiki interna mediante el prompt de la sesión.