> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Auto-Triage Sentry Errors

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Auto-Triage Sentry Errors" description="Wire Sentry webhooks to the Devin API to auto-triage each new production error." prompt="Help me set up a Sentry-to-Devin auto-triage pipeline. Follow the guide at https://docs.devin.ai/use-cases/gallery/api-sentry-auto-triage and walk me through each step: enabling the Sentry MCP, creating the internal integration, and deploying the webhook handler." category="Incident Response" features="API, MCP" />

<div className="uc-detail-wrapper">
  <Tip>For a more detailed Sentry integration guide, [click here](/enterprise/integrations/sentry).</Tip>

  <Steps>
    <Step title="Enable the Sentry MCP">
      Devin needs access to your Sentry account so it can pull stack traces, breadcrumbs, and event metadata during triage.

      1. Go to **Settings > Connections > MCP servers** and find **Sentry**
      2. Click **Enable** and complete the OAuth flow with the Sentry account that has access to your projects
      3. Test the connection — start a session and ask Devin to list recent issues in one of your projects

      Once connected, Devin can query any Sentry project your account has access to: issue details, full stack traces, event breadcrumbs, release tags, and more. See the [MCP Marketplace docs](/work-with-devin/mcp) for setup details.
    </Step>

    <Step title="Create a Sentry Internal Integration">
      Sentry delivers webhooks through Internal Integrations. In your Sentry dashboard, go to **Settings > Developer Settings > Custom Integrations** and click **Create New Integration > Internal Integration**.

      Configure it:

      * **Name:** `Devin Auto-Triage`
      * **Webhook URL:** A service you'll deploy in the next step (e.g., `https://your-domain.com/sentry-webhook`)
      * **Alert Rule Action:** Toggle **on** — this makes the integration available as an action in alert rules
      * **Permissions:** Read access to **Issue & Event** and **Project**

      Save the integration, then create an alert rule. Go to **Alerts > Create Alert Rule > Issue Alert** for your project:

      * **When:** A new issue is created
      * **If:** The issue has more than **50** events in **1 hour** (adjust to your traffic)
      * **Then:** Send a notification via **Devin Auto-Triage**
    </Step>

    <Step title="Wire the webhook to the Devin API">
      Build a small handler that receives Sentry's alert payload and starts a Devin session. Create a [service user](/api-reference/v3/overview) in **Settings > Service Users** with `ManageOrgSessions` permission and store its token as `DEVIN_API_KEY` in your handler's environment. Set `DEVIN_ORG_ID` to your organization ID — get it by calling `GET https://api.devin.ai/v3/enterprise/organizations` with your token.

      ```javascript theme={null}
      const express = require('express');
      const app = express();
      app.use(express.json());

      app.post('/sentry-webhook', async (req, res) => {
        const event = req.body.data?.event;
        if (!event) return res.sendStatus(200);

        const orgId = process.env.DEVIN_ORG_ID;
        const response = await fetch(
          `https://api.devin.ai/v3/organizations/${orgId}/sessions`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${process.env.DEVIN_API_KEY}`,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            prompt: [
              `A Sentry alert fired for a new issue: "${event.title}"`,
              `Culprit: ${event.culprit}`,
              `Sentry URL: ${event.web_url}`,
              ``,
              `Use the Sentry MCP to pull the full stack trace and breadcrumbs.`,
              `Identify the root cause, fix the issue, and open a PR with a`,
              `regression test.`,
            ].join('\n'),
            tags: ['sentry-auto-triage', `project:${event.project}`],
          }),
        });

        const { session_id } = await response.json();
        console.log(`Started Devin session ${session_id} for: ${event.title}`);
        res.sendStatus(200);
      });

      app.listen(3000);
      ```

      Deploy this anywhere that can receive HTTPS traffic — a Cloudflare Worker, AWS Lambda, or a small VPS. Point your Sentry Internal Integration's webhook URL to it.

      The code above tags each session with `sentry-auto-triage` and the Sentry project name. This lets you filter these sessions in the Devin dashboard and [pull them via the API](/api-reference/v3/sessions/get-organizations-sessions) using the `tags` query parameter — useful for tracking how many errors Devin triages per project.

      To verify the pipeline works, trigger a test alert in Sentry (or lower your threshold temporarily), then check [app.devin.ai](https://app.devin.ai/?utm_source=docs\&utm_medium=use-case-gallery) for a new session tagged `sentry-auto-triage`.
    </Step>

    <Step title="What Devin does with each alert">
      When a new error crosses your threshold and the webhook fires, Devin starts a session and works through the issue:

      1. **Queries Sentry via MCP** — pulls the full stack trace, breadcrumbs (user actions leading to the crash), affected browser/OS/release tags, and event frequency
      2. **Traces the root cause** — reads the source file at the exact line from the stack trace, follows the data flow to understand why the value is `undefined` or `null`
      3. **Writes a targeted fix** — implements error handling (optional chaining, default values, input validation) that matches your codebase's existing patterns
      4. **Adds a regression test** — creates a test case that reproduces the original crash scenario and verifies the fix prevents it
      5. **Opens a PR** — links the Sentry issue URL in the PR description so reviewers can cross-reference the original error context and event volume

      Example PR description:

      ```
      Fix: TypeError in UserProfile when user.profile is null

      Root cause: The /api/users/:id endpoint returns { profile: null }
      for users who haven't completed onboarding. UserProfile.tsx:47
      destructures email from user.profile without a null check.

      Fix: Added optional chaining and a fallback state.
      Test: Added test for users with null profile — verifies the
      component renders "Complete your profile" instead of crashing.

      Sentry issue: FRONTEND-1892 (340 events in the past hour)
      ```
    </Step>

    <Step title="Sharpen triage with playbooks and Knowledge">
      Once the pipeline is running, make the auto-triage smarter:

      **Create a triage playbook.** Start from the [`!triage` template playbook](https://app.devin.ai/settings/playbooks/14fed18b89d44713a26e673cf258f548?utm_source=docs\&utm_medium=use-case-gallery) — duplicate it and customize with your team's error-handling conventions (error boundaries, null check patterns, logging format). Then pass the playbook ID in your webhook handler by adding `"playbook_id": "your-playbook-id"` to the request body. You can also ask Devin to generate a playbook from a description of your triage workflow.

      **Add [Knowledge](/product-guides/knowledge)** about your API contracts and known edge cases — e.g., "Responses from `/api/users` may return `{ profile: null }` for users who haven't completed onboarding. Always guard against this." Ask Devin to help you write Knowledge entries from your existing documentation. The more context Devin has about your domain, the more accurate its fixes.

      **Scope alerts carefully.** Use Sentry's alert rule conditions to limit which errors trigger Devin — filter by project, environment (`production` only), or error volume. A good starting point: only fire for issues with 50+ events in the first hour to focus on high-impact errors.

      **Set up a weekly review schedule.** Create a [schedule](https://app.devin.ai/settings/schedules/create?utm_source=docs\&utm_medium=use-case-gallery) that runs once a week to review the outcomes of your auto-triage sessions and feed learnings back into your playbook and Knowledge:

      <PromptBlock type="schedule">
        ```txt Weekly Sentry auto-triage review theme={null}
        Review all Devin sessions tagged "sentry-auto-triage" from the past week.
        For each session, check:

        1. PR outcome — was it merged, closed without merging, or still open?
        2. Sentry issue status — was it marked as resolved/fixed, ignored, or dismissed?
        3. Any reviewer comments or requested changes on the PR

        Based on these signals:
        - If PRs were consistently closed or had the same feedback (e.g., "don't use
          optional chaining here, use an explicit guard"), update the !sentry-triage
          playbook with that convention
        - If Devin missed context that led to a bad fix, add a Knowledge entry
          covering that domain area (e.g., API contracts, service dependencies)
        - Summarize: how many sessions ran, how many PRs merged vs closed, and
          any patterns in the feedback

        Post the summary to #engineering-ops on Slack.
        ```
      </PromptBlock>
    </Step>
  </Steps>
</div>
