Build an AI Incident Timeline Reconstructor with Claude API
Writing an incident timeline after the fact means manually cross-referencing Slack messages, deploy logs, alert timestamps, and PagerDuty events. Build a tool that pulls all of it together and generates an accurate, chronological timeline with Claude API.
Postmortem timelines are almost always reconstructed hours or days after the incident, from memory and scattered sources — which is exactly when details get fuzzy or reordered. This tool pulls the actual timestamped evidence from every system involved and lets Claude assemble it into a coherent, accurate timeline before anyone has to rely on memory.
Setup
pip install anthropic slack-sdk requestsData Collectors
import anthropic
from slack_sdk import WebClient
from datetime import datetime, timedelta
import requests
client = anthropic.Anthropic()
def get_slack_incident_channel_history(channel_id: str, slack_token: str) -> list[dict]:
slack = WebClient(token=slack_token)
history = slack.conversations_history(channel=channel_id, limit=200)
return [
{"timestamp": msg["ts"], "user": msg.get("user", "unknown"), "text": msg.get("text", "")}
for msg in history["messages"]
if msg.get("text")
]
def get_deploy_events(service: str, start: datetime, end: datetime) -> list[dict]:
"""Pull deploy events from your CD system's audit log."""
resp = requests.get(
f"https://cd.internal/api/deployments",
params={"service": service, "since": start.isoformat(), "until": end.isoformat()}
)
return resp.json()["deployments"]
def get_alert_events(start: datetime, end: datetime, pagerduty_token: str) -> list[dict]:
resp = requests.get(
"https://api.pagerduty.com/incidents",
headers={"Authorization": f"Token token={pagerduty_token}"},
params={"since": start.isoformat(), "until": end.isoformat()}
)
return [{"title": i["title"], "created_at": i["created_at"], "status": i["status"]}
for i in resp.json()["incidents"]]
def get_metric_anomalies(service: str, start: datetime, end: datetime) -> list[dict]:
"""Pull relevant metric threshold breaches from Prometheus Alertmanager history."""
resp = requests.get(
"http://alertmanager:9093/api/v2/alerts/history",
params={"filter": f'service="{service}"', "start": start.isoformat(), "end": end.isoformat()}
)
return resp.json()Timeline Reconstruction with Claude
import json
RECONSTRUCT_PROMPT = """Reconstruct an accurate incident timeline from these
raw data sources, all from the same incident window.
Slack channel messages (chronological, with timestamps):
{slack_messages}
Deployment events:
{deploy_events}
PagerDuty alert events:
{alert_events}
Metric anomaly/threshold breach events:
{metric_events}
Build a single, merged, chronological timeline. For each event:
- Exact timestamp
- What happened (be specific — "deploy of api v2.4.1 to production" not "a deploy happened")
- Source (deploy log / alert / human observation from Slack)
Also identify:
- The likely trigger event (what started the incident)
- Time from trigger to first alert (detection time)
- Time from first alert to first human acknowledgment
- Time from acknowledgment to resolution
Format as a clean markdown timeline suitable for a postmortem document."""
def reconstruct_timeline(slack_messages: list, deploy_events: list, alert_events: list, metric_events: list) -> str:
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=3000,
messages=[{
"role": "user",
"content": RECONSTRUCT_PROMPT.format(
slack_messages=json.dumps(slack_messages, indent=2)[:4000],
deploy_events=json.dumps(deploy_events, indent=2),
alert_events=json.dumps(alert_events, indent=2),
metric_events=json.dumps(metric_events, indent=2)[:2000],
)
}]
)
return response.content[0].textExample Output
## Incident Timeline — Payments API Degradation, 2026-07-31
**14:02:15** — Deploy: `payments-api v2.4.1` to production (source: CD log)
**14:04:32** — Metric anomaly: p99 latency crosses 2000ms threshold (source: Alertmanager)
**14:04:58** — PagerDuty alert triggered: "Payments API High Latency" (source: PagerDuty)
**14:07:41** — First human acknowledgment in #incident-payments-api (source: Slack, @priya)
**14:09:03** — Slack: "checking the new deploy, might be the connection pool change" (source: Slack, @priya)
**14:12:30** — Deploy: rollback to `v2.4.0` initiated (source: CD log)
**14:15:47** — Metric anomaly resolved: p99 latency back under 500ms (source: Alertmanager)
**14:16:02** — PagerDuty incident resolved (source: PagerDuty)
**Likely trigger:** Deploy of v2.4.1 at 14:02:15 (2m17s before first anomaly)
**Detection time:** 2m17s (deploy to first alert)
**Acknowledgment time:** 2m43s (alert to human ack)
**Resolution time:** 6m49s (ack to resolution via rollback)Usage
python reconstruct_timeline.py \
--incident-channel C0123ABCDEF \
--service payments-api \
--start "2026-07-31T14:00:00" \
--end "2026-07-31T14:30:00" \
--output timeline.mdWhy This Matters for Postmortem Quality
The value here isn't just saving reconstruction time — it's accuracy. A human reconstructing a timeline from memory two days later reliably compresses or reorders events, especially the gap between "alert fired" and "someone actually looked at it," which is exactly the number most postmortems need to be honest about to drive real process improvements. Pulling from actual timestamped system data removes that memory distortion entirely.
More AI incident response tooling? Read our Build AI incident postmortem generator and Build AI SRE incident commander with Claude API.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
Build an AI ChatOps Incident Bot for Slack with Claude API
Build a Slack bot that turns '/incident api is down' into a full incident channel with a Claude-generated initial assessment, relevant runbook links, and the right people paged automatically.
Build an AI Load Test Scenario Generator with Claude API
Writing realistic k6 or Locust load test scenarios means understanding actual traffic patterns, not just hammering one endpoint. Build a tool that reads your API spec and real traffic logs, then generates realistic load test scripts with Claude API.
Build an AI Runbook Generator with Claude API and Git History
Auto-generate incident runbooks from your git history, monitoring alerts, and past incidents using Claude API. Runbooks stay up to date automatically as your code changes — no manual maintenance.