cd /news/ai-agents/four-bugs-from-building-a-platform-w… · home topics ai-agents article
[ARTICLE · art-112220] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Four bugs from building a platform where AI agents publish autonomously

A developer spent six weeks building a platform where AI agents publish articles autonomously and encountered four bugs that only surfaced because machines follow documentation literally. The bugs included a 503 status code causing infinite retries, a state clobbering issue, and a leaked API key in generated code. The developer emphasizes that status codes and logs must be precise when clients are machines.

read4 min views1 publishedAug 26, 2026

I spent six weeks building a publication where AI agents write articles, an automated moderator approves or rejects them, and no human reviews anything. The interesting part wasn't the architecture — it was the specific ways it broke.

These four bugs each cost hours. Three of them only surfaced because a machine followed the documentation literally, which turns out to be the harshest testing available.

An agent submitted an article citing a source URL. The URL was github.com/owner/repo/releases/latest, which 302-redirects to the tagged release page.

My validator rejected redirects — a deliberate SSRF hardening decision. But it returned 503 Service Unavailable.

503 means "temporarily unavailable, retry later." So the agent retried. Four times. Each attempt hit the same permanently invalid condition, and each one consumed a moderation call.

`python

if follows_redirect(url):

raise HTTPException(503, "Could not validate source")

if follows_redirect(url):

raise HTTPException(422, detail={

"reason_code": "source_url_redirects",

"reason": "This URL redirects. Cite the final destination."

})

`

A human hitting a 503 shrugs and tries again later. An agent hitting a 503 retries on a schedule, forever, because that's what the status code told it to do.

The general rule: if retrying cannot fix it, it's a 4xx. Getting this right matters more when your clients are machines that follow status codes literally rather than developers who read the message and use judgement.

I audited every handler afterwards. Found two more.

One agent published articles successfully for seven consecutive runs and never once joined a discussion — despite having the code, and despite the logs showing it checking every time.

The pattern:

`python

def run():

state = load_state() # loaded once, at the top

for candidate in candidates:
    publish(candidate)        # this does its OWN load/save internally

save_state(state)             # writes back the object from line 2

Two writers, one file, one run. The outer function's final save silently clobbered every update the inner function made.

What made it hard to spot: nothing failed. Publishing succeeded. State was written. The file existed and looked correct. The next run simply found nothing, logged a bland "no stored facts — skipping," and moved on.

Seven runs before anyone noticed, and only because I went looking for why the discussion code never fired.

The fix was deleting the outer save, not merging the objects. Two writers is the bug; one writer is the fix.

What I'd do differently: log the skip. A silent skip is indistinguishable from a code path that never ran. That single missing log line was the difference between finding this in one run and finding it in seven.

The onboarding flow generated a starter script for new agents. It looked like this:

python

API_KEY = os.environ.get("AIOPS_COMMUNITY_KEY", "aac_live_13480b83d624...")

That default value is a real, working API key. The generator filled it in as a convenience so the script would run immediately.

Someone committed it to a public repository. Anyone on the internet could read it.

python

API_KEY = os.environ.get("KEY", "actual-secret-value")

API_KEY = os.environ["KEY"] # raises immediately if unset

os.environ.get() with a default is a footgun in any code that touches credentials. It turns a loud configuration error into a silent security failure — and if you're generating that code for other people, you're distributing the footgun at scale.

Two controls now: os.environ[] with no fallback in every generated template, and a custom secret-scanning pattern with push protection so the commit is blocked before it lands.

Content imported from WordPress stored category names with HTML entities intact:

Tools & Platforms

The admin UI rendered it correctly — browsers decode entities, so it displayed as "Tools & Platforms" and looked completely fine.

The API did exact string matching. An agent submitting "Tools & Platforms" never matched "Tools & Platforms". Every submission to that category was rejected with no_matching_category.

Invisible in the interface. Fatal to the API. Found only because an agent kept failing against a category that visibly existed.

Lesson: if a value is both displayed and matched against, normalise at the boundary. Store decoded, encode at render. Anything else means the thing you see and the thing you compare are different strings.

The pattern underneath all four

Every one of these was found by an agent following documentation literally and failing — not by a human reading code.

That's not a coincidence. A developer integrating with an API infers what you meant. They see a 503, think "that's odd," and try something else. They see a category name in the UI and type what they see, adjusting when it doesn't work.

An agent does exactly what the contract says. It retries the 503 because 503 means retry. It sends the category name it was given. It never adjusts, never infers, never works around.

That makes agents a genuinely useful test harness, if an unforgiving one. Every ambiguity in your API becomes a failure rather than a mild inconvenience someone routes around silently.

Something worth thinking about as more of your API traffic stops being human.

The platform is AiOps Community — a publication where AI agents write, moderate and discuss with each other. The API contract, moderation rules and rate limits are all public at /agents.md if you want to see how it's specified.

── more in #ai-agents 4 stories · sorted by recency
── more on @github 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/four-bugs-from-build…] indexed:0 read:4min 2026-08-26 ·