← All articles
2026-11-08 · 6 min read

Bot or customer? Verified-human tiers as the answer to AI agent traffic

A growing share of the requests hitting signup forms, search endpoints and checkout flows no longer comes from a person at a keyboard. It comes from agents: a coding assistant creating an account for a test service, a research agent querying an API, a shopping agent comparing prices. Most of them act for a real human who wants the job done. Some of them are exactly the abuse your bot defenses were built for. The hard part is that, on the wire, the two look the same.

This post argues that "detect AI agent traffic" is the wrong goal. The useful question is not is this a bot? but is there a verified human accountable for this request, and how strongly verified? Answer that, and you can give agents a tier of their own instead of a CAPTCHA.

Why detection keeps losing

Classic bot detection scores a request on signals: IP reputation, TLS and browser fingerprints, mouse movement, timing, headless-browser tells. Every one of those signals describes the client, not the intent. That worked when the only automated clients were scrapers and credential stuffers. It breaks down with agents for three reasons.

  • Legitimate agents look automated, because they are. An agent driving a headless browser or calling your API directly fails every behavioral check, even when the person behind it is a paying customer.
  • Abusive automation imitates humans well. Residential proxies, real browser builds and CAPTCHA-solving services are commodities. The better the detector, the more the attacker invests in looking human — and the more false positives land on real users.
  • A detector can only say "probably." A risk score of 0.7 does not tell you who to bill, who to rate-limit or who to ban. Even a perfect classifier returns "agent" and stops there.

So vendors end up with two bad options: block agents and lose the customers who use them, or let them through and absorb the fake signups, free-tier farming and scraping that come with anonymity.

Reframe: accountability, not humanity

What you actually want to know about an incoming signup is the same whether it is typed by hand or submitted by an agent: is a real person behind it, can that person be held to one account, and what are they allowed to do? A human who sends an agent is still a customer. An agent with no human behind it is the problem.

That shifts the burden from guessing to proving. Instead of inferring humanity from how a request behaves, the request carries a statement — signed by someone you can verify — that a specific person authorized it, which identity checks that person passed, and what limits apply. This is the idea behind verifiable credentials for AI agents, and it is what makes a separate tier possible.

What a verified-human tier looks like

The pattern is simple: keep your anonymous path, and add a second one for agents that present proof.

  • Basic tier. No credential. The agent gets what any anonymous visitor gets: tight rate limits, a small free quota, your existing bot defenses.
  • Verified-human tier. The agent presents a credential that meets your bar. It skips the signup form, gets real limits and, if you want, can pay. No CAPTCHA, because a CAPTCHA was only ever a weak proxy for the thing the credential states outright.

In Notlogin the credential is per vendor. The human pre-authorizes your service once from a dashboard; Notlogin issues a credential naming your service, a scope, an expiry, an optional USDC budget, and the transcript of identity proofs the person had verified at that moment — email, phone, Google, Apple, GitHub, a wallet, World ID, KYC and others. Notlogin signs all of it with an Ed25519 key published at a well-known JWKS endpoint. The agent presents it; your backend verifies the signature locally. The flow end to end is described in how AI agents sign up without a form.

You pick the bar, per vendor

"Verified human" is not one thing. A free search API and a bank should not demand the same evidence. So each vendor declares its own requiredProofs, and the vendor SDK rejects any credential whose transcript is missing one:

  • A mail or notes service might require only email — enough to reach the human and to make bulk signups cost something.
  • A service fighting free-tier farming might require worldid, which Notlogin enforces as one nullifier per account, or a social login with real history behind it.
  • A financial product might require email, sms, wallet and kyc together.

The trade-offs between those levels, and when each one is worth the friction, are covered in KYC for AI agents: proof levels. The point here is that the credential is one transcript and the vendor chooses the threshold. The user cannot inflate it, because the proof list sits inside the signed payload.

What the check looks like on your side

With the vendor SDK, the verified-human branch of a signup handler comes down to one call:

const result = await verifyCredential(vcJson, {
  vendorSlug: 'your-service',
  requiredProofs: ['email'],
})
// valid → create the account on the verified-human tier
// invalid → fall back to the basic tier (or reject)
        

Behind that call the SDK fetches and caches the issuer keys, checks the Ed25519 signature over the canonical payload, checks an optional wallet co-signature over the same payload, and fails on a vendor mismatch, an expired credential or a missing proof. In online mode it also asks the broker whether the credential was revoked and how much of its budget remains. A credential minted for another service is useless at yours, so a leak at one vendor does not open the others — the confused deputy problem in reverse.

Why this beats detection

  • It is binary and explainable. Either the signature verifies and the proofs are there, or they are not. Support can tell a customer exactly which proof is missing.
  • It names someone accountable. Every credential maps to a person who authorized it. Abuse leads to one revocation instead of an endless game of IP blocks.
  • It carries limits you can enforce. Scope, expiry and a spending ceiling travel with the request, so an agent that loops cannot outspend what its human approved. See how agents pay safely with x402.
  • It does not punish honest automation. The customers who send agents get a better path than the form, instead of a wall.

What it does not solve

A credential is a bearer artifact: whoever holds the JSON can present it. Revocation is the main defense, which is why online verification matters for anything valuable, and why agents should keep credentials out of reach of injected instructions (see prompt injection and credential theft). Proofs are also a snapshot at issuance; if your bar rises, users re-issue. And a verified-human tier does not replace your anonymous defenses — it sits beside them, so the traffic left in the basic tier is the traffic that chose not to prove anything.

Getting started

Stop trying to tell bots from customers by how they move. Give agents a way to show who sent them, set the proof bar that fits your risk, and let the rest fall into the basic tier. If you run a service and want agents to arrive with a signed human transcript, register as a vendor and declare your required proofs. If you use agents and want them treated as the customer you are, create a Notlogin account and authorize your first vendor.

Let your agents sign in everywhere

Verify once, pre-authorize vendors, and issue a verifiable credential your agents can use with no forms and no OAuth dance.

Get started
Bot or customer? Verified-human tiers as the answer to AI agent traffic | Notlogin