Incident Response Agent 🚨
Hackathon: Slack Agent Builder Challenge — New Slack Agent Track
Live Demo: Test Sandbox Workspace (Slack App ID: A0B9PQ3PQRW)
Repo: github.com/kyisaiah47/incident-response-agent
Inspiration
When a production system goes down, every second counts — and most of that time gets wasted on coordination overhead. Who's on-call? What channel do we use? What was happening in Slack before this blew up? Incident Response Agent eliminates the coordination tax entirely. One shortcut click and your team has a war room, context, and an on-call engineer paged before anyone has time to panic.
What It Does
Incident Response Agent gives Slack two new superpowers via link triggers:
Declare Incident — a modal collects service name, severity (SEV1/SEV2/SEV3), and a description, then automatically:
- Scans recent Slack messages across engineering channels to surface context about the affected service
- Generates a unique incident ID and creates a dedicated war room channel (e.g.
#inc-sev1-api-gateway-0607-1423) - Pages the on-call engineer via PagerDuty
- Fetches active Datadog monitors for the service and posts them to the war room
- Posts a full context brief so the team hits the ground running in seconds — no manual digging
Resolve Incident — captures root cause and fix description, reads the full war room conversation history, and posts a structured postmortem with timeline, duration, action items, and all human messages — directly to the war room channel.
Every incident is persisted in a Slack Datastore and the status transitions from active to resolved on resolution.
How I Built It
Architecture
Declare trigger (link trigger)
│
▼
IncidentDeclaredWorkflow
├── OpenForm → collect service, severity, description
├── search_context → scan Slack channels for recent activity
├── prepare_incident → generate incident_id, channel name, team_id
├── CreateChannel → Slack built-in (Enterprise Grid-safe)
├── create_war_room → post context brief, invite declarer, save to datastore
├── page_oncall → PagerDuty REST API
└── fetch_metrics → Datadog Monitors API
Resolve trigger (link trigger)
│
▼
IncidentResolvedWorkflow
├── OpenForm → collect root cause, fix description
└── draft_postmortem → read war room history, generate postmortem, update datastore
Datastore: Incidents (incident_id, service, severity, channel_id, declared_by, declared_at, status)
Tech Stack
| Layer | Technology |
|---|---|
| Runtime | Deno |
| Framework | Slack Functions SDK (deno-slack-sdk 2.15.1) |
| Persistence | Slack Datastore |
| Alerting | PagerDuty REST API |
| Monitoring | Datadog Monitors API |
| Deployment | Slack automation platform (slack deploy) |
Slack Platform Integration
The entire app is built natively on the Slack automation platform — no external hosting, no servers:
- Slack Datastore is the sole persistence layer — incident records are stored, queried, and updated entirely within Slack infrastructure. The
draft_postmortemfunction queries bychannel_idto find the matching incident record and mark it resolved. - conversations.list + conversations.history power the context search — the app scans up to 8 engineering channels (general, alerts, incidents, oncall, deployments) for recent messages mentioning the affected service, surfacing them before the team even joins the war room.
- CreateChannel (built-in Slack function) creates the war room — using Slack's native function rather than the API directly ensures the app works on Enterprise Grid workspaces where
auth.testreturns an enterprise ID rather than a workspace team ID. - conversations.history (limit 200) drives the postmortem — the entire war room thread is read, human messages extracted, and a structured markdown postmortem assembled without any external LLM calls.
- Link triggers are the entry points — shareable shortcut URLs that can be pinned in any channel, bookmarked, or shared in runbooks.
Challenges
- Enterprise Grid team_id resolution:
auth.testreturns the enterprise ID (E...) for org-level installs, but the built-inCreateChannelfunction requires the workspace team ID (T...). The fix was to callconversations.infoon the triggering channel and extractcontext_team_idfrom the channel object — the only reliable source of the workspace-level ID. - Graceful degradation: PagerDuty and Datadog are optional. Rather than hard-failing when keys are missing, each function checks for env vars and posts an informational message to the war room instead. The app is fully functional with zero external integrations configured.
- Postmortem without an LLM: The postmortem is assembled from structured inputs (root cause, fix) plus raw war room history — no external AI calls needed. This keeps the app lightweight and eliminates latency on resolution.
What's Next
/incidentslash command as an alternative entry point to the link trigger- Automated severity escalation if the incident exceeds a time threshold without resolution
- PagerDuty escalation policies mapped per service
- Scheduled digest of open incidents posted to a central
#incidentschannel - Integration with Statuspage to auto-update external status on declare/resolve
Team
Built solo by @kyisaiah47 for the Slack Agent Builder Challenge — New Slack Agent Track.
Built With
- datadog
- deno
- pagerduty-api
- slack-automation-platform
- slack-datastore
- slack-functions-sdk
- typescript

Log in or sign up for Devpost to join the conversation.