Skip to content

Notifications

A workspace where every lane event lands in your inbox is unusable. A workspace where no event lands anywhere is dangerous. Notifications are the routing layer in between — they take the firehose of lane events and deliver the slice you actually need to the channel where your team already lives.

SprintLoop ships first-party integrations for Slack, Microsoft Teams, and Discord, plus a generic incoming-webhook target for anything else. The setup is the same shape across all four.

What gets routed

The full lane event taxonomy:

EventFires when
lane.openedA lane is created (manual, from issue, or harness-initiated)
lane.dispatchedThe lane’s harness starts executing
lane.tool_blockedA tool call is denied by scope or policy
lane.review_requestedThe harness signals “ready for review”
lane.review_verdictA reviewer (Architect / Security / QA / custom) emits a verdict
lane.signed_offThe owner approves the lane
lane.mergedThe PR merges on GitHub/GitLab and the lane closes
lane.canceledThe lane is canceled (race loser, manual cancel, timeout)
lane.policy_deniedDispatch was blocked by a policy rule
lane.federation_stampedThe lane’s chain head is signed into the federation root

Plus workspace-scoped events: member.invited, member.joined, policy.updated, audit.exported. Most teams ignore these in their default channels.

Connect Slack

From the workspace web app: Settings → Notifications → Add Slack workspace. The OAuth flow asks for the standard chat:write and incoming-webhook scopes — no admin permissions, no DM read, nothing else.

After install, you’ll be back in SprintLoop with the Slack workspace listed. Click Add channel to wire a routing rule:

  1. Pick the Slack channel (the dropdown only shows channels the bot has been invited to — invite the bot by typing /invite @SprintLoop in the channel first).
  2. Pick the events you want to route (default: lane.review_requested, lane.merged, lane.policy_denied).
  3. Optional filters: scope to a repo, scope to a specific reviewer’s verdicts, scope to lanes owned by certain users.
  4. Save.

The bot posts a one-time confirmation message in the channel so you know routing is live.

What the Slack payload looks like

A lane.review_requested event lands as:

🔵 Lane ready for review: Refactor auth refresh logic

Owner: @alex · Repo: acme/payments · Harness: Claude Code · Diff: +124 / −38 · Files: 7

Reviewer verdicts: Architect ✅ · Security ✅ · QA ⚠️ (coverage drop in auth/refresh.ts)

Approve · Open

The buttons are not just links — they’re Slack interactive components. Clicking Approve in Slack signs off on the lane (after a confirmation modal); the action is signed by your Slack identity tied to your SprintLoop account.

A lane.policy_denied event lands as a red attachment with the rule name, the lane’s brief, and a link to the policy editor.

Connect Microsoft Teams

Teams uses the Incoming Webhook connector. From SprintLoop: Settings → Notifications → Add Teams channel.

You’ll be asked to paste a Teams incoming webhook URL. To get one: in the Teams channel, click the three-dot menu → ConnectorsIncoming WebhookConfigure. Name it “SprintLoop” and copy the URL.

Paste it into SprintLoop. The same per-event filters apply.

Teams doesn’t support interactive message buttons the same way Slack does, so the Approve button is a deep link to the workspace approval page rather than an inline action. Otherwise the payload is equivalent.

Connect Discord

Discord also uses incoming webhooks. Server settings → Integrations → Webhooks → New Webhook. Copy the URL.

In SprintLoop: Settings → Notifications → Add Discord channel. Paste the URL. Pick events. Save.

Discord renders the lane-event embeds in its native rich-embed style. Verdict checkmarks become Discord emoji; the diff size and reviewer summary land in the embed footer.

Generic incoming webhooks

For anything else — a custom Slack-compatible bot, an internal status board, a PagerDuty-on-policy-denied flow — use Settings → Notifications → Generic webhook.

Paste any HTTPS URL. Pick events. SprintLoop sends a JSON POST per event with this shape:

{
"event": "lane.review_requested",
"ts": "2026-05-09T14:31:08.221Z",
"workspace": "acme",
"lane": {
"id": "ln_2K8m...",
"title": "Refactor auth refresh logic",
"owner_email": "alex@acme.test",
"repo": "acme/payments",
"harness": "claude-code",
"diff": { "additions": 124, "deletions": 38, "files_changed": 7 },
"verdicts": [
{ "reviewer": "architect", "verdict": "approve", "confidence": 0.92 },
{ "reviewer": "security", "verdict": "approve", "confidence": 0.88 },
{ "reviewer": "qa", "verdict": "has_questions", "confidence": 0.71,
"rationale": "Coverage delta -2.4% on auth/refresh.ts" }
],
"url": "https://app.sprintloop.ai/lanes/ln_2K8m..."
},
"signature": "v1=..."
}

Every webhook payload is signed with HMAC-SHA256 over the raw body. The signing secret is shown once at creation; verify the X-SprintLoop-Signature header on your end before trusting the payload.

Filter recipes

A few filter combinations worth copying:

  • High-signal #engineering channel. lane.review_requested AND lane.merged AND lane.policy_denied. Skip everything else.
  • Security on-call channel. All events filtered to lanes that touched **/auth/**, **/billing/**, or any path under the policy file’s require.reviewer: security rules.
  • Race-only channel. lane.dispatched AND lane.canceled filtered to lanes that are part of a race. Useful for tuning racing.
  • PagerDuty-on-policy-denied. Send lane.policy_denied to a generic webhook pointing at PagerDuty’s events API. Fires a low-urgency incident; useful in regulated workspaces.

Rate limits

Slack and Teams rate-limit incoming webhooks at ~1 req/sec. SprintLoop coalesces bursts: if 12 lane events fire in 1 second, they get batched into a single message with one summary header and 12 line items. The batch threshold is configurable (default: coalesce within a 5-second window).

For generic webhooks, no batching is applied by default — each event is a separate POST. If you need batching, set batch_window_seconds on the channel config.

What’s not in v1

We don’t yet support email notifications (use generic webhooks → SendGrid for now), SMS, or in-app push to mobile devices outside of the SprintLoop iOS/Android apps. Those are on the roadmap; the rate-limit story for SMS in particular needs more thought.