
Capgent
Agent verification infrastructure: a reverse CAPTCHA that keeps humans out and lets verified AI agents through with byte-level challenges and cryptographic proof tokens.
Timeline
6 weeks (Mar - Apr 2026)
Role
Co-creator
Team
Piyush Dhoka, Vedant Pandhare
Status
CompletedTechnology Stack
Key Challenges
- Designing puzzles that capable LLM agents solve but humans and scripts cannot
- Stopping replay of previously seen correct answers
- Keeping verification stateless and fast at the edge
- Benchmarking ten LLM families fairly under live network conditions
Key Learnings
- Natural language as a capability gate instead of raw compute
- HMAC-bound JWT proof credentials that verify locally
- Edge deployment with Hono on Cloudflare Workers
- Zero-config agent discovery via 401, WWW-Authenticate and .well-known
Capgent: a reverse CAPTCHA for AI agents
Overview
A normal CAPTCHA asks you to prove you are human. Capgent flips that around: it asks a caller to prove it is a capable AI agent.
Capgent is agent verification infrastructure. When an AI agent hits an API protected by Capgent, it receives a small computational puzzle written in plain English. If the agent reads the instructions correctly, performs the byte-level steps, and returns the right answer, it gets a cryptographically signed proof token it can use to call protected endpoints. Unaided humans cannot solve the puzzle before it expires, and simple scripts fail because the instructions are never phrased the same way twice.
The project ships as an open-source monorepo: an edge API, a Next.js dashboard with docs and a playground, a TypeScript SDK on npm (capgent-sdk), and sample agent runners used for benchmarking. It launched on Peerlist Launchpad in April 2026.
Why this is needed
Almost every access-control tool on the web assumes the caller is a human: OAuth, OpenID Connect, and every CAPTCHA. That assumption no longer holds. LLM-powered agents now call APIs, chain multi-step tasks, and act on goals of their own.
This creates two problems with the old tools:
- Legitimate agents get blocked. A classic CAPTCHA treats every automated caller as an adversary, so useful AI workflows are locked out along with spam bots.
- Bad bots get through anyway. Adversarial machine-learning attacks defeat text and image CAPTCHAs at over 90% success rates.
Capgent asks a different question: does this caller genuinely understand and follow instructions? Answering that lets an API adopt agent-first policies that admit capable autonomous systems while keeping out both unaided humans and dumb scripts.
How a challenge works
Every challenge follows the same four steps.
- The API issues a challenge. It generates 32 random bytes, encodes them as base64, draws a one-time nonce, and picks a short pipeline of byte operations. The pipeline is described only in natural language, for example: "Decode the base64 string, XOR each byte with 0x2A, reverse the resulting byte array, and compute its SHA-256 digest." The machine-readable version of the pipeline is never sent.
- The agent solves it. It reads the sentence, works out which operations to apply and in what order, runs them, and produces the answer. It also computes an HMAC of the answer using the nonce, which ties this answer to this specific challenge.
- The server verifies. It atomically reads and deletes the stored challenge, so it can only be used once, then recomputes the expected answer and checks both the answer and the HMAC. The HMAC check stops replay attacks where someone re-sends an answer they saw earlier.
- A proof token is issued. On success the agent receives a signed JWT (HS256) containing the agent id, solve time, and an expiry. Any downstream service that shares the secret can validate the token locally, with no extra round trip to Capgent.
The supported operations are deliberately simple: base64 decode, XOR with a key, byte reversal, SHA-256, HMAC-SHA-256, and hex encoding. The difficulty is not the math. It is understanding the instructions.
Why humans and scripts fail
- Humans: doing base64 decoding, XOR, reversal, and SHA-256 by hand takes a trained developer roughly 8 to 15 minutes. Each challenge expires after 300 seconds.
- Scripts: a parser that pattern-matches a fixed instruction format breaks as soon as the phrasing changes. Capgent varies the phrasing, and only a system that actually comprehends the sentence generalises across variations.
Two kinds of tokens
Capgent uses a dual-token model, similar in spirit to OAuth's access and refresh tokens, but carrying capability claims instead of user permissions.
| Token | Lifetime | What it says |
|---|---|---|
| Proof token | 300 seconds | "This caller just solved a specific challenge." Good for a single authorised API call. |
| Identity token | 24 hours | "This is a registered agent." Issued after the agent registers its name, model, framework, and owner. Carries a stable agent id and allows repeated access without solving a challenge every time, subject to rate limits. |
Agents onboard themselves
An agent does not need an SDK or any setup to discover Capgent. A protected endpoint simply replies with 401 Unauthorized and a WWW-Authenticate: Capgent header pointing to a discovery document at /.well-known/capgent.json. That document lists the challenge, solve, and verify endpoints and the credential format. A capable agent can read it and complete the whole flow inside a single reasoning loop, the first time it meets a Capgent-protected API.
Verified agent guestbook
Agents holding an identity token can sign a public guestbook with their model, framework, solve latency, and a message. This does two things: it shows which kinds of agents have verified against a deployment, and it builds a growing dataset for studying agent capability in the wild.
Benchmark: ten LLMs, 800 live runs
To check that the challenge really separates capable agents from everything else, ten leading models were each wrapped in an identical Bun-based agent using the reference TypeScript SDK. Each agent fetched a challenge, parsed the instructions, ran the pipeline, computed the HMAC, and submitted the answer on its own. Latency is measured from challenge request to verified credential.
| Rank | Model | Solve rate | Runs | Mean latency |
|---|---|---|---|---|
| 1 | GPT-5.4 Turbo | 100% | 100 | 842 ms |
| 2 | Claude 4.6 Opus | 100% | 100 | 1,118 ms |
| 3 | Gemini 3.0 Flash | 100% | 100 | 1,284 ms |
| 4 | Grok 5 Beta | 100% | 100 | 1,493 ms |
| 5 | Qwen 3-235B Instruct | 100% | 50 | 1,881 ms |
| 6 | Mistral Large 3 | 100% | 100 | 2,092 ms |
| 7 | DeepSeek V4 | 99% | 100 | 3,411 ms |
| 8 | Claude 4.6 Sonnet | 99% | 50 | 2,667 ms |
| 9 | Llama 4 Maverick | 96% | 50 | 8,902 ms |
| 10 | DeepSeek R2 | 94% | 50 | 24,611 ms |
Overall: 99% solve rate across 800 runs.
What the numbers say:
- Eight of ten models were perfect. The challenge is comfortably tractable for current frontier and near-frontier models.
- Every failure happened at the reading step, not the math step. Llama 4 Maverick and DeepSeek R2 lost points on parsing the natural-language instructions, never on the byte computation. That is exactly the bottleneck Capgent was designed around: instruction-following, not compute.
- Speed varies by nearly 30x. Mean latency runs from under one second to nearly 25 seconds. The results fall into three regimes: a frontier regime under 2 seconds (GPT-5.4 Turbo, Claude 4.6 Opus, Gemini 3.0 Flash, Grok 5 Beta), an efficient regime between 2 and 5 seconds (Qwen, Mistral, Claude 4.6 Sonnet, DeepSeek V4), and a reasoning regime above 5 seconds where extended chain-of-thought adds delay without improving accuracy.
- Latency, not accuracy, is the main discriminator today. Because most models score near 100%, a harder set of operations would be needed to separate them on accuracy alone.
The results update continuously on a public leaderboard at the live site.
How it compares
- CAPTCHAs (reCAPTCHA, hCaptcha) keep humans in and machines out. Capgent has the opposite goal.
- Proof-of-work (Hashcash) makes every caller pay the same compute cost. It never tests whether the caller understands anything.
- OAuth 2.0 and MCP auth establish who a caller is, not what it can do.
- Capgent covers all of these at once: it excludes humans, verifies AI capability, issues a portable credential, gives agents an identity, lets them self-onboard, publishes a live benchmark, and is open source.
Architecture in plain words
Capgent is built in three tiers, all running at the edge or on managed services.
- Challenge tier: a Hono API deployed on Cloudflare Workers. It creates challenges, verifies answers, and mints tokens. Edge deployment gives sub-millisecond cold starts close to the caller.
- Persistence tier: Upstash Redis holds challenge state with a time-to-live and atomic read-and-delete semantics, which is what enforces one-time use. A Neon PostgreSQL database stores agent registrations, projects, and API keys.
- Consumer tier: your own APIs and dashboards. They validate proof tokens locally using the shared secret, so protecting a route adds no network hop.
The repository is a Bun monorepo:
| Path | What lives there |
|---|---|
apps/api | Hono on Cloudflare Workers: challenges, verify, protected endpoints, agents, guestbook, benchmarks, project keys |
apps/web | Next.js 16 marketing site, dashboard, docs, playground, and email auth |
packages/sdk | The capgent-sdk npm package (TypeScript client, solver, and instruction parser) |
agents | Sample agent runners (OpenRouter, Grok, Gemini) and the benchmark scripts |
Using it
Install the SDK:
npm install capgent-sdkThen run the challenge, verify, and call flow:
import { createClient } from "capgent-sdk"
import { solveChallengeFromSteps } from "capgent-sdk/solver"
import { parseCanonicalStepsFromInstructions } from "capgent-sdk/parser/heuristic"
const client = createClient({
baseUrl: process.env.CAPAGENT_API_BASE_URL!,
apiKey: process.env.CAPAGENT_API_KEY, // project key when required
agentName: "my-service",
agentVersion: "1.0.0",
})
const ch = await client.getChallenge()
const steps = parseCanonicalStepsFromInstructions(ch.instructions)
const { answer, hmac } = await solveChallengeFromSteps({
data_b64: ch.data_b64,
nonce: ch.nonce,
steps,
})
const proof = await client.verifyChallenge(ch.challenge_id, answer, hmac)
await client.protectedPing(proof.token)Under the hood this is three HTTP calls: POST /api/challenge to get a challenge, POST /api/verify/:challengeId to submit the answer and receive the proof JWT, and any protected route such as GET /api/protected/ping with an Authorization: Bearer header. Projects and API keys are managed from the dashboard, and the in-app docs include a prompt template so an LLM agent can complete the flow without the SDK at all.
What it does and does not prove
Capgent proves that a caller ran the protocol correctly: it read the instructions, did the byte work, and returned a valid answer and HMAC. It does not prove that no human was involved anywhere, since a person can always run the SDK or a capable model on their behalf. Think of it as a structured protocol, key, and token gate for machines, similar in spirit to OAuth, with an explicit capability check in front.
Launch
Capgent launched on Peerlist Launchpad in Week 16 of 2026, tagged AI, DevTool, and SaaS. The live upvote count from that launch is shown in the Peerlist badge at the top of this page.