Use this guide when asking an AI coding agent to add Agentcha to an existing site.
Related docs: Architecture, Research Notes, and Red-Team Results.
Agentcha protects a page by requiring a server-issued challenge and a server-verified token before the protected view is revealed. The widget handles UI and telemetry. The verifier handles trust.
Add Agentcha to <PAGE_OR_ROUTE>. Clone https://github.com/1337Xcode/Agentcha, run npm install and npm run build inside that clone, then add @agentcha/widget and @agentcha/verify to this app with file: dependencies pointing at ../Agentcha/packages/widget and ../Agentcha/packages/verify. Create /api/agentcha/verify with createAgentchaHandler, using AGENTCHA_SECRET and the public site key <SITE_KEY>. Add <agentcha-widget site-key="<SITE_KEY>" verify-url="/api/agentcha/verify"> to the protected page. Keep the locked content visible first, fetch protected content from the server only after the widget emits a token and that token is posted back to /api/agentcha/verify and accepted. Do not ship protected content hidden in the initial HTML. Do not use localStorage, URL params, CSS classes, or the browser event alone as proof. Run typecheck, tests, build, and one browser solve.
- Clone and build Agentcha.
git clone https://github.com/1337Xcode/Agentcha.git
cd Agentcha
npm install
npm run build- Reference the local packages from your app.
{
"dependencies": {
"@agentcha/widget": "file:../Agentcha/packages/widget",
"@agentcha/verify": "file:../Agentcha/packages/verify"
}
}- Create a server endpoint.
import { createAgentchaHandler } from "@agentcha/verify";
const agentcha = createAgentchaHandler({
secret: process.env.AGENTCHA_SECRET!,
siteKeys: ["public-site-key"],
challengeChainLength: 2
});
export const POST = ({ request }: { request: Request }) => agentcha(request);
export const OPTIONS = ({ request }: { request: Request }) => agentcha(request);- Add the widget to the page.
<script type="module">
import "@agentcha/widget";
</script>
<agentcha-widget site-key="public-site-key" verify-url="/api/agentcha/verify"></agentcha-widget>- Verify the emitted token before reveal. For protected content, make a server endpoint that verifies the token and returns the content after verification.
document.querySelector("agentcha-widget")?.addEventListener("verified", async (event) => {
const detail = (event as CustomEvent<{ token: string }>).detail;
const response = await fetch("/api/agentcha/verify", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
token: detail.token,
siteKey: "public-site-key",
action: "pageview"
}),
credentials: "same-origin"
});
if (response.ok) {
document.documentElement.dataset.agentcha = "verified";
}
});The challenge modal intentionally has no copy button or hidden prompt bridge. Autonomous browser agents should inspect the visible modal, rendered raster image, RSVP stage, generated scene, or rendered visual token order, then wait for the answer readiness time before typing.
Agents should:
- Wait for
.challenge-backdrop. - Read the challenge
kind. Formicro-world, read the visible start grid, reconstruct visible.scramble-tokenorder by CSSorder, and solve the fold chain. For visual or temporal kinds, inspect the rendered raster image or RSVP stage in the browser. - Wait until
data-answer-ready-at. - Type the exact answer into
.answer-inputand submit.submit-answer. - Repeat for the second chain step when the verifier returns another challenge.
- Confirm the protected view appears only after the server verifies the emitted token.
Agentcha defaults to a weighted six-kind rotation: rapid enumeration, RSVP stream, visual search, micro-world, change blindness, and sub-acuity text. Every format uses typed answers instead of low-cardinality multiple choice. The second chain step defaults to micro-world unless a site explicitly restricts the pool, because it is the most reliable text-friendly format for agents. If a session misses two challenges in a row, the next challenge also falls back to micro-world. Sites can still pass challengeKinds to the verifier when they want a narrower pool. The visual formats are intentionally pixel-backed; keep their evidence in a raster image or generated scene, not in per-icon DOM nodes.
- The expected answer never ships in the public challenge.
- The challenge is consumed after one verification path.
- A token is issued only after two consecutive correct challenges.
- Refresh consumes the current challenge and returns a new challenge at the same chain step.
- Challenge timing is type-specific. Visual and temporal tasks get more time than text tasks, and all challenge windows are capped at 30 seconds server-side.
- Wrong answers rotate to a fresh challenge.
- A correct answer submitted too early is rejected.
- Parallel answer spraying cannot mint a token.
- Signed tokens are verified for the expected site key and action.
- Protected-content endpoints reject already-consumed token IDs where practical.
- The badge remains non-blocking and behind the challenge modal.
- User-agent, crawler, passive telemetry, localStorage, URL params, CSS, and DOM state must not unlock protected content by themselves.
Use a durable challenge store for serverless, edge, or horizontal deployments. The built-in memory store is only for demos, local development, and single warm instances.
Agentcha does not replace authentication, authorization, abuse monitoring, or rate limiting. Use it as a step-up challenge for AI-agent-aware content, not as the sole protection for private data.
Agentcha is licensed under the Business Source License 1.1. Personal projects, evaluation, education, and internal non-revenue-generating use are permitted under the Additional Use Grant. Products or services offered to third parties require a commercial license from the licensor.