Automate Incident Postmortem Drafting From Logs and Slack
For Data Engineers ·
What This Builds
Close out an incident in PagerDuty and a first-draft postmortem is waiting in Confluence a few minutes later, pulled from the Slack thread and Airflow logs instead of a blank page. Postmortem writing runs 4 to 8 hours per incident when done from scratch, mostly invisible time that never shows up on a sprint board. This automation turns that into a short review and edit pass, and it runs every time without anyone needing to remember to kick it off.
Prerequisites
- Comfortable using an AI chat tool for drafting tasks (Level 1) and at least one dedicated AI tool in your pipeline stack (Level 3)
- Admin or integration access to PagerDuty, Slack, and Confluence (or whatever your team uses for incident tracking, chat, and docs)
- Professional Zapier account ($29.99/month): Sign up - multi-step Zaps with a Paths or Filter step need a paid tier
- A Claude API key for the drafting step. API usage is billed per token rather than a flat subscription, and a single postmortem draft is a small fraction of a cent, but set a monthly spend cap in your Anthropic console so a noisy incident week cannot run up a surprise bill
- Total ongoing cost: your Zapier plan plus metered Claude API usage. Budget the Zapier plan as the fixed cost and treat the API spend as variable but small
The Concept
Think of this Zap as a relay race with four runners. PagerDuty fires the starting gun when an incident closes. Zapier hands the baton to Slack, which fetches the incident thread. Zapier hands it to Airflow's logs (via a webhook or log export step), which adds the technical timeline. The last runner is Claude, which takes everything collected and writes a structured first draft. Nobody has to remember to start the race. It starts itself, every time an incident closes.
Build It Step by Step
Part 1: Connect the trigger
- In Zapier, create a new Zap with PagerDuty as the trigger app.
- Choose the trigger event for an incident changing state to resolved (Zapier lists PagerDuty's incident state-change events; pick the resolved/closed variant).
- Test the trigger against a recently closed incident so you have sample data to map in later steps.
- Add a Filter by Zapier step right after the trigger if you only want this to run for incidents above a certain urgency or a specific service, so a five-minute blip does not generate a postmortem nobody asked for.
Part 2: Pull the context
- Add a Slack action step: Find Message or Get Thread, using the incident's Slack channel or thread ID if PagerDuty passes one, or a channel name convention your team already uses for incident channels.
- Add a step to pull the relevant Airflow log excerpt. If Airflow exposes a REST API or you have a lightweight internal endpoint that returns the failed DAG run's log tail, use Zapier's Webhooks by Zapier > GET action pointed at that endpoint. If you do not have an API for this yet, start with a manual paste field instead (see Variations below) and automate the log pull later.
- Add a Claude action step (Zapier's Claude integration, or a Webhooks POST to the Anthropic API if you prefer direct control over the model and prompt). Map the Slack thread text and log excerpt into the prompt as variables.
Part 3: Draft and post
- Use this system instruction in the Claude step, adjusting the section headers to match your team's postmortem template:
You are drafting a first-pass incident postmortem for a data engineering team. You will receive a Slack thread and a log excerpt. Write a structured draft with these sections: Summary (2-3 sentences), Timeline (bulleted, with timestamps where available), Root Cause (state your confidence level: confirmed, likely, or unclear), Impact (what broke downstream, who was affected), Action Items (bulleted, each with a suggested owner role, not a named person). Do not invent timestamps, names, or root causes that are not supported by the input. If something is unclear from the input, say so directly instead of guessing.
- Add a Confluence action step: Create Page, using a postmortem template page as the parent, and map Claude's draft output into the page body.
- Add a final Slack action step that posts a short message to the incident channel: draft postmortem is ready at [Confluence link], tagging the incident commander.
Real Example: A failed Snowflake load pipeline
Setup: PagerDuty incident closes for a failed nightly Snowflake load. The Zap fires, pulls the #incident-4471 Slack thread (14 messages) and the Airflow task log tail for the failed load_orders_snowflake task.
Input: Slack thread shows the on-call engineer noticing the failure at 2:14am, investigating a warehouse credential expiry, and manually re-running the load at 2:52am. Log excerpt shows the exact authentication error.
Output: A Confluence draft with a Summary noting the nightly orders load failed due to an expired warehouse credential, a Timeline built from the Slack timestamps, a Root Cause marked "confirmed" (the log error is unambiguous), an Impact line noting the orders dashboard was stale for roughly 6 hours, and Action Items suggesting a credential rotation alert be added, tagged to "pipeline on-call owner" rather than a named person.
Time saved: The on-call engineer spends 10 to 15 minutes reviewing and correcting the draft instead of 60 to 90 minutes writing one from a blank page.
What to Do When It Breaks
- Zap runs but the postmortem draft is empty or garbled → Check the field mapping between the Slack/log steps and the Claude prompt. A common cause is a Slack thread that returned no messages because the channel ID mapping was wrong.
- Zap stops firing altogether and nobody notices for two weeks → This is the failure you will not see. Turn on Zapier's built-in Zap health alerts (Zap owner gets an email when a Zap errors repeatedly), and separately, once a month, manually close a test incident and confirm a draft appears. A silent automation is worse than no automation because the team stops writing postmortems by hand, assuming the Zap has it covered.
- Draft includes a root cause that is not actually supported by the log → This means the prompt's instruction to flag uncertainty is not being followed consistently. Tighten the prompt to explicitly require quoting the log line that supports any root cause claim, and treat every "confirmed" root cause as a claim to spot-check against the raw log before publishing.
- Confluence page created in the wrong space or under the wrong parent → Double-check the parent page ID is hardcoded to your postmortem template location, not left to Zapier's default.
Variations
- Simpler version: Skip the automated log pull and have the Zap only pull the Slack thread, with a placeholder section in the draft asking the engineer to paste log details manually.
- Extended version: Add a step that also creates a Jira ticket for each action item automatically, and a scheduled follow-up Zap that pings the assigned owner if the ticket is still open after two weeks.
What to Do Next
- This week: Run the Zap against your last two or three real incidents (retroactively, using historical data) to see how close the draft gets to your team's actual write-up.
- This month: Tune the prompt's section headers to match whatever postmortem template your team already uses, so reviewers are not thrown by an unfamiliar structure.
- Advanced: Connect the "Schedule a Weekly AI Generated Cost and Performance Report" automation so a postmortem's cost impact (if any) feeds into the next scheduled report instead of getting lost.
Advanced guide for Data Engineer professionals. These techniques use more sophisticated AI features that may require paid subscriptions.