The Issue Triage System is an automated GitHub Actions workflow that uses Claude Code to categorize and manage labels on GitHub issues. The system analyzes issue content and conversation threads to apply appropriate category labels (bug, enhancement, question), lifecycle labels (needs-repro, needs-info, stale, autoclose), and platform/API labels. It operates in two distinct modes: initial triage when issues are opened, and re-evaluation when comments are added.
For information about duplicate issue detection, see Issue Deduplication System. For stale issue lifecycle management, see Stale Issue Management. For critical issue detection, see Oncall Issue Detection.
The triage system is implemented as a GitHub Actions workflow that executes Claude Code with a structured prompt and restricted tool access.
Workflow Configuration Details
Sources: .github/workflows/claude-issue-triage.yml1-22
The workflow file claude-issue-triage.yml defines the following configuration:
| Configuration | Value | Purpose |
|---|---|---|
| Triggers | issues.opened, issue_comment.created | React to new issues and comments |
| Runner | ubuntu-latest | Execution environment |
| Timeout | 10 minutes (workflow), 5 minutes (Claude step) | Prevent runaway executions |
| Model | claude-opus-4-6 | AI model for triage decisions |
| Concurrency Group | issue-triage-{issue_number} | One triage per issue at a time |
| Cancel in Progress | true | Stop older runs when new event arrives |
The triage system operates with a strictly controlled label vocabulary. Labels are never invented; only pre-defined labels from the allowed list can be applied.
Label Application Rules
Sources: .github/workflows/claude-issue-triage.yml45-51 .github/workflows/claude-issue-triage.yml96-102
The prompt explicitly constrains Claude to only use labels from the allowed list:
The workflow enforces label constraints through the prompt at .github/workflows/claude-issue-triage.yml45-51:
ALLOWED LABELS — you may ONLY use labels from this list. Never invent new labels.
Type: bug, enhancement, question, documentation, duplicate, invalid
Lifecycle: needs-repro, needs-info, stale, autoclose
Platform: platform:linux, platform:macos, platform:windows, platform:wsl, ...
API: api:bedrock, api:vertex
When an issue is first opened (EVENT == "issues"), the triage system performs comprehensive initial categorization.
Validity Check Logic
Sources: .github/workflows/claude-issue-triage.yml65-66
The first step checks if the issue is actually about Claude Code (the CLI/IDE tool). Issues about other Anthropic products receive the invalid label:
When invalid is applied, no other labels are added and processing stops immediately.
Lifecycle Label Application Rules
Sources: .github/workflows/claude-issue-triage.yml72-80
The needs-repro label (7-day timeout) is applied to bug reports that lack clear reproduction steps:
Apply needs-repro When | Do NOT Apply When |
|---|---|
| Bug has no specific steps to reproduce | User provided error messages |
| Cannot follow the narrative description | User provided logs or file paths |
| Traditional repro steps are missing | User described what they did |
| Model behavior issues (examples/patterns sufficient) |
The needs-info label (7-day timeout) is applied to bugs needing additional context:
Apply needs-info When | Do NOT Apply When |
|---|---|
| Missing version information | User already provided version/environment |
| Missing environment details | User already provided error details |
| Maintainer asked follow-up questions | Issue just needs engineering investigation |
| Missing error messages |
Important: Lifecycle labels are only applied to bugs, never to enhancements or questions.
When a comment is added to an existing issue (EVENT == "issue_comment"), the triage system re-evaluates lifecycle labels based on the updated conversation.
Comment Evaluation Rules
Sources: .github/workflows/claude-issue-triage.yml85-94
When processing comment events, the workflow follows these rules:
Stale/Autoclose Removal: Any new human comment automatically removes stale or autoclose labels, indicating the issue is still active
Substantive vs. Non-substantive Comments: The system distinguishes between meaningful information and engagement-only comments:
Substantive (Remove needs-*) | Non-substantive (Keep needs-*) |
|---|---|
| Reproduction steps provided | "+1" or "me too" |
| Error messages/logs shared | "same here" |
| Environment details given | Emoji reactions |
| Answers to maintainer questions | Generic agreement |
Category Label Preservation: On comment events, the system does NOT add or remove category labels (bug, enhancement, question, documentation, duplicate, invalid). These are set only during initial triage.
Lifecycle Label Addition: If a maintainer comment clearly requests information (e.g., "Please provide reproduction steps"), the appropriate lifecycle label can be added even on a comment event.
The triage workflow operates with restricted tool access to ensure safe, predictable behavior.
Tool Restrictions
Sources: .github/workflows/claude-issue-triage.yml104-106
The workflow explicitly restricts Claude Code to only these Bash tool patterns:
--allowedTools "Bash(gh issue view:*),Bash(gh issue edit:*),Bash(gh search issues:*)"
This prevents Claude from executing arbitrary commands or accessing other GitHub features like:
Environment and Authentication
Sources: .github/workflows/claude-issue-triage.yml18-21 .github/workflows/claude-issue-triage.yml30-33
The workflow provides authentication through:
| Environment Variable | Purpose | Source |
|---|---|---|
GH_TOKEN | GitHub CLI authentication | secrets.GITHUB_TOKEN |
github_token | Claude Code Action authentication | secrets.GITHUB_TOKEN |
anthropic_api_key | Claude API access | secrets.ANTHROPIC_API_KEY |
The allowed_non_write_users: "*" setting allows the workflow to run on issues opened by any user, not just repository collaborators.
The workflow implements concurrency control to prevent conflicting label operations when multiple events occur rapidly on the same issue.
Concurrency Configuration
Sources: .github/workflows/claude-issue-triage.yml15-17
This configuration ensures:
Event Filtering
Sources: .github/workflows/claude-issue-triage.yml12-14
The workflow only runs when:
issues.opened, ORissue_comment.created AND issue is not a pull request AND comment author is not a BotThis prevents the workflow from:
The triage system integrates with downstream automation workflows that manage the full issue lifecycle.
| Label Applied | Downstream Workflow | Behavior |
|---|---|---|
needs-repro | Stale Issue Management | Auto-closed after 7 days without response |
needs-info | Stale Issue Management | Auto-closed after 7 days without response |
stale | Stale Issue Management | Warning before closure |
autoclose | Stale Issue Management | Closure scheduled |
duplicate | Issue Deduplication System | Marked as duplicate with comment |
invalid | Manual handling | Repository maintainers review |
Label Removal on Activity
Sources: .github/workflows/claude-issue-triage.yml87-89
The triage system removes lifecycle labels when users respond:
If the issue has `stale` or `autoclose`, remove the label — a new human comment
means the issue is still active
This creates a human-in-the-loop escape hatch where user engagement prevents premature closure even after the grace period has expired.
The triage prompt is embedded directly in the workflow file, making it easy to customize behavior without code changes.
Key Customization Points
Sources: .github/workflows/claude-issue-triage.yml35-103
| Aspect | Location | Customization |
|---|---|---|
| Allowed labels | Lines 45-51 | Add/remove label categories |
| Validity rules | Lines 65-66 | Define what constitutes "invalid" |
| Lifecycle thresholds | Lines 73, 76 | Adjust what triggers needs-* labels |
| Model selection | Line 105 | Change Claude model (currently opus-4-6) |
| Timeout values | Lines 11, 28 | Adjust execution time limits |
| Tool patterns | Line 106 | Expand or restrict gh command access |
Conservative Defaults
Sources: .github/workflows/claude-issue-triage.yml99-102
The prompt emphasizes conservative label application:
GUIDELINES:
- Be conservative with lifecycle labels — only apply when clearly warranted
- Only apply lifecycle labels to bugs — never to questions or enhancements
- When in doubt, don't apply a lifecycle label — false positives are worse than missing labels
- It's okay to not add any labels if none are clearly applicable
This design philosophy prioritizes precision over recall, preferring to miss some labels rather than incorrectly applying labels that could lead to premature issue closure or user frustration.
Sources: .github/workflows/claude-issue-triage.yml1-107 .github/workflows/claude-dedupe-issues.yml1-85 .github/workflows/oncall-triage.yml1-119