AI as Your Backlog's First Responder: A Small Experiment

What happens when you let an AI agent pick up the small, well-defined tickets nobody has time for? Notes from a personal experiment — including where it broke.

AIEngineering

Every backlog has the same shape: a handful of important features at the top, and a long tail of small, well-understood, low-glamour tickets that never quite get prioritized. A typo in an error message. A date formatter that breaks on one locale. A validation message that says the wrong field name. Nobody’s against fixing them. Nobody ever gets to them either.

Over the past few months I’ve been experimenting — on my own time, on a personal project, not a client’s production system — with routing exactly that tail of tickets to an AI agent before a human ever looks at them. Not “AI writes all your code.” Something much narrower: can an agent safely pick up the tickets a team already agrees are simple, and show up with a draft PR instead of a person having to context-switch into them?

Here’s what that looked like, including the parts that didn’t work.

Deciding what “simple enough” even means

The interesting design problem isn’t the AI part — it’s the triage rule that decides what the agent is allowed to touch. I settled on a checklist a ticket has to pass before it’s eligible:

  • The change is scoped to one file or one clearly-named module.
  • There’s an existing test that will catch a regression, or the ticket description makes the expected behavior unambiguous.
  • Nothing about it touches auth, billing, or a database migration.
  • The reporter described a reproducible symptom, not just “this feels off.”

Tickets that fail any of those stay firmly in the human queue. That checklist did more work than the model did — most of what makes this safe is refusing to hand over the ambiguous 80% of the backlog, not the AI being clever about the remaining 20%.

The rough shape of it

Nothing exotic under the hood: a small triage step reads new tickets against that checklist, and anything that passes gets handed to an agent with read/write access to a throwaway branch, the repo’s existing test suite, and nothing else — no production credentials, no network access beyond package installs. It runs the tests before touching anything, makes the change, runs them again, and only opens a draft PR if both runs are green and the diff stays inside the ticket’s declared scope. A human still reviews and merges every single PR — the agent never gets write access to a protected branch.

The stack, briefly

Kept deliberately boring on purpose: a queue that new tickets land in, a triage step that checks the checklist above and either routes to the agent or leaves the ticket alone, and the agent itself running in a throwaway container with the repo checked out, package installs allowed, and nothing else reachable from that sandbox — no production database, no external APIs, no secrets beyond what running the test suite needs. The model choice mattered less than I expected going in; the checklist and the sandbox did most of the safety work, and a reasonably capable model was enough once those guardrails existed.

A few tickets it actually handled

A locale-sensitive date bug. A ticket described a timestamp rendering as “Invalid Date” for users in one specific timezone offset — a classic off-by-one in a manual date parser. The agent found the parsing function, reproduced the failure with the existing test runner, and proposed swapping the manual parse for the same date library already used two files over in the codebase. Small, boring, correct. Exactly the kind of fix a senior engineer would make in ten minutes and then forget to log as a win.

A flaky test, not a flaky feature. One ticket complained a checkout test “sometimes fails in CI.” The agent’s diff didn’t touch the feature code at all — it found an unawaited promise in the test setup and added the missing await. That’s a distinction worth calling out: a chunk of what looks like “the feature is broken” backlog is actually “the test harness is broken,” and that’s often more mechanically fixable than the ticket description makes it sound.

A validation message pointing at the wrong field. Genuinely the most boring ticket in the queue, and also the best fit — a one-line string fix that had been sitting for months because it never felt worth a pull request on its own. The agent bundled three of these in one PR with a clear before/after in the description.

A dependency bump that wasn’t actually simple. This one’s worth including because it’s where the checklist saved me from myself. A patch-version bump looked like the easiest possible ticket. The agent ran the test suite first, as always — and one previously-passing test started failing against the new version. Under the “simple enough” rule, a failing test after the change means the PR doesn’t get opened; it gets flagged back with the failure attached instead. The bump itself was fine. My assumption that “patch version = safe” wasn’t, and I was glad something checked before a person had to find out in production.

Where it had to stop

Anything with two reasonable interpretations. A ticket asking to “improve error handling on the upload endpoint” got correctly bounced back to the human queue — “improve” isn’t a diff, it’s a design conversation, and the triage checklist caught that before the agent ever saw it.

Cross-service changes. One ticket looked simple in isolation but the actual fix meant changing a shared response shape that another internal service depended on. The agent got partway into the change, correctly flagged that a dependent consumer would break, and stopped — which is the outcome I wanted, not a failure. Refusing safely is the feature.

Anything where “correct” depends on product judgment. A UI copy tweak that seemed trivial actually needed a decision about tone, not grammar. That’s not something I want an agent guessing at on my behalf, and the review step exists precisely to catch when it tries.

What I’d change next time

Two lessons stood out after running this for a while. First, the checklist needed to be stricter than my first draft of it — I initially allowed “touches one file” without also requiring existing test coverage, and the one time that bit me was a genuinely one-file change to code nothing was testing. The agent had no way to prove it hadn’t broken something, and neither did I until a person looked closely. Test coverage became a hard requirement, not a nice-to-have, after that.

Second, the draft-PR description mattered more than I expected. An agent that explains why it made a change, not just what changed, turned review from “re-verify this from scratch” into “confirm this reasoning holds” — which is a much faster review and a much more honest one, because it surfaces the agent’s assumptions instead of hiding them inside a diff.

What this is actually worth

The honest framing isn’t “AI replaces the backlog.” It’s that a well-scoped agent, wrapped in a checklist stricter than the model itself, can absorb the tickets that were never going to get a person’s attention anyway — the ones competing with a feature launch and reliably losing. The backlog didn’t get smaller because the AI is smart. It got smaller because a boring triage rule finally gave someone — human or not — permission to work on the boring tickets.

That’s a smaller claim than the headlines about AI replacing engineers. It’s also the part I’d actually stand behind.

Have a similar problem?

I take on backend, integration and automation work like this. Tell me what you're building and I'll tell you honestly if I'm the right fit.

Hire me on Upwork → Get in touch →