AI / GenAI·7 min·7 August 2026

From 200 issues to almost zero: how Astro put AI agents to work

This site runs on Astro. So when Cloudflare published a piece on how the Astro team hands its bug reports to AI agents, I did not read it as general industry news. It is about the stack underneath this page.

The headline number: the Astro repository went from over 200 open issues to roughly 30, and the team expects to hit zero within a month. That would be a first in the repo’s five-year history. They got there without mass-closing stale tickets, which is the usual move when an issue list gets away from you.

Why triage is the expensive part

Reading a bug report takes a minute. Reproducing it can take hours. You clone the reporter’s example project, install the right versions, check whether the problem actually shows up, and only then do you start looking for the cause. For an open source maintainer this is the work that is never finished and that nobody thanks you for.

The problem has grown. Writing an issue with AI costs almost nothing now. Reading and judging one still costs a human. The ratio between what comes in and what can go out has tipped over.

Four agents, each in its own room

The Astro team did not start with a pipeline. They started with a skill: the steps a maintainer takes by hand, written down so a coding agent can follow them. First locally on their own machines, later the same skill inside a GitHub Action.

Four phases:

  1. Reproduce. Clone the reporter’s repository and confirm the bug is real.
  2. Diagnose. Instrument the code and add logging to find the root cause.
  3. Verify. Read the test suites, comments and docs to decide whether this is a bug or intended behaviour.
  4. Fix. Turn the reproduction into failing unit tests, find the solution via the architecture guide, and ship it.

The list is not the interesting part. The separation is. Each phase runs in its own subagent with its own empty context. They never talk to each other and never see each other’s reasoning. The only handoff is a file: report.md. Phase one writes down what it found, phase two reads that and appends its own findings.

The logic behind that is sharp. A language model wants to produce a solution. Let the same model reproduce the bug and also judge whether it is a bug, and it will push through its own earlier conclusion, because it is already invested in it. Put the verifier in a clean context, with the report and none of the reasoning that produced it, and you get a second opinion instead of an echo.

That is the piece most agent setups miss. People build one agent with a long instruction and a lot of memory. Astro built four short agents and a shared notepad.

The pipeline has no memory

The whole automation turns out to be a state machine driven by GitHub labels. A new report gets triage needed. Once the reporter confirms the fix works, it moves to fix verified. Beyond those labels the pipeline stores nothing. On every run it reads back the existing comments on the issue and works out from there where it is.

That sounds primitive, and that is the strength. There is no database that can drift away from reality. Everything the bot knows sits visibly on the issue, and anyone can audit the reasoning.

When the agents land on a fix, the pipeline builds a preview release with pkg.pr.new and posts it back to the issue: a summary of what it found, the full logs, and install instructions. The reporter tries the patch against their own project. Only after they confirm it works does the automation open a pull request.

That order is the actual design. The bot is allowed to do everything except have the last word. Confirmation comes from the person who filed the problem.

What went wrong, and why it helped

The Astro team treats a failing agent as a code problem, not a model problem. If the agent cannot find the solution, that points at three kinds of debt in the repo: unclear boundaries between components, missing comments explaining why code does what it does, and thin unit test coverage.

There is a concrete example. Across a run of Hot Module Replacement bugs, the bot kept editing the same if condition. The edit fixed the reported bug and broke something else, because that condition had no test covering it. Once the team added a comment explaining what logic that line guards, the bot stopped making the edit.

The lesson goes past bots. Every time the team chases down a failure like that and adds the comment, the test or the clearer boundary, the agent gets better at that part of the code and so does the next human who touches it. An agent that keeps stalling on your codebase is a free architecture review.

One caveat worth stating plainly: this is not a switch-it-on story. The team spent months on it and says outright it was not an instant success. What you are looking at is the result of repeated sanding, not of one good prompt.

What you can take from it

The triage logic used to live inside the Astro monorepo. That made every change risky, so it was pulled out into a separate repository: triagebot-action. It is open, and other teams have picked it up, some using it directly, some forking it for their own pipeline.

Wiring it in is one block in your workflow:

- uses: withastro/triagebot-action@v1
  with:
    read-token: ${{ secrets.GITHUB_TOKEN }}
    write-token: ${{ secrets.BOT_GITHUB_TOKEN }}
    cloudflare-api-key: ${{ secrets.CLOUDFLARE_API_KEY }}
    cloudflare-account-id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
    triage-model: cloudflare-workers-ai/@cf/moonshotai/kimi-k2.7-code
    verification-model: cloudflare-workers-ai/@cf/moonshotai/kimi-k2.6
    triage-skill: .agents/skills/triage

Note the two separate model fields. The model that triages is not the model that verifies. Same thinking as the isolated contexts, one layer deeper.

The engine underneath has since become its own framework, Flue. The team noticed nothing about their setup was specific to GitHub. Reacting to an event, running a sequence of isolated subagents, and keeping the reasoning separate from the actions the agent is allowed to take works just as well from a Slack message, a cron job or a webhook.

For most readers here the pattern travels better than the code. Three things you can borrow today, with or without a GitHub Action:

  • Cut a task into phases and give each phase a clean context. One agent doing everything gets stuck on its first conclusion.
  • Have the phases communicate through a file, not through memory. A report.md is readable, auditable and restartable.
  • Put the human confirmation at the point where things become irreversible. For Astro that is the pull request. For you it might be the publish button or the email that leaves the building.

And if you run an Astro project yourself: the bot now picks up your report automatically, so it does not sit in a queue waiting for a maintainer with a free evening. For my own stack that is the most concrete outcome of the whole story.

An ethics note

Two things the original post does not touch.

The pipeline runs on Cloudflare Workers AI with two closed model ids. That is not a neutral choice. Adopt this setup and you tie your triage to a single provider and to models you cannot inspect, cannot freeze and cannot run yourself. If the model changes, your triage changes with it, without anything in your repo moving. For an open source project, where the whole promise is that you can check what happens, that is a remarkable place to build in a blind spot.

Then there is the reporter. The issue tracker was never only a queue. It was also the front door through which new maintainers arrived. Someone files a bug, someone else replies, a conversation starts, and occasionally that person stays. Put a bot in between that answers politely and fast, and the queue gets shorter while that entry point quietly closes. That is a real trade, and 200 down to 30 tells you nothing about which way it falls.

The original post is on the Cloudflare blog and is worth reading, if only for the pipeline screenshots.