Appearance
AI Autofix Workflow
Automated investigate-and-fix pipeline: Slack message → Claude investigation → Copilot fix PR, with Slack thread updates throughout.
How It Works
The workflow can also be triggered manually from the GitHub Actions UI (workflow_dispatch) with error message, location, source, and branch.
IxDF-web Side (Slack → GitHub)
The @IxDF Squirrel bot exposes an "Autofix with AI" message shortcut. When triggered:
SlackProcessInteractivityControllerreceives the interactivity payloadParseSlackErrorMessageActionauto-detects the error source using a parser chain:
| Parser | Detects via | Source |
|---|---|---|
ParseBugsnagErrorMessageAction | Attachment with "Location" field | bugsnag |
ParseLaravelErrorMessageAction | Attachment with "Level" + "Exception" | laravel |
ParsePlainTextErrorMessageAction | Any non-empty text (catch-all, last) | slack-user |
PostSlackThreadReplyActionposts an initial reply in the Slack threadTriggerGitHubAutofixWorkflowActionsendsrepository_dispatchwith anErrorInfoDTO (source, error, location, channel, branch)
To add a new error source, implement SlackErrorParsable and register it before the plain-text catch-all.
GitHub Actions Side (autofix_with_ai.yml)
Issue Creation
- Generates a clean title via a fast and simple LLM (e.g.
Claude Haiku) (falls back to truncated error text) - Creates an issue with error details, source, branch, location, and a link to the workflow run
- Notifies the Slack thread with a link to the issue
Claude Investigation
Runs via anthropics/claude-code-action with read-only tools only (Bash, Read, Glob, Grep, WebFetch). Claude:
- Reads
CLAUDE.mdfor project context - Traces data flow upstream to find the root cause
- Posts a structured comment: root cause analysis, affected files, suggested fix, testing notes
- Has access to BugSnag and NewRelic MCP tools for querying error details and metrics
Copilot Handoff
Assigns the issue to copilot-swe-agent[bot] via GitHub API with custom instructions:
- Fix the bug based on Claude's root cause analysis
- Create a PR and mark it ready for review
- Request review from
copilot-pull-request-reviewer[bot] - Notify the Slack thread via
notify_slack.yml(a helper workflow, since Copilot can't access Slack tokens directly)
Secrets
| Secret | Purpose |
|---|---|
ANTHROPIC_API_KEY | Claude API (title generation + investigation) |
COPILOT_PAT | PAT with permissions to assign Copilot agent |
SLACK_SQUIRREL_APP_BOT_TOKEN | Slack bot for posting thread updates |
Key Design Decisions
- Claude investigates, Copilot fixes — Claude has deep codebase understanding and MCP tools; Copilot has native GitHub integration for PR creation. Each plays to its strengths.
- Read-only investigation — Claude cannot create branches or PRs, preventing conflicts with Copilot's fix step.
- Auto-detected source — The parser chain identifies BugSnag, Laravel, or plain-text messages from message structure. No user input needed.
- Thread-based updates — All notifications go to the same Slack thread, keeping context together.
- Graceful degradation — Slack notifications are non-blocking. The workflow works without Slack context (e.g., manual dispatch).
Key Files
| File | Purpose |
|---|---|
.github/workflows/autofix_with_ai.yml | Main GitHub Actions workflow |
.github/workflows/notify_slack.yml | Helper workflow for Copilot → Slack |
app/Modules/Infrastructure/SlackBot/Http/Controllers/SlackProcessInteractivityController.php | Slack interactivity entry point |
app/Modules/Infrastructure/SlackBot/Actions/ParseSlackErrorMessageAction.php | Parser chain orchestrator |
app/Modules/Infrastructure/SlackBot/Actions/ParseBugsnagErrorMessageAction.php | BugSnag message parser |
app/Modules/Infrastructure/SlackBot/Actions/ParseLaravelErrorMessageAction.php | Laravel error message parser |
app/Modules/Infrastructure/SlackBot/Actions/ParsePlainTextErrorMessageAction.php | Catch-all plain text parser |
app/Modules/Infrastructure/SlackBot/Actions/PostSlackThreadReplyAction.php | Posts initial Slack thread reply |
app/Modules/GitHub/Actions/TriggerGitHubAutofixWorkflowAction.php | Sends repository_dispatch |
app/Modules/GitHub/Dto/ErrorInfo.php | DTO passed through the pipeline |
Extending
- New error source — Implement
SlackErrorParsable, register beforeParsePlainTextErrorMessageAction. - Investigation prompt — Edit the Claude prompt in the "Investigate with Claude Code" step. Add/remove MCP tools in
claude_args. - Copilot instructions — Modify the
INSTRUCTIONSvariable in the "Assign issue to Copilot" step. - Extra notifications — Use the
notify_slack.ymlpattern for additional Slack updates.