DEV Community

Cover image for # Bug Ticket Agent — AI-Powered Sentry Triage into Notion
Steven Nguyen
Steven Nguyen

Posted on

# Bug Ticket Agent — AI-Powered Sentry Triage into Notion

Notion MCP Challenge Submission 🧠

Bug Ticket Agent — AI-Powered Sentry Triage into Notion

This is a submission for the Notion MCP Challenge.


What I Built

Every time an error fires in production, someone on your team has to open Sentry, read through the stack trace, decide how urgent it is, and manually write a ticket. That happens at 2am. People skip steps. Duplicates pile up.

Bug Ticket Agent automates the entire triage workflow. It listens for Sentry webhooks, runs a Claude AI agent to analyze each error, and writes a structured, prioritized ticket directly into a Notion database — including deduplication, AI-generated summaries, and suggested fixes.

Key Capabilities

  • Automatic intake — receives Sentry webhook events and queues them for processing
  • Intelligent deduplication — searches Notion before creating anything; updates existing tickets instead of duplicating
  • AI priority assignment — Claude assigns P0–P3 based on environment, user impact, and frequency
  • Structured tickets — every ticket gets an error type, stack trace, affected users, AI summary, and a concrete fix suggestion
  • Escalation alerts — P0/P1 production errors are flagged immediately for PagerDuty/Slack wiring
  • Queue-based processing — serialized job queue prevents race conditions when Sentry fires bursts of events

Demo

[Terminal A — server running]
🐛 bug-ticket-agent running on http://localhost:3000

[Terminal B — send a P0]
$ npm run demo -- --scenario p0

→ Webhook received: "TypeError: Cannot read properties of undefined (reading 'charge')"
→ Triage started...
→ Searching Notion for duplicates... none found
→ Assigning priority: P0 (payment service, 247 affected users, production)
→ Writing summary and suggested fix...
→ Creating Notion ticket... ✓ page_id: abc123

⚠️  ESCALATION ALERT: P0 detected in production — notify on-call immediately

[Notion database — ticket appears]
Title:    TypeError: Cannot read properties of undefined (reading 'charge')
Priority: P0
Env:      production
Users:    247
Summary:  "Payment processing failed due to a null reference on the charge object..."
Fix:      "Add a null check for stripe.charge in src/payments/processor.ts:88"
Enter fullscreen mode Exit fullscreen mode
[Send the same error again]
$ npm run demo -- --scenario duplicate

→ Searching Notion for duplicates... found existing ticket (page_id: abc123)
→ Updating frequency: 12 → 18 occurrences, last seen: now
→ Done. No duplicate created.
Enter fullscreen mode Exit fullscreen mode

Show Us the Code

GitHub: bug-ticket-agent

Sentry Webhook
     │
     ▼
Express Server  ──→  Job Queue (serialized)
                          │
                          ▼
                   Claude Triage Agent
                    ├── Search Notion (duplicate check)
                    ├── Assign P0–P3 priority
                    ├── Write summary + fix suggestion
                    └── Create or Update Notion page
                              │
                              ▼
                       Notion Database
                     (Bug Tracker, live)
Enter fullscreen mode Exit fullscreen mode

Tech stack: TypeScript · Express · Claude claude-sonnet-4-6 · Notion MCP Server · Zod


How I Used Notion MCP

1. Claude Discovers Tools at Runtime

Instead of hardcoding Notion API calls, I spin up the official Notion MCP server over stdio and let Claude fetch the available tools on startup. Claude then decides which tools to call and in what order — search-database, create-page, update-page — based on what it finds.

This means zero Notion API wrapper code on my end. If Notion adds new MCP tools, the agent gets them for free.

2. Deduplication via MCP Search

The first thing Claude does in every triage loop is call the Notion search tool with the error title. If it finds a matching ticket, it updates frequency and last-seen instead of creating a new one. This logic lives entirely in the agent prompt — not in hand-written code:

1. Search the database for an existing ticket matching this error title.
2. If duplicate found: update frequency and last seen. Report the page ID.
3. If no duplicate: assign priority, write summary and fix, create a new page.
Enter fullscreen mode Exit fullscreen mode

3. Structured Tickets via MCP Create

When Claude creates a ticket, it maps the error data to Notion's property schema — priority as a select, environment as a multi-select, stack trace as a code block, summary and fix as rich text. The Notion MCP server handles all the property formatting; Claude just fills in the values.

4. The Priority Rubric

Claude doesn't guess — it applies a deterministic rubric from the system prompt:

Priority Criteria
P0 Production down, data loss, auth/payment broken, or >100 affected users
P1 Major feature broken, >10 affected users, recurring in production
P2 Minor degradation, <10 users, workaround exists, or staging
P3 Cosmetic, single user, dev environment, very low frequency


What This Unlocks

Before this: an engineer gets paged, opens Sentry, reads the error, manually creates a Notion ticket, assigns a priority based on gut feel, and hopes they didn't miss a duplicate.

After this: the ticket is already in Notion by the time the engineer opens Slack. It has a priority, a summary, a suggested fix, and no duplicate. The engineer can go straight to fixing instead of triaging.

The Notion MCP server made this possible without building a custom Notion integration. Claude handled all the tool orchestration — I just described what I wanted in the system prompt.

Top comments (1)

Collapse
 
muhammad_tahir_hasni profile image
Muhammad Tahir Hasni

Nice