Skip to content

End-to-End Walkthrough

This walkthrough follows a concrete scenario through every node of the Triage workflow. The goal is to show you exactly what SWEny does at each step, what tools it calls, and what decisions it makes.

Your payment service starts throwing NullReferenceError at 2 AM. By 6 AM, Sentry has recorded 312 occurrences. Your SWEny triage workflow runs on schedule:

on:
schedule:
- cron: '0 6 * * 1-5' # weekdays at 6 AM UTC

GitHub fires the workflow. SWEny starts the Triage DAG from the gather entry node.

Instruction: Gather all relevant context — errors from observability, recent commits from source control, similar issues from the tracker.

Skills active: github, sentry, linear

Claude makes the following tool calls:

ToolWhat it does
sentry_list_issuesPulls unresolved issues for the project — finds the NullReferenceError in WebhookHandler.process() with 312 occurrences
sentry_get_issue_eventsFetches the last 10 events with full stack traces — the crash happens on event.payload.metadata.refundId
github_list_recent_commitsLists the last 10 commits on main — finds a deploy 8 hours ago that touched src/webhooks/WebhookHandler.ts
github_search_codeSearches for WebhookHandler to understand the file’s role
linear_search_issuesSearches for “NullReferenceError WebhookHandler” — finds no matching open issues

The node produces structured context: error details, stack traces, recent deploys, and the result of the duplicate search. This context is passed to the next node.

Instruction: Correlate the error with recent changes, identify the root cause, assess severity, determine if this is a duplicate.

Skills active: github

Claude reads the context from Node 1 and works through the analysis:

ToolWhat it does
github_get_fileReads src/webhooks/WebhookHandler.ts at the current HEAD — sees event.payload.metadata.refundId accessed without a null check
github_get_fileReads the same file at the commit before the deploy — confirms the access was added in the recent deploy

Claude produces structured output:

{
"root_cause": "WebhookHandler.process() accesses event.payload.metadata.refundId without null-checking metadata. Refund webhooks from Stripe do not include the metadata field.",
"severity": "high",
"affected_services": ["payment-api"],
"is_duplicate": false,
"recommendation": "Add a null guard on event.payload.metadata before accessing refundId",
"fix_approach": "Add optional chaining and an early return when metadata is missing"
}

The executor evaluates outgoing edges from investigate:

  • Edge 1: when: "The issue is novel (not a duplicate) and severity is medium or higher" — target: create_issue
  • Edge 2: when: "The issue is a duplicate of an existing ticket, or severity is low" — target: skip

Claude reads the structured output — is_duplicate: false, severity: "high" — and picks Edge 1. Execution routes to create_issue.

Instruction: Create an issue with root cause, severity, affected services, reproduction steps, and recommended fix.

Skills active: linear, github

ToolWhat it does
github_create_issueCreates a GitHub Issue with the full root cause analysis

The created issue looks like:

NullReferenceError in WebhookHandler.process() on refund webhooks

Severity: High Service: payment-api Occurrences: 312 in last 24h

Root cause: WebhookHandler.process() accesses event.payload.metadata.refundId without null-checking metadata. Refund webhooks from Stripe do not include the metadata field, causing a crash on every refund event.

Introduced by: commit a1b2c3d (deployed 8 hours ago)

Recommended fix: Add optional chaining on event.payload.metadata and an early return when metadata is missing. Add a test case for refund webhook payloads.

Labels: bug, severity:high, payment-api

Instruction: Send a notification with the alert summary, severity, root cause, and a link to the created issue.

Skills active: slack, notification

If Slack is configured, Claude calls slack_send_message with a summary. If not, the GitHub Actions summary serves as the default notification.

ToolWhat it does
slack_send_messagePosts a summary to the configured Slack channel

The Slack message:

SWEny Triage: payment-api

Severity: high Root cause: NullReferenceError in WebhookHandler — missing null check on metadata for refund webhooks. Issue: #142 Occurrences: 312 in last 24h

The workflow ends. No more outgoing edges.

Regardless of notification provider, SWEny always writes a structured summary to the GitHub Actions run:

SWEny Triage Summary
─────────────────────────────
Workflow: Alert Triage
Duration: 3m 42s
Nodes run: gather → investigate → create_issue → notify
Top issue: NullReferenceError in WebhookHandler
Service: payment-api
Severity: high
Occurrences: 312 in last 24h
Root cause: Missing null check on event.payload.metadata
Issue: #142
Fix approach: Add optional chaining + test case

If linear_search_issues had found a matching open issue (say ENG-401), the Root Cause Analysis node would have set is_duplicate: true. The routing would have picked Edge 2, and execution would have gone to the skip node — logging a brief note and ending the workflow.

Same result. The edge condition checks both is_duplicate and severity. A low-severity, non-duplicate issue routes to skip rather than clogging your issue tracker with cosmetic bugs.

A typical triage run with investigation-depth: standard:

MetricTypical range
Wall time2-8 minutes
Agent turns5-20 per issue
Token usage10k-50k tokens per issue

With a Claude Max subscription (claude-oauth-token), triage runs are included in your subscription. With an API key, expect roughly $0.10-$0.50 per run at current Sonnet pricing.

To control costs:

  • Set max-investigate-turns to cap investigation depth (default: 50)
  • Use service-filter to focus on specific services (e.g., payment-*)
  • Use time-range: 4h instead of 24h to reduce log volume
  • Use investigation-depth: quick for faster, cheaper runs
  • Use dry-run: true to test without creating issues or PRs
InputWhat it controlsExample values
time-rangeHow far back to scan4h, 24h, 7d
severity-focusError level filtererrors, warnings, all
service-filterLimit to specific servicespayment-*, api-gateway
investigation-depthHow thorough the analysis isquick, standard, thorough
max-investigate-turnsInvestigation turn limit20, 50
novelty-modeSkip already-tracked issuestrue, false
dry-runInvestigate without creating issues/PRstrue, false

See Action Inputs for the complete list.