---
name: pagerduty-weekly-incident-report
description: "Every Monday: last week's PagerDuty incidents by service and urgency, mean time to acknowledge and resolve, and the noisiest service. Use when the user asks for this, or when it runs on a schedule."
---

# PagerDuty weekly incident report

Every Monday: last week's PagerDuty incidents by service and urgency, mean time to acknowledge and resolve, and the noisiest service.

The on-call handoff usually starts with "it was a rough week" and no numbers. PagerDuty has them, spread across the incidents list and the analytics pages, and the question people actually ask in the retro (which service woke us up, and was it the same alert every time) takes a few exports to answer.

The agent pulls last week's incidents and the per-service response metrics, compares them with the week before, and finds the service and alert that caused the most interruptions. It also counts pages outside working hours, the number that tells you whether on-call is sustainable.

## Two ways to get the data

Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.

## Route A: API or MCP server

### What you need

- A PagerDuty read-only REST API key (or a user token) in `PAGERDUTY_TOKEN`. The analytics endpoints depend on your PagerDuty plan; without them the agent computes the averages from the incidents list.
- Or a PagerDuty MCP server: the hosted one at `https://mcp.pagerduty.com/mcp`, or the open source `pagerduty-mcp-server`, whose `list_incidents` and `get_incident` tools are read only by default.

If something is missing, say what and stop; do not invent numbers.

### Steps

1. **List last week's incidents** (PagerDuty): `GET https://api.pagerduty.com/incidents?since=<last Monday 00:00>&until=<this Monday 00:00>&statuses[]=triggered&statuses[]=acknowledged&statuses[]=resolved&limit=100&time_zone=<your zone>`, paging with `offset`. Keep `service.summary`, `urgency`, `created_at`, `title` and `status`.
2. **Get response metrics per service** (PagerDuty): `POST https://api.pagerduty.com/analytics/metrics/incidents/services` with `filters: {created_at_start, created_at_end}` for the same week returns `total_incident_count`, `mean_seconds_to_first_ack` and `mean_seconds_to_resolve` per service. Repeat for the week before.
3. **Find the noise**: Group incidents by service and by title. A title that repeats five or more times, or incidents resolved within five minutes without anyone acknowledging, point to an alert that needs tuning rather than a real outage.
4. **Count the off-hours pages**: Count high-urgency incidents created outside 9:00 to 18:00 on weekdays in your time zone, and on weekends. Compare with the week before.
5. **Report**: Totals and the weekly change, one row per service, the noisiest service and its repeating alert, and the off-hours count. Name the longest incident with its duration.

## Route B: the browser

### What you need

- Signed in to PagerDuty with at least the Observer or Responder role on the account; Analytics pages need a role that can view them and a plan that includes Analytics.

If something is missing, say what and stop; do not invent numbers.

### Steps

Start at https://app.pagerduty.com/incidents. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.

1. **Open the Incidents list for last week**: PagerDuty lives on your own subdomain (`<account>.pagerduty.com`); the link lands there once you are signed in. On **Incidents**, set the status filter to **All** and the date filter to a custom range from last Monday 00:00 to this Monday 00:00 in your time zone, and keep **Urgency** at all.
2. **Export the week**: The list paginates, so click **Export CSV** at the bottom of the table and read the file: service, urgency, title, created, acknowledged and resolved times, and status. Repeat for the week before, or widen the range to two weeks and split the rows.
3. **Read the response metrics**: Open **Analytics** > **Insights**, set the same date range, and read the **Services** table for incidents, mean time to acknowledge and mean time to resolve per service. If Analytics is not on your plan, compute them from the CSV timestamps.
4. **Find the noise and the off-hours pages**: From the CSV, group by service and by title. A title repeating five or more times, or incidents resolved within five minutes with no acknowledgement, is an alert to retune. Count high-urgency incidents created outside 9:00 to 18:00 on weekdays and on weekends.
5. **Report**: Totals with the weekly change, one row per service, the noisiest service and its repeating alert, the off-hours count and the longest incident with its duration, plus one suggestion for the retro.

Note: The Incidents page shows 25 to 100 rows at a time, so the CSV export is the reliable way to get a full week. Insights numbers can differ from a hand count because Analytics uses its own time zone setting and excludes incidents still open from resolution times. Analytics is not included on every plan.

## The report

- **Incidents** last week, high and low urgency, with the change.
- **Per service**: incidents, mean time to acknowledge, mean time to resolve.
- **Noisiest service** and the alert that repeated most.
- **Off-hours pages** and the longest incident.
- One suggestion for the retro, such as an alert to retune.

## Post it to Briefkin

When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.

```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
  -H "authorization: Bearer $BRIEFKIN_TOKEN" \
  -H "content-type: application/json" \
  -d @- <<'JSON'
{
  "v": 1,
  "event_id": "pagerduty-weekly-incident-report/<date of this run, e.g. 2026-10-16>",
  "item_key": "pagerduty-weekly-incident-report",
  "project": "Acme",
  "source": "PagerDuty weekly incident report skill",
  "kind": "update",
  "title": "37 incidents last week, checkout-api the noisiest",
  "summary": "**37** incidents, up from 29, and **12** were high urgency. **11** paged someone outside working hours. checkout-api raised 14, nine of them the same latency alert.",
  "widget": [
    {
      "type": "Grid",
      "props": {
        "columns": 3
      },
      "children": [
        {
          "type": "Stat",
          "props": {
            "label": "Incidents",
            "value": 37,
            "delta": 27.6,
            "better": "lower"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Mean time to ack",
            "value": "6m 40s"
          }
        },
        {
          "type": "Stat",
          "props": {
            "label": "Mean time to resolve",
            "value": "48m"
          }
        }
      ]
    },
    {
      "type": "Table",
      "props": {
        "columns": [
          "Service",
          "Incidents",
          "High",
          "MTTA",
          "MTTR"
        ],
        "align": [
          "left",
          "right",
          "right",
          "right",
          "right"
        ],
        "rows": [
          [
            "checkout-api",
            14,
            5,
            "4m 10s",
            "22m"
          ],
          [
            "payments-worker",
            9,
            3,
            "7m 30s",
            "1h 05m"
          ],
          [
            "search",
            6,
            2,
            "9m 05s",
            "51m"
          ],
          [
            "auth",
            5,
            1,
            "5m 20s",
            "38m"
          ],
          [
            "data-pipeline",
            3,
            1,
            "11m 40s",
            "2h 12m"
          ]
        ]
      }
    },
    {
      "type": "Callout",
      "props": {
        "text": "Nine checkout-api incidents were \"p95 latency above 600 ms\" and resolved on their own within 5 minutes. Raising the threshold or the evaluation window would cut most of them.",
        "tone": "warn"
      }
    }
  ]
}
JSON
```

Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.

## Run it on a schedule

Suggested: Mondays at 9:00 (`0 9 * * 1`). From cron, with the agent signed in on that machine:

```bash
0 9 * * 1 claude -p "Run the pagerduty-weekly-incident-report skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```

Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/pagerduty-weekly-incident-report#schedule

Source: https://briefkin.dev/skills/pagerduty-weekly-incident-report
