Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Debugging a Real Issue with an AI Agent — A Worked Example

A real end-to-end case: a vague bug report from the finance team, fixed by an AI coding agent running in the hh-infra multi-repo workspace. Read this after the OpenCode + MiniMax guide — that guide tells you how to set the agent up; this one shows the loop in action.

This is not a tutorial about the URL shortener. It’s a tutorial about how to drive an AI agent through a real investigation — what to expect, where it goes wrong, and how to steer it to a correct, reviewed fix.

The whole session ran on MiniMax M2.7 inside OpenCode, against the hh-infra workspace (many repos checked out side by side, not a single repo). The agent had gh, aws, and kubectl available and used them itself.


The setup that makes this work

Before the first prompt, two things were already true — both come straight from AGENTS.md:

  1. The workspace is multi-repo. hh-server, knowledge-base, and the Terraform repos are all checked out next to each other. The agent can grep hh-server code and knowledge-base docs in the same session.
  2. The agent can run the CLIs. It can kubectl into eks-prod and the DigitalOcean cluster to inspect live pods — no copy-pasting logs into a chat.

First prompt of every session: read AGENTS.md. It loads the repo map, the AWS profiles, the kubectl contexts, and the safety rails before you give it real work.


Step 1 — Hand it the vague report (and let it investigate)

The report from finance was barely a spec:

“booking link for download it long text, can you help me check for this list”

What was actually given to the agent:

Our system sends an email with subject "Monthly reservation report links".
It contains a link for each restaurant report to download.
Some links are NOT shortened — maybe a rate limit, or the URL service was down,
so the system used the fallback (original long link).

- Check docs in knowledge-base repo or hh-server repo about this feature first.
- Check docs about the URL shortener service too.
- Use kubectl to get pod info on eks-prod and the DigitalOcean cluster.

Notice the prompt tells it where to look (which repos) and what tools to use (kubectl, which clusters). That’s the job of the human: point the agent at the right ground, then let it dig.

What the agent did on its own in ~1–2 minutes:

  • grep across knowledge-base for reservation report / url short → found the relevant release notes (the consolidated-links feature, the shortener fixes).
  • grep across hh-server for the worker and exporter code.
  • kubectl against the DigitalOcean cluster → confirmed rails-dynamic-links (the shortener service, domain hhub.ly) was healthy — 5 pods, actively creating short links.

That last step matters: the agent verified the live service itself. It ruled out “the shortener is down” without anyone leaving the chat.


Step 2 — The first answer was wrong (this is normal)

The agent confidently reported a root cause:

ConsolidatedLinksWorker doesn’t shorten URLs before sending the email — it uses the raw S3 URL directly. Fix: call MyUrlShortener.find_or_create in the worker before building the email body.

Plausible. Also wrong. The email body wasn’t the problem — the email links to an Excel file, and it’s the rows inside the Excel that contained long links.

Lesson 1: a vague prompt produces a confident wrong answer.

The agent didn’t hallucinate — it answered the question it thought you asked. The fix is not to distrust the agent; it’s to tighten the prompt. The model is only as precise as the target you give it.

The right move here is not “the AI is bad.” It’s: read the answer, notice it solved the wrong layer, and clarify.


Step 3 — Refine the prompt to the real target

Finance expects shortened links INSIDE the Excel file.
The email contains one link → clicking it downloads the Excel from S3.
We need each ROW in the Excel to use a shortened link.

One short correction. The agent re-traced, found the real code, and pinpointed it:

app/services/reservation_report/consolidated_links_exporter.rbgenerate_excel writes link.download_url straight into each row. If the shortener was down when a row’s link was first generated, that stored value is the raw S3 URL, and the exporter never re-shortens it.

Now the diagnosis is correct and it matches the symptom finance reported (some rows long, some short).

Lesson 2: correct the target, not the whole approach.

A single sentence redirected the agent from the wrong file to the right one. You don’t need to re-explain everything — just fix the part it got wrong.


Step 4 — Let it implement (fix + tests + PR)

Go ahead and fix it. Include the RSpec test update too.
We'll run the tests on GitHub Actions, not locally.

The agent:

  • Edited consolidated_links_exporter.rb to shorten each URL before writing the row, mirroring the existing pattern in NotificationWorkers::ReservationReport#download_link.
  • Updated consolidated_links_exporter_spec.rb to mock MyUrlShortener and assert shortened output.
  • Opened hh-server PR #8176 on branch fix/consolidated-link-shortening, with CI running the specs.

Lesson 3: “run the tests on CI, not locally” is a valid strategy.

You don’t have to set up the whole Rails test env locally. Let the agent write the tests, push the PR, and let GitHub Actions be the test runner. The agent reads the CI result and self-corrects. (This only works because hh-server has a test suite — see “Add automated tests” in the OpenCode + MiniMax guide.)


Step 5 — Review the fix by questioning it

This is the most important step and the one people skip. Don’t just merge what the agent produced — interrogate it:

In consolidated_links_exporter.rb it shortens link.download_url.
Can you confirm download_url is an ORIGINAL link?
Check the codebase — I worry it might already be a shortened link.

Good question, because double-shortening would be a real bug. The agent traced both cases:

  • Already a hhub.ly short linkfind_or_create returns it unchanged (the shortener API is idempotent). Safe.
  • An S3 URL → the shortener’s allowed_hosts validation rejects non-hungryhub.com hosts, so it falls back to returning the original. Safe (and exactly the bug being fixed).

So the fix was correct as-is. But the question surfaced a cheap improvement.

Lesson 4: review = ask the agent to prove its own change is safe.

“Are you sure X is always Y? Check the codebase.” forces the agent to trace real call paths instead of assuming. It catches the bugs that look fine.


Step 6 — Add the guard

Yes, go ahead and add a guard.

The agent added a SHORTLINK_DOMAINS constant (hhub.ly, links.hhub.ly, links-staging.hhub.ly), a shortened_url? helper that checks the URL host, and a shorten_url wrapper that skips the API call entirely if the link is already short — avoiding pointless shortener calls. It added specs for the already-short and staging-domain cases. PR #8176 updated. Ready to merge once CI is green.


Step 7 — Close the loop: document what you learned

This investigation existed because there was no doc for the URL shortener or the consolidated report links — only scattered release-note lines. That’s why the first prompt had to be long and the agent still guessed wrong. Every minute of this session was effectively re-discovering how the feature works.

So the last step of every debug session is: write the missing doc.

After this fix, the missing reference was added to the knowledge-base: URL Shortener & Reservation Report Links — what the shortener is, where it runs, how it fails, and a debugging checklist.

This turns a one-time investigation into permanent team knowledge, and it pays off both ways:

  • Write side (after debugging): if you discovered something undocumented, document it. The next person doesn’t re-trace the codebase.

  • Read side (before debugging): because the doc now exists, the next time you can open with a short prompt instead of a long one:

    Search knowledge-base for the URL shortener / reservation report links,
    then investigate why some links in the finance Excel are not shortened.
    

    The agent reads the doc, already knows the shortener lives on DigitalOcean with a fallback-to-original behaviour, and skips straight to the live check — no long hand-written context needed.

Lesson 5: documentation is part of the fix, not extra work.

Undocumented feature → long prompt → wrong first answer (you saw it in Step 2). Documented feature → short prompt → faster, more accurate investigation. Each debug session you document makes the next one cheaper — for you and for every teammate.


The loop, in one picture

vague report
   └─> point agent at repos + give it the CLIs
        └─> agent investigates (grep code + docs, kubectl live pods)
             └─> first answer: confident but WRONG layer
                  └─> human refines the TARGET (one sentence)
                       └─> correct diagnosis
                            └─> agent: fix + tests + PR (CI runs the tests)
                                 └─> human reviews by QUESTIONING the change
                                      └─> agent proves safety + adds a guard
                                           └─> merge
                                                └─> DOCUMENT the gap in knowledge-base
                                                     └─> next debug starts with a short prompt

Takeaways for the team

  1. Start with read AGENTS.md. It loads the repo map, profiles, and contexts.
  2. Point the agent at the right repos and let it run kubectl / gh / aws itself. It verified the live shortener service without anyone leaving the chat.
  3. Expect the first answer to be wrong when your prompt is vague. That’s a prompt problem, not a model problem. Refine the target, don’t re-explain everything.
  4. You don’t need a local test env. “Write the tests, push, let CI run them” is a legitimate workflow — if the repo has a suite.
  5. Reviewing means questioning. Ask the agent to prove its change is safe against the real codebase (“are you sure X is always Y? check it”). That’s where the double-shorten guard came from.
  6. One human in the loop, one agent doing the work. Each turn was a small, cheap correction — not a rewrite.
  7. Document the gap when you’re done. This whole investigation happened because the feature was undocumented. After fixing, add the missing doc to knowledge-base — then the next debug starts with “search knowledge-base for X” instead of a long prompt. Documenting is part of the fix, and it helps every teammate.

Related: Agentic Coding with OpenCode + MiniMax (setup, model choice, parallel agents, letting the agent run CLIs) and AGENTS.md (workspace map and safety rails).