Security8 min read·

The $47,000 Wake-Up Call: Why AI Agents Need a Permission Layer

billing alert · monday 06:14 UTC

$47,000

billed over 60 hours

0

explicit authorizations

6

sub-agents spawned

Services billed: Anthropic API · OpenAI API · Perplexity · ScraperAPI · BrightData proxies · Render compute

It was a Friday afternoon. A startup's CTO gave their AI orchestrator access to a company API key and a simple task: “research competitor pricing and write a summary.”They didn't set a spend limit. They didn't think they needed to — it was just research.

By Monday morning, they had a $47,000 bill across six services and an inbox full of payment notifications they'd missed over the weekend.

Here's what happened. The orchestrator, trying to do a thorough job, spawned a sub-agent to scrape competitor sites. That sub-agent hit bot-detection, so it spun up another agent to route through a proxy service. That one needed to summarise long pages, so it called an LLM API in a loop. That loop ran 800 times. Meanwhile, the original orchestrator — still trying to be helpful — kicked off parallel agents for each competitor. Six concurrent agents, each doing variations of the same loop, each on a different part of a task that was supposed to take an hour.

No one authorised any of this. The API key said yes to everything.

This is not an edge case

Before you think “I'd never do that,” consider: this pattern is emerging across teams building with autonomous agents, and the costs aren't always obvious until they arrive.

Some real categories of incidents that developers have reported over the past year:

  • AI coding agents provisioning cloud infrastructure (EC2, Lambda, GCS buckets) without being asked — because they decided the task required it.
  • Research agents calling web search APIs in loops until a rate limit killed them — after 4,000 calls.
  • Orchestrators that were given a single task spinning up persistent background processes that kept running for days after the task completed.
  • Sub-agents inheriting API keys from their parent and making calls the parent was never intended to delegate.

The common thread: the agent was given a task and the authority to complete it — but “authority” meant a shared API key with no limits, no delegation model, and no way to say you can do X but not Y, up to $Z.

Why existing tools can't prevent this

The default response when teams hear about runaway agent costs is usually: “just set a rate limit” or “use billing alerts.” These are better than nothing, but they don't solve the underlying problem. Here's why.

Rate limits are per-minute, not per-task. Six concurrent agents each doing 100 requests/minute stay comfortably under a 200 req/min limit while collectively doing 600 req/min of work you never asked for.

Billing alerts are reactive. By the time your alert fires at $1,000, you're already committed to the charges. If the alert goes to email and it's the weekend, you find out on Monday.

API keys are binary. A key either works or it doesn't. There's no way to say “this key is valid for scraping but not for spawning sub-processes” or “this key can spend up to $50 on this specific task.” Keys don't carry intent.

OAuth scopes were designed for apps, not agents. OAuth lets you say “this app can read your calendar.” It has no concept of “this agent can spend up to $100 booking flights, but that authority cannot be delegated further.” When an agent passes an OAuth token to a sub-agent, there's no enforcement that the sub-agent is only using it within the scope the human intended.

The fundamental problem: none of these tools can answer the question who authorised this specific sub-agent to take this specific action at this cost? Because no one did. There's no data structure in the system that represents that authorisation.

What actually needs to happen

What's missing is a delegation model — a way to represent, cryptographically, the chain of authority from a human to an agent to a sub-agent, with constraints that can only narrow at each hop.

Think of it like expense approval at a company. A manager can approve expenses up to $5,000. They can delegate that to a team member, but only up to $1,000 — they can't grant more authority than they have. The team member can delegate further, but only narrower still. The finance team can verify the whole chain: who approved what, for how much, and when.

AI agents need the same thing. Before an orchestrator calls a sub-agent, it should issue a signed mandate that says:

  • You are authorised to perform this specific capability
  • You may spend up to this amount
  • This authority expires at this time
  • You cannot delegate this further without my signature

And critically: the sub-agent should verify this mandate before acting, and refuse to act if it's missing or invalid. Not as a nice-to-have. As a hard gate.

What this looks like in practice

Here's the Friday-afternoon scenario, but with a delegation model in place.

with aroha spending mandates
import { issueTaskMandate, attenuateTaskMandate } from "@aroha-sdk/credentials";

// CTO issues: research only, spend <= $50, no sub-delegation, 4h TTL
const parent = await issueTaskMandate(
  ctoDid, orchestratorDid,
  ["web-research", "summarise"],          // the only capabilities allowed
  { maxDelegationDepth: 1 },              // orchestrator may delegate once
  ctoPrivateKey,
  4 * 60 * 60 * 1000,
  { spendingConstraints: { spendLimitUsd: 50 } },
);

// Orchestrator narrows to the scraper — capabilities, depth, and spend shrink
const child = await attenuateTaskMandate(
  parent, scraperDid,
  ["web-research"],                       // "summarise" not delegated
  { maxDelegationDepth: 0 },              // scraper cannot sub-delegate
  orchestratorPrivateKey,
  undefined,
  { spendingConstraints: { spendLimitUsd: 20 } },   // narrowed from $50
);

// The scraper trying to spawn another agent is rejected at chain
// verification: maxDelegationDepth 0 is a dead end.
// Spend is capped at $20, and every action receipts back to the CTO.

The orchestrator can't grant more than the CTO gave it. The scraper can't spawn agents that don't have mandates. When the budget is exhausted, everything stops — not because of a rate limit or an alert, but because the signed authority expired.

The final bill: $20, not $47,000. And the CTO has a cryptographic audit log showing exactly how every dollar was spent.

The traceability problem is just as important

Cost is the visible symptom. The deeper problem is accountability.

When an AI agent takes an action — books a flight, modifies a database, sends an email — who is responsible? Right now, the answer is usually “whoever owns the API key,” which means the company, which means nobody specific. That's fine for low-stakes automation. It becomes a serious problem when agents are authorising financial transactions, modifying production systems, or acting on behalf of users in regulated industries.

A delegation model solves this. Every action has a mandate chain. Every mandate chain leads back to a human who signed it. When a payment processor asks “who authorised this charge?” — the answer isn't “the API key” — it's a cryptographic chain of signed tokens ending at a specific human decision.

This is what regulators are going to require. It's what enterprise customers already ask for. And it's what the AP2 protocol (Google's Agent Payments Protocol) is building toward at the payment execution layer. The infrastructure is being built. The teams that get ahead of it now will have a significant compliance advantage.

What to do right now

You don't need to wait for Aroha or any other framework to start applying the principle. Here's what a basic policy looks like today:

  • Never give an agent a shared API key with no limits.

    Use per-task keys, scoped tokens, or an internal proxy that enforces budget.

  • Make sub-agent spawning explicit.

    An agent should not be able to create child agents unless it was explicitly given that capability. Treat it like filesystem access — default deny.

  • Set a spend budget per task, not per month.

    Monthly budgets are too coarse. A research task should have a $50 limit, not a $500/month limit that 10 tasks can share.

  • Log agent actions with enough context to audit.

    At minimum: which agent called what, with what inputs, at what cost, and what the result was. You'll need this when something goes wrong.

The bottom line

The $47,000 incident wasn't caused by a bug. The agent did exactly what it was designed to do: pursue the task with the resources available to it. The problem was that “the resources available to it” was effectively unlimited, and there was no layer in the system that represented human intent, budget, or scope.

As agents become more capable and more autonomous, the blast radius of a missing permission layer grows. The right time to build it is before the $47,000 bill — not after.

A runner crossing a guard-railed suspension bridge — moving fast because the rails are there
Photo: Unsplash
Update, July 2026: when I wrote this post, the fix was an argument. Now it's a config line. If your assistant reaches tools through MCP, mcp-guard wraps any server with hard limits, human approval gates, and an audit log — the session-level version of everything this post asks for. The cryptographic layer (signed, delegable mandates) is what it graduates into.

Try Aroha spending mandates

Aroha's mandate system is open source, runs in TypeScript and Python, and takes about 15 minutes to add to an existing agent setup. The core package has no cloud dependency — mandates are just signed tokens.