Skip to content

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:

  1. SlackProcessInteractivityController receives the interactivity payload
  2. ParseSlackErrorMessageAction auto-detects the error source using a parser chain:
ParserDetects viaSource
ParseBugsnagErrorMessageActionAttachment with "Location" fieldbugsnag
ParseLaravelErrorMessageActionAttachment with "Level" + "Exception"laravel
ParsePlainTextErrorMessageActionAny non-empty text (catch-all, last)slack-user
  1. PostSlackThreadReplyAction posts an initial reply in the Slack thread
  2. TriggerGitHubAutofixWorkflowAction sends repository_dispatch with an ErrorInfo DTO (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.md for 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

SecretPurpose
ANTHROPIC_API_KEYClaude API (title generation + investigation)
COPILOT_PATPAT with permissions to assign Copilot agent
SLACK_SQUIRREL_APP_BOT_TOKENSlack 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

FilePurpose
.github/workflows/autofix_with_ai.ymlMain GitHub Actions workflow
.github/workflows/notify_slack.ymlHelper workflow for Copilot → Slack
app/Modules/Infrastructure/SlackBot/Http/Controllers/SlackProcessInteractivityController.phpSlack interactivity entry point
app/Modules/Infrastructure/SlackBot/Actions/ParseSlackErrorMessageAction.phpParser chain orchestrator
app/Modules/Infrastructure/SlackBot/Actions/ParseBugsnagErrorMessageAction.phpBugSnag message parser
app/Modules/Infrastructure/SlackBot/Actions/ParseLaravelErrorMessageAction.phpLaravel error message parser
app/Modules/Infrastructure/SlackBot/Actions/ParsePlainTextErrorMessageAction.phpCatch-all plain text parser
app/Modules/Infrastructure/SlackBot/Actions/PostSlackThreadReplyAction.phpPosts initial Slack thread reply
app/Modules/GitHub/Actions/TriggerGitHubAutofixWorkflowAction.phpSends repository_dispatch
app/Modules/GitHub/Dto/ErrorInfo.phpDTO passed through the pipeline

Extending

  • New error source — Implement SlackErrorParsable, register before ParsePlainTextErrorMessageAction.
  • Investigation prompt — Edit the Claude prompt in the "Investigate with Claude Code" step. Add/remove MCP tools in claude_args.
  • Copilot instructions — Modify the INSTRUCTIONS variable in the "Assign issue to Copilot" step.
  • Extra notifications — Use the notify_slack.yml pattern for additional Slack updates.