37 incidents last week, checkout-api the noisiest
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.
Every Monday: last week's PagerDuty incidents by service and urgency, mean time to acknowledge and resolve, and the noisiest service.
Reads
You get
The card on the right is a sample. Yours shows your own numbers and updates in place every run.
What lands on your board
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.
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.
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.
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.
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.
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.
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.
With BRIEFKIN_TOKEN set, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.
Pick your agent, where the data comes from and how to schedule it; the commands below follow.
One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.
shellcurl -fsSL https://briefkin.dev/skills/pagerduty-weekly-incident-report/install | shAsk Claude Code:
promptRun the pagerduty-weekly-incident-report skillOr paste the prompt instead of installing:
promptUsing the PagerDuty REST API (read only) or the PagerDuty MCP server, list all incidents created last week, Monday to Sunday in my time zone, with service, urgency, title, created and resolved times. If the analytics API is available, use POST /analytics/metrics/incidents/services for the same week to get incidents, mean seconds to first acknowledge and mean seconds to resolve per service; otherwise compute them from the incidents. Do the same for the week before. Report total incidents and high-urgency ones with the change, one row per service, the noisiest service and the alert title that repeated most, incidents that resolved within 5 minutes without an acknowledgement, the number of high-urgency incidents outside 9:00 to 18:00 on weekdays, and the longest incident. End with one suggestion for the retro.Mondays at 9:00, from cron on any machine where Claude Code is signed in:
crontab0 9 * * 1 claude -p "Run the pagerduty-weekly-incident-report skill"Add it with crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.
Connect Briefkin once with curl -fsSL https://briefkin.dev/install | sh and every run lands on your board as a report card. How setup works
SKILL.md---
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
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.
https://mcp.pagerduty.com/mcp (https://mcp.eu.pagerduty.com/mcp for EU accounts), also in Claude's connector directory. It takes a user API key in the header Authorization: Token token=<key>, or OAuth with static client credentials (it doesn't support dynamic client registration). In Claude Code: PAGERDUTY_API_KEY=<key> claude mcp add-json pagerduty '{"type":"http","url":"https://mcp.pagerduty.com/mcp","headers":{"Authorization":"Token token=${PAGERDUTY_API_KEY}"}}'; in Cursor, add the URL under mcpServers in .cursor/mcp.json (guide). Its browse_* tools read incidents, schedules and on-calls, services, teams and logs; its manage_* tools change them. The older self-hosted server is deprecated.PAGERDUTY_API_KEY and send Authorization: Token token=<key> with Accept: application/vnd.pagerduty+json;version=2.The hosted server can't hide its write tools, so the credential decides: a read-only key allows only GET calls, and every manage_* tool fails with it.
Usually because of the time window or the time zone. The report uses Monday 00:00 to Monday 00:00 in your zone and counts incidents by creation time; dashboards may default to UTC or a rolling 7 days. Set time_zone in the prompt to match what your team reads.
Yes. Triggered and acknowledged incidents are counted in the totals and listed with how long they have been open, but they are left out of the mean time to resolve, since they have not resolved yet.
No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a report card, so you can glance at it instead of asking again.
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.
Yes. Switch the data source to "Your browser" and the steps change to the PagerDuty pages themselves: the agent opens app.pagerduty.com/incidents in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.
Skills are free to use with any agent. Briefkin is where their results land: one board for every report, number and question your agents send, with a ping when something needs you.
Free during the open beta. No card.