Every bot detection system I've seen works with two actors: human or bot. Block the bot, let the human through.
That model is wrong in 2026.
There is a third actor: AI agents acting legitimately on behalf of real users. Shopping assistants. Automated onboarding flows. Fintech integrations. These agents look like bots by every traditional signal: headless browser characteristics, scripted input patterns, no idle pauses. But blocking them means turning away real business.
I built Nyasa to handle all three.
Why existing tools fail now
CAPTCHA was built for bots that couldn't read distorted text. Those bots are dead. CAPTCHA farms solve challenges at $0.50 each. LLM vision models solve them in milliseconds.
Device fingerprinting catches webdriver flags and automation markers. Modern headless browsers patch those out. Playwright, Puppeteer, and every major automation framework have community patches specifically for passing fingerprint checks.
Behavioral analytics (typing cadence, mouse movement) catch scripted bots. But LLM agents don't use scripted input anymore. They type at 60-80 WPM with realistic keystroke intervals, move the mouse in curved paths, and pause at form fields before filling them.
The deeper problem is architectural. Existing systems ask: "Is this a bot?" Nyasa asks: "Who is this session?" The answer is one of three things.
The three-actor model
Nyasa classifies every session as exactly one of:
Human: no detection rules fired
AuthorizedAgent: holds a valid cryptographic identity claim, automatically bypasses bot rules
UnauthorizedBot: one or more detection rules fired
The AuthorizedAgent category is the real addition. An AI shopping assistant built on top of your product shouldn't have to pass a CAPTCHA. It should present a signed identity claim, and your system should recognize and respect it. Nyasa handles that handshake.
Feature extraction architecture
Early versions of Nyasa had each detection rule computing its own derived metrics from raw signals. That caused two problems: duplicated math across rules, and rules diverging when they read the same underlying signal at slightly different times during a session.
The feature extraction layer solves this. It runs once per session and computes 8 shared derived metrics before any detection rule evaluates. Every rule reads from the same computed values.
The metrics include things like overall typing variance, click precision distribution, and mouse activity ratio. Computing them once means a detection rule that needs "mouse stillness percentage" and a sibling rule that also needs it will always agree on the number.
isMultimodalBot benefits from this the most. It reads the DetectionResults of its sibling rules rather than re-running signal evaluation. Near-miss composition (where a session nearly triggers multiple rules without fully triggering any) gets caught without any rule having to re-sample data that may have aged out.
The verdict system
Every session gets a verdict object with three fields:
interface NyasaVerdict {
type: 'Human' | 'AuthorizedAgent' | 'UnauthorizedBot';
confidence: number; // 0.0 to 1.0
badges: DetectionBadge[]; // which rules fired or nearly fired
}
Confidence is a noisy-OR score across all active rules. If one rule fires with 0.8 confidence and a second fires with 0.6, the combined score is 1 - (1 - 0.8) * (1 - 0.6) = 0.92. Multiple weak signals compound.
Badge labels tell you which rules contributed. A session might come back as UnauthorizedBot with badges for isHeadless and isLLMAgent, which tells you this is a headless LLM agent. That gets different handling than a scripted form filler.
The verdict payload ships via navigator.sendBeacon. Non-blocking, fires after the page interaction completes, survives page unload. Your analytics pipeline or backend decision layer receives it without adding latency to the user-facing flow.
The SDK runs entirely in the browser. Signals are collected passively as the session progresses. The feature extraction layer runs on a timer and on key events. Detection rules evaluate when a verdict is requested or automatically at session end.
Dual packaging
Nyasa ships as both ESM and IIFE from a single tsup build config.
ESM for bundlers:
import { createNyasa } from '@devanshhq/nyasa';
const nyasa = createNyasa({
endpoint: 'https://your-backend.com/nyasa',
agentBypass: true,
});
nyasa.start();
IIFE for script tags, no bundler required:
<script src="https://cdn.jsdelivr.net/npm/@devanshhq/nyasa/dist/nyasa.iife.js"></script>
<script>
Nyasa.createNyasa({
endpoint: '/api/nyasa',
agentBypass: true,
}).start();
</script>
Same source, two outputs. The tsup config handles the split. No separate build for CDN distribution.
Installation and quick start
npm install @devanshhq/nyasa
Minimal setup:
import { createNyasa } from '@devanshhq/nyasa';
const nyasa = createNyasa({
endpoint: '/api/session-verdict',
});
nyasa.start();
// Get the verdict at any point
const verdict = await nyasa.getVerdict();
console.log(verdict.type); // 'Human' | 'AuthorizedAgent' | 'UnauthorizedBot'
console.log(verdict.confidence); // 0.0 - 1.0
console.log(verdict.badges); // ['isHeadless', 'isLLMAgent', ...]
On the backend, you receive the verdict via the beacon endpoint and decide what to do: allow, challenge, block, or route differently based on the type.
The authorized agent bypass
If you're building an AI agent that needs to interact with Nyasa-protected pages, set the signature before the SDK initializes:
// In your agent code, before navigating to the page
window.__nyasaAgentSignature = {
token: 'signed-jwt-from-your-auth-server',
agentId: 'shopping-assistant-v2',
issuedAt: Date.now(),
};
Or via meta tag for server-rendered flows:
<meta name="nyasa-agent-signature" content="signed-jwt-here" />
The isAuthorizedAgent rule reads this claim, validates the signature, and short-circuits to AuthorizedAgent. No other rules run. The session is logged as a known agent, not blocked as a bot.
This is the part that most bot detection tools don't have a concept for. If you're running a fintech integration or an AI onboarding assistant, you shouldn't have to fight your own security layer.
What it catches that others miss
Traditional fingerprinting misses LLM agents because they run in real browsers with patched automation markers. Traditional behavioral analytics miss them because modern LLM agents have realistic typing cadence.
Nyasa catches them through the combination: machine-speed micro-bursts that no human produces, combined with zero backspace rate and pixel-perfect clicks. Any one signal has false positives. All three together don't.
The multimodal rule catches the edge cases: sessions that pass fingerprinting and look almost human behaviorally but have soft contradictions across signals that don't fit either profile cleanly.
Live:
npm: npm install @devanshhq/nyasa
SOCIAL SHARE CARD GENERATOR