@kyalabs/agent-radar
v1.0.0
Published
Lightweight AI agent detection for merchant storefronts. Behavioral signals, environment probes, and confidence scoring.
Downloads
29
Readme
@kyalabs/agent-radar
AI agent detection for merchant storefronts. Identifies automated visitors (GPT-4o, Claude, Gemini, Browser Use, Playwright, Puppeteer) through 21 behavioral, environment, and network signals. Three lines of code, zero Core Web Vitals impact.
Radar is the detection layer of the kya trust platform. It detects agents, issues temporary identity (guest passes), and feeds the kyaScore reputation system. Merchants see their agent traffic via the Radar dashboard or the stats API.
Install
npm install @kyalabs/agent-radarQuick Start
1. Client-side detection (React)
Wrap your app with RadarProvider. Detection starts automatically.
// layout.tsx or root.tsx
import { RadarProvider } from '@kyalabs/agent-radar/client';
export default function Layout({ children }) {
return (
<RadarProvider
merchantId="your-merchant-id"
apiKey="mk_live_your_key"
endpoint="https://yourdomain.com"
>
{children}
</RadarProvider>
);
}2. Read detection state
import { useRadar } from '@kyalabs/agent-radar/client';
function ProductPage() {
const { isAgent, agentType, confidence, guestPassId } = useRadar();
// isAgent: true if confidence >= 0.60
// agentType: "GPT-4o" | "Claude" | "unknown-automated" | null
// confidence: 0.0-1.0
// guestPassId: guest pass token if issued
}3. Server middleware
Add server-side detection for network signals (known agent IPs, UA patterns, header anomalies).
Express / Connect:
import { radarMiddleware, radarReportHandler } from '@kyalabs/agent-radar/server';
const config = {
merchantId: 'your-merchant-id',
apiKey: 'mk_live_your_key',
endpoint: 'https://yourdomain.com',
};
// Detection middleware — runs on every request
app.use(radarMiddleware(config));
// Signal report endpoint — receives client signals for the feedback loop
app.post('/kya/report', radarReportHandler(config));Next.js / Web API:
import { handleRadarRequest, handleRadarReport } from '@kyalabs/agent-radar/server';
const config = {
merchantId: 'your-merchant-id',
apiKey: 'mk_live_your_key',
endpoint: 'https://yourdomain.com',
};
// In middleware.ts
export async function middleware(request: NextRequest) {
const result = await handleRadarRequest(config, request);
// result.classification.classification → "high" | "probable" | "possible" | "unknown"
}Configuration
RadarConfig
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| merchantId | string | required | Your merchant ID from kyaLabs |
| apiKey | string | required | Publishable API key (mk_live_*) — safe for client-side |
| endpoint | string | "" | Backend URL for signal reporting (e.g., https://yourdomain.com) |
| apiBasePath | string | "/api" | Base path prefix for API routes. All internal requests use ${endpoint}${apiBasePath}/... |
| batchInterval | number | 5000 | Client signal batch interval (ms) |
| debug | boolean | false | Enable console.warn debug logging |
RadarMiddlewareConfig (extends RadarConfig)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| extraUaPatterns | Array<{pattern, agentType}> | [] | Additional UA regex patterns to match as agents |
| extraCidrRanges | Array<{provider, ranges}> | [] | Additional CIDR ranges to match as agent IPs |
| secureCookies | boolean | true | Set Secure flag on cookies. Set false for local HTTP dev. |
apiBasePath
By default, all API calls go to ${endpoint}/api/.... If your backend mounts kya routes at a different path:
// Routes at /v2/radar/detect, /v2/badge/guest-pass, etc.
<RadarProvider
merchantId="..."
apiKey="..."
endpoint="https://yourdomain.com"
apiBasePath="/v2"
/>Set to empty string if routes are at the domain root.
Detection Signals
21 signals across four layers:
Behavioral (B1-B8): Pointer absence, scroll depth, dwell time, click precision, WebDriver flags, automation artifacts, form fill speed, CTA blindness
Environment (P1-P5): Permissions API contradiction, SpeechSynthesis void, AudioContext hash, CSS preference void, hardware geometry anomaly
Shopping (B9-B11): Image engagement blindness, mouse teleportation, hyper-velocity carting
Network (N1-N5, server-side): Known agent UA patterns, known agent IP ranges (CIDR), JA4+ fingerprint, header anomalies, cooperative identity headers (Kya-Token, X-UCP-Agent-ID, X-TAP-Signature)
Execution budget: <15ms main thread for client signals. Server signals add zero latency (header inspection only).
How It Works
- Server middleware runs first — inspects headers, IP, UA for network signals (N1-N5)
- Client detection runs after page load — behavioral signals (B1-B11), environment probes (P1-P5)
- Feedback loop — client POSTs signals to server, server merges with cached network classification
- Guest pass — if merged confidence >= 0.60, a guest pass (
_kya_gpcookie) is issued automatically - Identity ladder — guest pass can upgrade to LiteBadge (agent opts in) then full Badge (user enrolls)
API Reference
Client exports (@kyalabs/agent-radar/client)
| Export | Description |
|--------|-------------|
| RadarProvider | React context provider. Starts detection on mount, cleans up on unmount. |
| useRadar() | Hook returning { isAgent, agentType, confidence, classification, guestPassId } |
| shouldNegotiate() | Check if LiteBadge negotiation should be offered to a returning agent |
| injectNegotiation() | Inject the LiteBadge DOM element and window.__kya_negotiation global |
| removeNegotiation() | Clean up LiteBadge DOM element |
Server exports (@kyalabs/agent-radar/server)
| Export | Description |
|--------|-------------|
| radarMiddleware(config) | Express/Connect middleware — runs N1-N5, classifies, issues guest passes |
| radarReportHandler(config) | Express handler for client signal reports (feedback loop) |
| handleRadarRequest(config, request) | Web API handler — same as middleware but for edge/serverless |
| handleRadarReport(config, request) | Web API handler for signal reports |
Shared exports (@kyalabs/agent-radar/shared)
Types (Classification, RadarConfig, SignalBag, SignalId, etc.) and the signal registry.
Privacy
Radar collects detection signals only. No PII is ever transmitted.
Collected: Behavioral signal results (boolean flags + timing), classification band, confidence score, page URLs, hashed IP (SHA-256), user-agent string, guest pass token.
Not collected: Names, emails, addresses, payment info, browsing history, cross-site tracking data, cookies beyond _kya_gp.
The _kya_gp cookie is a guest pass token — an opaque string that cannot be reversed to identify a person. It expires after 90 days.
See kyalabs.io/privacy for the full privacy policy.
Dashboard
View your agent traffic at radar.kyalabs.io or pull data programmatically:
curl -H "Authorization: Bearer mk_live_your_key" \
https://kyalabs.io/api/radar/stats?period=7dRequirements
- Node.js >= 20
- React >= 18 (optional — only needed for
RadarProvider/useRadar)
License
Proprietary. See LICENSE for terms.
