Building an Autonomy Error Budget Gateway with SigNoz and OpenTelemetry A developer built LEASH, an error budget gateway for AI agents that dynamically adjusts permissions based on real-time telemetry from SigNoz and OpenTelemetry. The system demotes an agent's access tier when failures exceed a threshold, preventing autonomous agents from causing damage during hallucinations or tool failures. The project was completed in about a day for the Agents of SigNoz hackathon. I built an AI agent that's allowed to run database migrations and clean up staging tables on its own. Then I built a second system whose only job is to take that permission away the moment things start going wrong. That second system is LEASH, and this is the story of building it in about a day for the Agents of SigNoz hackathon. Everyone talks about AI agents "acting autonomously" like it's a settled, safe thing. It isn't. If you give an agent write access to a database and it hallucinates, or one of its tools starts failing silently, nothing stops it from doing that ten more times before a human even notices. The usual fix people reach for is "human in the loop." Sounds responsible. In practice it doesn't scale. Nobody is reviewing every single tool call an agent makes at 3am. You either become a rubber stamp clicking approve without reading, or the whole pipeline grinds to a halt waiting on you. So I asked a dumber, more mechanical question instead: what if the agent's permissions weren't fixed, and instead moved up and down based on whether its recent actions were actually working? That's basically an error budget. SRE teams have used this idea for years for deployments, if a service is burning through its error budget, you freeze releases. I just pointed the same idea at an AI agent's tool calls instead of at deploys. LEASH sits between an agent and the tools it's allowed to call. The agent doesn't get to decide for itself if it's trustworthy right now, SigNoz decides, based on real telemetry, and LEASH enforces it. There are three tiers: The agent starts at T3 by default. It stays there as long as its tool calls keep succeeding. The moment failures pile up past a threshold in a 5 minute window, SigNoz's alert fires, hits a webhook on my broker, and the agent gets demoted before it can do anything else destructive. I split this into four small services instead of one big one, mostly because I wanted the "agent" and the "thing enforcing policy on the agent" to be genuinely separate processes, not just two functions in the same file pretending to be separate. agent-runner - the fake release agent. Calls tools like read release notes , apply migration , delete staging table . leash-broker - the actual gateway. Every tool call from the agent goes through here first. It checks the current tier, decides allow or deny, and exposes the webhook endpoint SigNoz hits. migration-tool and resource-tool - dumb downstream services doing the actual work, with a flag I can flip to make them start failing on demand.Every one of these is instrumented with the OpenTelemetry Python SDK, shipping spans, metrics and logs straight to SigNoz over OTLP. The part I actually spent the most time getting right wasn't the policy logic, it was making sure the span names and attributes told a story on their own. leash.policy.decision carries the current tier, the required tier, and the verdict. leash.tool.execute carries the actual call. If you open a trace in SigNoz without reading any of my code, you should be able to tell exactly why a call was allowed or denied just from the span attributes. That's the whole point of doing this with SigNoz instead of just writing decisions to a log file somewhere, the trace itself becomes the evidence. This is the one piece where I think a lot of hackathon projects fake it, so I want to be specific about what's real here. I set up a metric alert on leash tool calls total , filtered to tool name = apply migration and outcome = error , aggregated with sum, threshold = 3, over a 5 minute window. Nothing fancy. When it fires, SigNoz POSTs straight to http://