Inspiration

Every Slack workspace has the same problem: 5 to 20 alert channels that nobody reads. GitHub notifications, Sentry errors, deploy alerts, CI/CD results, Stripe webhooks — they pile up in channels that get muted within a week of creation. Meanwhile, in the human channels, the team talks about what they're working on, makes promises ("I'll fix the auth bug today"), and asks questions nobody follows up on.

These two realities — what the team says and what the machines prove — run side by side but never connect. Managers ask "what happened yesterday?" and get anecdotes. Engineers wonder if anyone noticed their 4-PR afternoon. Commitments quietly expire.

SitRep was built because we realized that the data to answer "what actually happened?" already exists in Slack — it's just scattered across channels that humans don't have the bandwidth to cross-reference. We wanted an agent that could be the one entity in the workspace that reads everything and connects the dots.

What it does

SitRep is a Slack agent that reconstructs team workday narratives by cross-referencing human conversations with machine-generated alerts, then delivers the synthesis as structured, evidence-backed reports.

Core capabilities:

  • Cross-channel correlation engine. SitRep reads alert channels (GitHub, Linear, Sentry, Stripe, CI/CD) and human discussion channels simultaneously. It uses Slack's Real-Time Search API to construct temporal timelines, then correlates conversations to machine events using time windows ($\pm$ 15–120 minutes) and LLM-powered semantic similarity matching. When Sarah says "I'll look into the auth bug" at 9:15am and a fix ships at 10:17am, SitRep connects those dots across three channels automatically.

  • 14 slash commands. /sitrep for current progress, /sitrep yesterday, /sitrep retro for weekly retrospectives, /sitrep incident <keyword> for focused incident timelines, /sitrep postmortem <keyword> for post-mortem generation, /sitrep who <topic> for expert finding, /sitrep @user for individual activity narratives, /sitrep followups for open commitment tracking, and more.

  • Commitment tracking. When someone says "I'll handle that today," SitRep extracts the commitment, stores it, and checks subsequent alert events for evidence of follow-through. Open commitments surface in every report until resolved. The tracking creates accountability through visibility, not nagging.

  • Four report styles. Brief (executive summary), Ops (incident-commander voice), Sitrep (team narrative, the default), and Standup (observational humor grounded in data). Every claim in every style traces back to a specific message timestamp or alert event.

  • Natural language @mentions. Ask @SitRep who knows about the auth service? and it searches channel history to rank experts by evidence. Ask @SitRep what happened with the deploy? and it generates a focused timeline.

  • Channel intelligence. On install, SitRep scans your workspace and classifies every public channel by bot-to-human message ratio. Channels with $>80\%$ bot messages are classified as alert channels. This classification drives the correlation engine — it knows which channels to treat as evidence sources and which as discussion sources.

How we built it

Architecture: SitRep runs on Cloudflare Workers with a Hono HTTP router, using Slack's HTTP event delivery mode (not Socket Mode). The database is Turso (LibSQL) for multi-workspace state. Report generation uses an LLM via OpenRouter. The marketing site is static HTML deployed to Cloudflare Pages.

Data flow:

  1. Channel discovery — On install, SitRep lists all public channels via conversations.list, samples recent messages, and calculates a bot-to-human ratio. Channels are classified as Alert ($>80\%$ bot), Human ($<20\%$ bot), or Hybrid.
  2. Timeline construction — When a report is triggered, SitRep uses the Slack Real-Time Search API to query across all monitored channels for the time window. Alert messages are parsed into structured events (commits, deploys, errors, payments). Human messages are extracted as statements, questions, and commitments.
  3. Temporal correlation — For each human statement, SitRep searches for alert events within a correlation window ($-15$ to $+120$ minutes). Confidence tiers: direct match (same person in both channels), semantic match (topic overlap confirmed by LLM), or temporal proximity (excluded unless patterns repeat).
  4. Report generation — Assembled timelines, open commitments, and previous report context are sent to the LLM with tone-specific system prompts. The output is formatted as Slack Block Kit and delivered to the configured channel.
  5. Feedback loop — Emoji reactions on reports are stored and used to calibrate tone and detail for future reports.

Key technical decisions:

  • Inline database migrations for Workers compatibility (no filesystem access)
  • HMAC-SHA256 signature verification via Web Crypto API
  • Ephemeral loading messages during LLM generation (60-second timeout)
  • Bot user cache for accurate bot/human message classification
  • OAuth install flow supporting multi-workspace deployment

Challenges we faced

Slack's Real-Time Search API has quirks. Search results don't always include bot messages in the way you'd expect. We had to build a bot user cache that maps bot IDs to their app names to reliably distinguish between human messages and alert-channel noise. The classification heuristic went through several iterations before the 80% threshold proved stable.

Temporal correlation is harder than it sounds. A naive time-window approach produces too many false positives. We added semantic similarity checking via the LLM, which improved precision significantly, but it means correlation is computationally expensive. The tiered confidence system (direct match > semantic match > temporal proximity) was the breakthrough — it lets us be aggressive on high-confidence matches while filtering out noise.

Commitment extraction is fuzzy. Natural language is ambiguous. "I'll look into it" might be a commitment or might be a brush-off. We use the LLM for intent classification, which works well for clear commitments but sometimes over-extracts. The feedback buttons help calibrate this over time.

Workers environment constraints. No filesystem, no long-running processes, no native cron beyond Workers Cron Triggers firing hourly. Inline migrations, careful timeout management, and stateless request handling required rethinking patterns that are trivial in a traditional Node.js server.

What we learned

  • The comedy/standup angle from our initial concept evolved into a broader tone system. Humor is great for engagement but not every team wants jokes — having four distinct voices (brief, ops, sitrep, standup) dramatically increased appeal.
  • Channel classification by bot ratio is a surprisingly powerful heuristic. Most workspaces have a clear bimodal distribution: channels are either almost entirely bot messages or almost entirely human messages.
  • The hardest UX problem isn't generating reports — it's making the onboarding flow fast enough that a new user gets value within 60 seconds of installing.

Built With

  • bolt.js
  • cloudflare
  • hono
  • openrouter
  • rts
  • slack
  • slack-agent-builder
  • slack-ai-capabilities
  • slack-block-kit
  • slack-real-time-search
  • typescript
Share this project:

Updates