Inspiration
Security operations centers drown in alerts. The dangerous ones look identical to the noise until someone spends fifteen minutes gathering context: is this IP known-bad? Has it hit us before? What asset did it touch, and who owns the response? I wanted an agent that does that first fifteen minutes automatically, inside Slack, where the team already lives.
What it does
When an alert fires (Splunk webhook, GitHub webhook, or /simulate-alert), the agent:
- Enriches the source IP against VirusTotal and AbuseIPDB in parallel
- Correlates it with past incidents from the same IP — including incidents from previous sessions, found by searching Slack message history with the Real-Time Search API
- Computes a deterministic 0–100 risk score with an auditable factor breakdown (threat intel signals, asset criticality, correlation count)
- Runs LLM triage that returns severity, summary, response playbook, and a routing decision — with the risk score acting as a floor so a weak model response can never bury a high-evidence incident
- Routes an interactive incident card to the right severity channel, with the matching runbook pulled from an MCP server
Analysts then investigate conversationally: the agent lives in Slack's AI assistant panel with suggested prompts, answers questions like "which incident has the highest risk score?" grounded in live incident data, and can be @mentioned in any channel. A live dashboard shows KPIs, incident detail
How we built it
Node.js with Bolt and Express on Railway. Webhooks are authenticated (shared secret for Splunk, HMAC signature verification for GitHub), enrichment calls run in parallel, and incidents persist to disk so correlation survives restarts. Triage uses DeepSeek in JSON mode with validated output. The runbook MCP server is a separate deployed service, keeping response procedures decoupled from the agent. The dashboard is a single self-contained page served by the same process.
Challenges we ran into
- Trusting an LLM with severity decisions. Free-text triage parsing failed silently when the model drifted. I switched to JSON mode with strict validation, then added the deterministic risk floor — the model can escalate beyond the evidence, but never downgrade below it.
- Slack's scope-vs-event model. The assistant panel greeted users but ignored their messages:
im:history(the permission) was granted, butmessage.im(the event subscription) wasn't — two different settings pages for one feature. - Deployment archaeology. A hardcoded port worked until it didn't: Railway's domain kept forwarding to port 3000 after the app moved to the injected
PORT, producing 502s that looked exactly like a Slack outage. - Secret hygiene. An early commit leaked an
.envfile; fixing it properly meant rotating credentials and rebuilding the git history, not just deleting the file.
Accomplishments that we're proud of
- The full loop works end to end — a webhook fires and seconds later a triaged, enriched, scored incident card lands in the right Slack channel with working buttons. No mocked steps: real VirusTotal and AbuseIPDB lookups, real LLM triage, real routing.
- The agent has a memory. Correlation works across restarts by searching Slack's own message history through the Real-Time Search API — the workspace itself becomes the incident database. Firing two alerts from the same IP and watching the second one say "linked to 1 prior incident, possible multi-stage campaign" still feels like magic.
- A risk score you can argue with. Every score comes with its receipts — "VirusTotal: 13 engines (+30) · Tor exit node (+10) · 2 correlated incidents (+20)" — so an analyst can disagree with a number instead of a black box.
- The LLM is a colleague, not an oracle. The deterministic floor means the model adds reasoning and readable summaries but can never bury a high-evidence incident, which made us comfortable letting it route real alerts.
- Asking the agent questions actually works. "Which incident needs attention first?" gets a grounded, specific answer citing incident IDs — built on Slack's assistant surface with suggested prompts and live status.
- It survived its own security review. Authenticated webhooks, HMAC verification, token-guarded dashboard, timing-safe comparisons, and a credential rotation after we caught our own early mistake.
What we learned
Hybrid scoring beats pure LLM judgment for anything with consequences — the deterministic layer gives you auditability and a safety floor, while the LLM adds reasoning and readable explanations on top. And Slack's agent surface turns a notification bot into something people can actually interrogate.
What's next for Next-Gen SOC
Response actions through MCP (block an IP, isolate a host, open a ticket), richer asset context from an inventory tool, and multi-workspace OAuth for a Marketplace listing.
Built With
- abuseipdb
- block-kit
- bolt
- deepseek
- express.js
- javascript
- mcp
- node.js
- railway
- slack
- virustotal
Log in or sign up for Devpost to join the conversation.