DEV Community

Shorya Sethia
Shorya Sethia

Posted on

AI agents can now click "delete" in your product. Who's checking?

If a human logs into your product, you already have auth, roles, and audit logs. If an AI agent calls the same endpoints, what do you have?

For most products, the honest answer is: an API key and hope.

The gap nobody built for

We spent a decade building permission systems for humans clicking buttons. RBAC, SSO, audit trails, all of it assumes a person is on the other end, moving at human speed, making one action at a time.

Agents break every one of those assumptions. They call your API in bursts, chain actions together, and increasingly use the same session across many requests without a human watching each one. Most teams patch this with an if/else check buried in a route handler. That works until you need to:

  • version what an agent is allowed to do without redeploying
  • pause a destructive action for human approval mid-flow
  • revoke access to one agent without touching everyone else
  • prove after the fact exactly what happened and why it was allowed

An if/else can't do any of that. It's not a permissions system, it's a guess that happens to compile.

What I built instead

Duct is a manifest-driven action enforcement layer that sits between your product and whoever is calling it, human or agent or another product.

Duct

Three primitives:

duct.config.ts — a manifest that declares every action your product exposes, what it does, and what it requires to run. This is the single source of truth, not scattered checks across your codebase.

Shell — the surface a human uses. Same actions, same manifest, but rendered for a person.

Invoke API — the surface an agent uses. Same actions, same manifest, enforced the same way.

The part that took the longest to get right is the token model. There are two tokens, not one:

A delegation token that says "this agent is allowed to act on this account, generally, for this long." Longer-lived, coarse-grained.

A per-action approval token that says "this specific side-effecting action is approved, right now." Short TTL, single use, required only for actions the manifest marks as sensitive.

Splitting these apart is what makes revocation and human-in-the-loop approval actually work. You can kill an agent's delegation token instantly without touching in-flight actions that already got their per-action approval. And you can force a human checkpoint on a refund or a delete without slowing down the 95% of actions that don't need one.

The hard part wasn't the happy path

Anyone can build this for the easy case: one human, one agent, one session. The interesting failures show up at the edges. An agent with browser or computer-use tools can technically forward an approval URL, but the proof of approval (a session-bound cookie) only gets issued at the moment a human actually loads that page. An API-only caller can't fake that, even if it has the URL. That distinction, between an agent forwarding a link and a human actually completing an approval, is most of the design work.

There's also a case I couldn't solve: a fully anonymous, agent-only product with no human and no KYC anywhere in the chain. For that, all you get are deterministic policy caps. No amount of clever token design gets you accountability if there was never an identity to begin with. Worth knowing where the line is instead of pretending otherwise.

Where this leaves us

Duct isn't a diagram. It's a working enforcement layer, built specifically because none of the existing auth or agent tooling answers "who approved that" for actions, not just credentials.

If you're building a product where agents call in and you don't yet have a real answer to that question, I'd genuinely like to hear how you're handling it, or if you want to try Duct on what you're building.

Highly recommend to checkout Duct.

Top comments (0)