{"slug": "i-built-an-ai-agent-for-production-incidents-the-interesting-part-is-when-it-to", "title": "I built an AI agent for production incidents. The interesting part is when it refuses to act.", "summary": "An engineer built Sonjomon, an AI agent for production incident response that can refuse to act when confidence is high but risk is too great. The agent uses an autonomy ladder that factors in confidence and blast radius, with deterministic code enforcing safety limits that the model cannot override. In live tests against a fragile Cloud Run service, it caught unexpected issues and correctly escalated when a rollback would be ineffective.", "body_md": "I wrote this for the All Things Agentic Hackathon.\n\nEvery incident-response demo you have seen ends the same way: something breaks, the agent fixes it, everyone applauds.\n\nI want to show you the opposite. Here is my agent, at 95% confidence, having correctly diagnosed a bad deployment, deciding not to roll it back.\n\nThat refusal is the whole project.\n\nThe question underneath\n\nAt 3am an alert fires. An engineer wakes up, reads several hundred log lines, correlates them against recent deploys, and rolls something back. Most of it is mechanical. It is an obvious target for automation.\n\nBut \"automate it with an LLM\" does not dissolve the problem, it relocates it. The new question is: how much would you let an agent change in production without asking you first?\n\nGive it too little and it is a chatbot that writes summaries. Give it too much and one confidently wrong diagnosis takes down your service at 3am with nobody watching.\n\nI named the project Sonjomon — Bengali for restraint.\n\nThe autonomy ladder\n\nAn agent should not have one blanket permission level. How far it may act alone is a function of two things: how confident it is, and how much damage the proposed action does if that confidence turns out to be wrong.\n\ntier = f(confidence, blast_radius)\n\nOBSERVE record findings, take no action\n\nSUGGEST recommend to a human, do not execute\n\nAPPROVE stage the action, execute on explicit approval\n\nACT execute now, then verify independently\n\nA restart is medium risk — reversible in seconds. A rollback is high risk — it shifts production traffic, and a needless rollback during a real outage extends it. Deleting data is critical, and no confidence level unlocks it.\n\nSix conditions can only ever push the tier down, never up: the blast-radius ceiling, thin evidence, a similar action that just failed, a third attempt at the same fix, a stale incident, and a global dry-run switch.\n\nNothing pushes it up. A wrong action is far more expensive than a missed one.\n\nThree things the model does not control\n\nIt cannot set its own blast radius. The model proposes an action name; a registry in code supplies the risk. If the risk table lived in the prompt, a confidently wrong model could talk itself into a rollback by calling it low-risk.\n\nIt cannot decide whether it may execute. That is deterministic, unit-tested code — installed as ADK's before_tool_callback, so the policy sits on the framework's real enforcement seam. Returning a dict cancels the tool call and hands that dict back to the model, so a blocked model learns why instead of silently retrying.\n\nIt cannot grade its own work. Verification is an independent HTTP probe, recorded as a separate event. An agent that self-reports success is worthless during an outage.\n\nForty-one tests hold this in place. One of them asserts that a 96%-confident agent still cannot run a destructive action.\n\nWhat happened when I ran it\n\nFourteen live incidents against a deliberately fragile Cloud Run service.\n\nIt found things I did not plant. In one incident it compared container image digests across five revisions and concluded that three of them — including the one named \"healthy\" — shared identical broken code, so a rollback would achieve nothing. It escalated instead. That inference was in neither its registry nor its prompt.\n\nIn another it noticed every revision had traffic_percent: 0. That was a real misconfiguration I had created by accident while setting up, and it caught it.\n\nIt failed, and handled the failure correctly. In one incident it reached the ACT tier and ran a real command against production. The command failed — a missing IAM permission I had not anticipated. The agent saw the failure, did not claim success, re-diagnosed the problem, and the loop breaker then required a human.\n\nThat IAM gap is worth naming. The agent had run.admin on exactly one service and still could not update it, because Cloud Run needs artifactregistry.repositories.downloadArtifacts to pull the image for a new revision. I only found it because the agent tried, failed, and logged the exact permission. Least privilege is discovered by breaking things.\n\nOnce, it said nothing at all. Forty percent confidence, ambiguous signals. Too low to even offer an opinion. In the log it simply reads: confidence too low to even recommend.\n\nThat is the row I am proudest of.\n\nThree things I got wrong\n\nI calibrated the thresholds before meeting the model. My initial ACT floor was 0.90. Gemini's self-reported confidence clusters in 0.85–0.95 for a well-evidenced diagnosis, which left the ACT tier effectively unreachable. Seven live incidents told me what no synthetic test would have.\n\nCloud Run cuts CPU the moment a request is acked. The push endpoint acks immediately and investigates in a background task — correct design, but with default CPU allocation the investigation crawled and the instance froze before finishing. --no-cpu-throttling is not optional for a long-running agent. That cost me an evening.\n\nMy first chaos injection destroyed its own evidence. The memory-leak fault climbed until the container hit OOM and restarted — which wiped the in-memory fault state and dropped memory back to zero before the alert's alignment window closed. The agent kept arriving at a healthy service and correctly reporting \"transient, already resolved.\" The fix was to cap the leak just below the container limit so it holds there instead of dying.\n\nThe uncomfortable result\n\nAcross fourteen incidents the agent almost never changed production. Every time, that was the correct call: two failure modes have no safe automatic fix by design, one had a rollback that would have achieved nothing, one had already self-resolved.\n\nI expected to be disappointed by that. I am not.\n\nThe friction this removes is the diagnosis, not the fix. An engineer woken at 3am reaches a root cause in twenty to thirty minutes. This agent did it in 8 to 30 seconds, every time, with the file, the line number, the occurrence count, and the offending revision.\n\nThe fix is the easy part. Knowing you are right enough to apply it is not.\n\nAn agent that acts anyway, to look useful, is the failure mode this project exists to prevent.\n\nCode: [https://github.com/singhakousik363-del/sonjomon](https://github.com/singhakousik363-del/sonjomon)\n\nDemo: [https://youtu.be/jBE6wztwGic](https://youtu.be/jBE6wztwGic)\n\nBuilt solo in ten days, as a first-year CS student, on Gemini 3.5, Google ADK, Cloud Run, Pub/Sub, Firestore, Cloud Logging, Cloud Monitoring and Secret Manager.", "url": "https://wpnews.pro/news/i-built-an-ai-agent-for-production-incidents-the-interesting-part-is-when-it-to", "canonical_source": "https://dev.to/singhakousik363del/i-built-an-ai-agent-for-production-incidents-the-interesting-part-is-when-it-refuses-to-act-1ddg", "published_at": "2026-08-30 03:10:03+00:00", "updated_at": "2026-08-30 03:22:21.069134+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "developer-tools"], "entities": ["Sonjomon", "Cloud Run", "ADK"], "alternates": {"html": "https://wpnews.pro/news/i-built-an-ai-agent-for-production-incidents-the-interesting-part-is-when-it-to", "markdown": "https://wpnews.pro/news/i-built-an-ai-agent-for-production-incidents-the-interesting-part-is-when-it-to.md", "text": "https://wpnews.pro/news/i-built-an-ai-agent-for-production-incidents-the-interesting-part-is-when-it-to.txt", "jsonld": "https://wpnews.pro/news/i-built-an-ai-agent-for-production-incidents-the-interesting-part-is-when-it-to.jsonld"}}