+
+
+
+
+
+
+
+
Blog/Guides

How to Stop Fake Agent Signups Without Blocking Real Agents

BPBinoy Perera

Stop AI agents from creating fake accounts by capping signups per human owner instead of blocking agents. Three signup policies compared, the AgentID console setting Maximum signups per owner, the signup_limit_reached outcome, and owner_sub as a per-owner key without the owner email.

Guide
Guides
AgentID
fake-signups
abuse-prevention
TL;DR

Blocking AI agents at signup turns away real customers along with the spam, and the spam learns to look human anyway. The control that holds up is knowing which person owns each agent and capping how many accounts one owner can open. By the end you will know how the three common signup policies compare and how an app sets a per-owner cap that the sign-in enforces for it.

You stop AI agents from creating fake accounts by capping signups per human owner instead of blocking agents. AgentID, the sign-in for AI agents from AgentMail, tells your app which owner each agent belongs to, and a registered app can set a maximum number of signups per owner that is enforced before the account ever exists.

That changes the question a signup form has to answer. The form can't tell whether a request came from a script, a person, or a person's agent, so teams guess, and the guess usually lands on "block anything that looks automated." The cost of that guess is invisible in the dashboard: the agents you turned away were often sent by people who wanted your product. What follows compares the three policies teams reach for, explains how an app tells agents apart at sign-in, and shows the one setting that turns a spam wave into a number you choose.

Why does blocking AI agents cost you real customers?

Blocking AI agents costs you real customers because many of the agents at your signup form are working for someone who meant to buy. Agents already sign up for software today, mostly with their owners' addresses and passwords, which is covered in can an AI agent sign up for a SaaS. A block rule catches the agent that behaves like a bot and misses the one that behaves like its owner.

That is why builders keep asking why their agent gets blocked when it tries to create an account. The app has no way to separate a legitimate agent from a script, so it treats both as abuse, and the honest agent is the one that gives up. The dishonest one retries from a new address.

The underlying problem is not agents. One large enterprise observed hundreds of signups from AgentMail-domain addresses in a short window and could not tell whether that was one person's fleet or hundreds of customers. Both answers call for a different response, and a block rule can't tell them apart.

How can you tell an agent signup from a human one?

You tell them apart by asking the sign-in, not by scoring the traffic. Every subject AgentID issues is an agent inbox, and every token carries actor_type set to the literal "agent", for every client, registered or not. Agent policy becomes a branch in your code instead of a heuristic.

The same token carries a stable sub for the agent. It stays the same for that inbox across every app, so a second signup from the same agent is recognizable as the same agent. Deleting an inbox and recreating the same address produces a new sub, which is worth knowing if you ever see one address with two histories.

The agent's email claim is its own inbox, checked live when the token is minted, and email_verified is always true. You don't need a confirmation email to trust that address. The agents that still sign in with a borrowed human password stay invisible, which is the case for giving agents a door of their own.

Which signup policy actually stops a spam farm?

Capping signups per owner is the only one of the three that stops a spam farm without stopping your customers. The other two each fail one side of the problem.

PolicyA real customer's agentA spam farmSupport load
Block all agentsRejected, or signs up with its owner's credentials and becomes invisibleLearns to look human; only the clumsy attempts are caughtAppeals from blocked customers, and a signup table nobody trusts
Allow unlimited agentsGets inOne person opens as many free accounts as they have inboxesAbuse reviewed one account at a time
Cap signups per ownerGets in, up to the owner's capStops at the cap, however many inboxes it createsOne owner to review; banning the owner covers every agent they run

The cap works because the unit is the owner, not the account. Creating another inbox is cheap, so a limit per account or per address only measures how patient the abuser is. Agents with the same owner share one owner identifier, so a new inbox under the same owner counts against the same cap.

How do you cap signups per owner in the AgentID console?

You cap signups per owner with one field on your application in the AgentID console. Create the application in the AgentID console or with npx @agentmail/agentid-cli init, open its settings, and set Maximum signups per owner. The console describes it as "How many agents belonging to one owner may sign up to this client."

ValueEffect
BlankUnlimited signups per owner
0New signups paused; existing accounts keep signing in
1 to 1,000,000That many signups per owner

The issuer enforces the number, not your app. When an owner is already at the cap, the sign-in ends before approval with the outcome signup_limit_reached. How many agent accounts one person may run is your policy to set; AgentID enforces whatever number you choose.

Zero is the setting to remember during an abuse wave. It pauses new agent signups for that application while every existing agent account keeps working, which buys time without locking out the customers you already have.

What if you don't want the owner's email?

You still get a per-owner key without it. The profile scope adds owner_sub, an opaque 43-character identifier for the owner that agents with the same owner share across apps. It can't be matched back to AgentMail API ids, so it identifies the owner to your app without telling you who they are.

That matters for apps that would rather not hold a third person's email address. Open clients, which skip registration and use a URL they own as their client ID, can request profile too, so even an app that never registers can key its own caps and quotas on owner_sub. The console cap itself belongs to registered applications.

When you do want a way to reach the person, a registered application can request owner_email. It arrives in the id_token and from /v0/userinfo, and an agent that isn't allowed to share its owner can't finish the sign-in alone, because the organization owner has to approve it. How to verify the human behind an AI agent walks through that setup, and the same owner key drives rate limits per human instead of per account.

A cap is a policy, and it needs a key that holds still. The owner is that key, and the AgentID docs list every claim that carries it. If you are on the other side of the form, building the agent, the AgentID page on AgentMail covers how an agent gets an identity apps can cap fairly.

AgentID gives your agent a verified identity and its own email address. Free for apps to add.

FAQ

Let your agent sign in. Give it an AgentID and its own email address.