An autonomous bug-fixing pipeline: errors become issues, issues become PRs, PRs get reviewed and merged — no human in the loop unless escalation is needed.
[Error Monitor] → [Issue Creator] → [Bugsolver Agent] → [Draft PR] ←→ [Code Review] → [Merge]
| Actor | Role | Trigger |
|---|---|---|
| Error Monitor | Watches production logs/alerts for errors | Continuous (server-side) |
| Issue Creator | Files GitHub issues with context (stack trace, affected file, repro steps) | Error detected |
| Bugsolver Agent | Picks up assigned issues, enters build/test/eval loop, opens draft PR | Issue assigned with label bug:autofix |
| Review Loop | Addresses CodeRabbit / reviewer comments iteratively | PR comment events |
| Merge Gate | Marks PR ready-for-review when all comments resolved + CI green | Zero unresolved threads + green CI |
The error monitor (already built via MCP) observes runtime errors and files GitHub issues:
Error detected → MCP tool call → gh issue create
Issue template requirements:
- Title: Short error description
- Body must include:
- Stack trace / error log
- Affected file(s) and line numbers
- Reproduction steps (if determinable)
- Severity tag
- Labels:
bug,bug:autofix - Assignee:
bugsolver-agent(or bot account)
# .github/workflows/bugloop-dispatch.yml
name: Bugloop Dispatch
on:
issues:
types: [assigned, labeled]
jobs:
dispatch:
if: contains(github.event.issue.labels.*.name, 'bug:autofix')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Bugsolver Agent
env:
ISSUE_NUMBER: ${{ github.event.issue.number }}
ISSUE_BODY: ${{ github.event.issue.body }}
run: |
# Install Claude Code CLI
npm install -g @anthropic-ai/claude-code
# Spawn agent with issue context
claude --prompt "$(cat .bugloop/prompts/solve-issue.md)" \
--env ISSUE_NUMBER=$ISSUE_NUMBER ┌─────────────────────┐
GitHub Webhook ───→ │ Dispatcher Service │
(issues.assigned) │ (Node/Python/Go) │
└────────┬────────────┘
│
▼
┌─────────────────────┐
│ Agent Spawner │
│ - Clones repo │
│ - Creates branch │
│ - Launches Claude │
└─────────────────────┘
Webhook server responsibilities:
- Validate webhook signatures
- Filter events (only
bug:autofixlabeled issues) - Manage agent lifecycle (spawn, monitor, kill if stuck)
- Track state per issue (solving, pr-open, reviewing, merged)
- Enforce concurrency limits
Once the bugsolver agent has the issue context, it enters an iterative loop:
┌─────────────────────────────────────────────┐
│ │
│ ┌──────────┐ ┌───────┐ ┌──────┐ │
│ │ Code │───→│ Build │───→│ Test │ │
│ │ Changes │ │ │ │ │ │
│ └──────────┘ └───────┘ └──┬───┘ │
│ ▲ │ │
│ │ ┌──────────┐ │ │
│ └─────────│ Evaluate │◀─────┘ │
│ └──────────┘ │
│ │
│ Exit condition: tests pass + build clean │
└─────────────────────────────────────────────┘
Loop constraints:
- Max iterations: 10 (configurable)
- Timeout: 30 minutes per issue
- If stuck after N iterations → label issue
needs-human, unassign bot
Agent prompt structure:
- Read the issue (error context, stack trace, affected files)
- Explore the codebase for relevant code
- Hypothesize the fix
- Implement the change
- Run build + tests
- If failing → analyze failure, adjust, retry
- If passing → exit loop, proceed to PR
After the ralph loop exits successfully:
gh pr create \
--title "fix: [short description from issue]" \
--body "Closes #${ISSUE_NUMBER}\n\n## Changes\n..." \
--draft \
--base mainPR body must include:
Closes #Nto auto-link the issue- Summary of changes made
- Test results (pass count, coverage delta)
- Files modified
Once the draft PR is open, automated reviewers (CodeRabbit, etc.) will comment. The agent enters a second loop:
┌──────────────────────────────────────────────────────┐
│ │
│ ┌────────────┐ ┌─────────────┐ ┌─────────┐ │
│ │ Wait for │───→│ Read │───→│ Address │ │
│ │ comments │ │ comments │ │ comments │ │
│ └────────────┘ └─────────────┘ └────┬────┘ │
│ ▲ │ │
│ │ ┌──────────┐ │ │
│ └──────────────│ Re-run │◀──────────┘ │
│ │ tests │ │
│ └──────────┘ │
│ │
│ Exit: zero unresolved threads + CI green │
└──────────────────────────────────────────────────────┘
Implementation:
# .github/workflows/bugloop-review.yml
name: Bugloop Review Handler
on:
pull_request_review_comment:
types: [created]
pull_request_review:
types: [submitted]
jobs:
handle-review:
if: startsWith(github.event.pull_request.head.ref, 'bugloop/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Resolve Comments
run: |
claude --prompt "$(cat .bugloop/prompts/resolve-comments.md)" \
--env PR_NUMBER=${{ github.event.pull_request.number }}Comment resolution strategy:
- Fetch all unresolved review threads via
gh api - Group by file
- For each comment: understand the suggestion, apply fix, push commit
- Re-run tests after all comments addressed
- Reply to each thread confirming the fix
Conditions to mark PR ready:
- All CodeRabbit comments resolved
- All CI checks passing
- No unresolved review threads
- Diff is under size limit (e.g., < 500 lines changed)
# Check conditions
UNRESOLVED=$(gh api repos/:owner/:repo/pulls/$PR/reviews | jq '[.[] | select(.state == "CHANGES_REQUESTED")] | length')
CI_STATUS=$(gh pr checks $PR --json state | jq -r '.[] | select(.state != "SUCCESS") | .name')
if [ "$UNRESOLVED" -eq 0 ] && [ -z "$CI_STATUS" ]; then
gh pr ready $PR
fiEach issue/PR moves through these states:
OPEN → ASSIGNED → SOLVING → PR_DRAFT → REVIEWING → READY → MERGED
│ │
▼ ▼
ESCALATED ESCALATED
State storage options:
- GitHub issue/PR labels (simplest, visible)
- A
.bugloop/state.jsonin the repo (versioned) - External store (Redis/SQLite) for the webhook server approach
bugloop/
├── .github/
│ └── workflows/
│ ├── bugloop-dispatch.yml # Issue → Agent trigger
│ ├── bugloop-review.yml # PR comment → Agent trigger
│ └── bugloop-gate.yml # Ready-for-review check
├── .bugloop/
│ ├── config.yml # Loop limits, timeouts, labels
│ └── prompts/
│ ├── solve-issue.md # Prompt template for bugsolver
│ └── resolve-comments.md # Prompt template for review resolution
├── src/
│ ├── dispatcher/ # Webhook server (Option B)
│ │ ├── server.ts
│ │ ├── webhook-handler.ts
│ │ └── agent-spawner.ts
│ ├── state/ # State machine
│ │ └── machine.ts
│ └── gates/ # Gate condition checks
│ └── ready-for-review.ts
├── ARCHITECTURE.md
└── README.md
# .bugloop/config.yml
labels:
trigger: "bug:autofix"
in-progress: "bugloop:solving"
needs-human: "bugloop:escalated"
limits:
max_ralph_iterations: 10
max_review_iterations: 5
timeout_minutes: 30
max_diff_lines: 500
branch_prefix: "bugloop/"
agents:
bugsolver:
assignee: "bugsolver-bot"
reviewer:
# CodeRabbit handles this automatically
external: true- Iteration limits: After N failed attempts, label
bugloop:escalatedand unassign - Timeout: Kill agent process after configured timeout
- Diff size: If changes exceed threshold, escalate for human review
- Branch protection: Require at least 1 human approval before merge (configurable)
- File restrictions: Agent cannot modify CI config, security-critical paths, or
.bugloop/itself - Rollback: If post-merge monitoring detects regression, auto-revert and re-open issue
- Multi-repo support: Error in service A files issue in service A's repo
- Priority queue: High-severity issues get solved first
- Learning loop: Track success rate per error pattern, skip known-unfixable patterns
- Cost tracking: Monitor API usage per issue resolution
- Parallel solving: Multiple agents working on different issues concurrently
- Human-in-the-loop mode: Agent proposes fix, waits for human approval before PR