Verdicts and authorization
A verdict says what the evidence shows about who is driving a browser session. It is input to your decision, never the decision itself. Your application authenticates the user, checks their account permissions and decides every protected action.
The live classifier is heuristic-v4.33. This page describes its rules; how they changed over time is in the Changelog at the end.
What each verdict means
| Verdict | Score (a fixed category code, not a probability) | What it means | What it does not mean |
|---|---|---|---|
| human | 1 | Recent input in one page fits human patterns: varied trusted input or sufficiently measured mouse navigation, with timing a person can produce (keys tens of milliseconds apart, the pointer moving before a mouse click), and no automation flag or active agent marker anywhere in the session. | Not proof of identity, and not a sign that the person may perform this action. A person can still be the wrong user, or be acting for an agent outside the browser. It is reported by the page, so it can be forged (see below). |
| agent (shown as "AI agent") | 99 | Recent evidence shows automation driving the page, or a valid Web Bot Auth signature from a reviewed operator. | Not a sign the agent is malicious or unwanted. Many agents act for a signed-in user who asked them to. It also does not say which AI model is driving: generic automation never establishes that. |
| unknown | 50 | The evidence is not enough to decide either way. Fresh sessions usually start here. | Not "probably human". Unknown is not counted as human: never counted, charged or treated as one. |
Scores are fixed labels for the three verdicts (1, 50 and 99). They are not probabilities: do not compare them with thresholds. Branch on verdict. An AI agent verdict also carries a confidence band (High or Medium, below), which is a strength level, not a probability either.
What backs an AI agent verdict: confidence bands
Every AI agent verdict carries agentEvidence, which says what backs it, and confidence, a strength band read from it. The bands are strength levels, never measured probabilities. The dashboard shows them as a chip, "AI agent · High confidence" or "AI agent · Medium confidence", with how we know.
| Confidence | What earns it (agentEvidence) | What it does at a protected action | Chargeable |
|---|---|---|---|
| High: Verified | Signed requests: a valid Web Bot Auth signature from a reviewed operator (verified) | Follows the action's AI agent rule, Deny included | Yes |
| High | An automation trace: the webdriver flag, a driver-defined trace, or a headless browser (automation-trace); input injected by software (injected-input); sustained behaviour (sustained-behaviour); a behaviour change after a person (behaviour-change); two or more independent behaviour families agreeing on one page, with no physical-device input on the session (behaviour-corroborated, "Strong evidence: several behaviour signals agree"); Claude in Chrome's cursor driving the clicks (cursor-driven, "Claude's cursor is driving the clicks") | Follows the AI agent rule, Deny included | Yes |
| Medium | Behaviour patterns alone: one behaviour family, or several when the session shows physical-device input (behaviour) | Held for review (step-up) by default, even when the AI agent rule says Deny. The site owner can switch it to follow the AI agent rule (block) | Never |
| Low | Reserved: nothing produces it today. A single weak signal stays Unknown, not AI agent | — | — |
| Unknown | Not enough to say | Your Unknown rule | Never |
| Human | Human-like input from a physical device | Your Human rule | Never |
Edge evidence your backend forwards (Cloudflare, Fingerprint) is not a level: it is recorded beside the verdict and may only raise a decision (see Evidence sources below).
Medium-confidence AI agent verdicts are held for review by default
By default, an AI agent verdict on behaviour patterns alone (medium confidence) is held for review (review, heldInsteadOfDeny: true) when the action's AI agent rule says Deny, so your backend can settle it with its own check, such as a passkey or MFA prompt, Turnstile or its own approval: see step-up. Allow and Hold for review rules apply as set. It is never charged.
The site owner may turn on Block medium-confidence AI agent verdicts (Control › Rules). They then follow the AI agent rule like any other AI agent verdict, Deny included. The warning, in plain words: real people who behave unusually (assistive technology, touch-screen kiosks, remote desktops) could be blocked from that action, though never from the rest of your site.
Only the workspace owner can change it; admins and viewers see it. Every change is audited. Verify responses, decision records and the protection.decision webhook say which applied to a medium-confidence verdict: behaviourOnlyDenyEnabled (false: held for review, the default; true: the AI agent rule applied in full) and behaviourOnlyReason, a plain sentence.
High confidence follows the AI agent rule whatever this setting says. The No recent activity rule still applies to old evidence, as it does to every verdict, and a WebMCP tool call keeps the AI agent rule in full because it is agent-initiated by definition.
Protected actions remember an earlier AI agent
If a session was confidently detected as an agent earlier (not an analytics-only observation: a reading the dashboard and reports count as AI agent but that does not, by itself, select the AI agent rule at a protected action), a later Human reading is treated as Unknown when a protected action is decided. Your policy's Unknown branch then applies, so a person who takes over from an agent is handled the way you chose for uncertain sessions, never silently allowed on the human branch. The session's own verdict and history are unchanged; this only affects protected-action decisions.
Weighted evidence, without a probability claim
weightedEvidence is attached to internal verdicts and session details. The legacy score remains the fixed category label above. The evidence strengths are not percentages, confidence, chargeable-use inputs or authorization thresholds. The main result remains Human, AI agent or Unknown.
Evidence is grouped into automation environment, automation behaviour and human interaction. Within each family, only the strongest eligible observation contributes: repeated events, multiple detectors describing the same pointer/click pattern and overlapping behavioural combinations cannot add points. Automation family strengths can sum up to 100, while human support remains a separate value. No amount of weak centred-click or regular-timing evidence can establish AI agent without a qualifying rule. Vendor markers have no positive weight.
Existing freshness, sample counts, paired-interaction checks, input exclusions and telemetry-completeness requirements run before a rule contributes. Validated behavioural combinations contribute 80 or 85; direct automation environment indicators contribute 90; a verified operator signature contributes 100. A supported human pattern contributes 85. The internal decision boundary is 80 with a qualifying evidence rule; these values are engineering choices, not fitted or calibrated probabilities. Human and behavioural automation support in conflict yields Unknown; direct environment evidence retains its existing precedence. Human-blocking evidence (such as a vendor marker or provider-origin cap) cannot become automation support merely by blocking Human.
The detail explanation records fixed signal codes, family winners and separate human and automation strengths. Current evidence and the last recorded observation are separate; expiry must not attach current weights to a historical verdict. Controlled detector histories preserve the bounded explanation and compare it during replay. Version 4.6 remains separately executable, so comparisons do not silently run the new model under an old name.
These weights improve traceability and prevent correlated votes from accumulating. They do not establish real-world accuracy. Synthetic fixtures check regressions, while genuine human, accessibility and unseen-controller trials remain required. Assistive software can produce the same browser-visible signals as automation; zero false positives cannot be guaranteed.
How we know the agent's name
When a session is agent, the evidence may name the agent (the API field is attribution.controller), always together with how we know the name (attribution.strength). The dashboard shows the two side by side, for example "Claude in Chrome · Unconfirmed" (Words we use lists every term). Naming an agent never changes the verdict.
How we know (strength) | Based on | How far to trust the name |
|---|---|---|
Verified (signed) | A valid Web Bot Auth signature from a reviewed operator directory | The operator is verified. The signature names the operator, not the user or the AI model, and authorizes nothing. A Verified name for a cloud browser platform (Intermediary) names the platform its customers' agents run on, not the customer agent. |
Unconfirmed (weak-marker) | Something the agent's tool leaves on the page, such as its overlay (a page marker), seen beside an agent verdict | A hint. Anyone can add or rename it, and overlays can outlive the agent's control. |
Self-reported (declared) | The client named itself in its user agent (for example Agent-NovaAct/), seen beside an agent verdict | A claim. Anyone can send or remove the token; it never changes the verdict or the usage category. |
Not named (unattributed-automation) | An agent verdict with no evidence naming the agent | Nothing is named. The dashboard shows these sessions as "Unnamed agent". |
A page marker beside a human or unknown verdict names nobody. It is listed in pageMarkers as a technical note (a diagnostic). A missing marker or signature never means a person is present.
What a verdict can and can't prove
- Human is reported by the page, so anything that can run script in the page can forge it. The SDK sends input events from the browser, and the server judges them. An agent, a browser extension or any script on your page can send made-up events with the session's token and get a human verdict. Treat Human as "nothing here looked automated", never as proof that a person is present.
- For sensitive writes, use
human: review. Exports, payments, invitations, account and billing changes should not be allowed on a Human verdict alone. Set the human branch of that action's policy to review (or deny and handle it in your app), and keep your own backend authorization and confirmation in front of every write. The default rule (for an action with no saved rule) allows human and unknown; change it per action. - Agent signs keep a session from being called human, but do not make it agent. An active agent marker (Claude in Chrome, Perplexity Comet, ChatGPT for Chrome, the Codex in-app browser, OpenClaw, browser-use, Stagehand or agent-browser) in any tab of the session, the SDK's agent-style UI flag, or a connection from a published AI-agent provider address range (OpenAI, Anthropic, Perplexity or Google user-triggered agents) holds the session at Unknown. None of them is agent evidence on its own: markers can be added or outlive the agent, and provider addresses are shared.
- Tabs are judged together, conservatively. One person working in tab A does not make the session Human while another tab of the same session shows an agent sign.
- A WebMCP tool call is an agent call. A tool started through
navigator.modelContextis decided on the stricter of the policy's agent branch and the current verdict's branch, and the execution is recorded as agent usage, whatever the session verdict says. The session verdict itself does not change. - AI agent recognises automation that leaves evidence. WebDriver, a headless browser, framework globals, a verified signature, exact-centre clicks at a machine-regular pace, or mouse clicks at the centre of controls with no pointer movement at all (below). An agent that hides these and paces itself like a person can read as Unknown, and can read as Human if it also forges person-like input.
- Mouse clicks at the exact centre with no pointer movement make a session read AI agent. When at least three trusted mouse clicks in the last minute each land within 2 px of the centre of the control they hit, and the session has had no pointer movement at all, no key presses and no keyboard, touch, pen or accessibility activations, the verdict is AI agent with the reason "Mouse clicks landed at the exact centre of controls with no pointer movement at all — a pattern of software driving the browser." A person with a mouse or trackpad moves the pointer to reach a control; software that sends clicks straight to a control's coordinates does not. The agent is not named (Not named) unless separate evidence names it, and no AI model is ever named from this. Scrolling with no wheel, touch or key input is mentioned when seen, but is not required. The rule needs the SDK's click input label, so clicks from older SDKs never count.
- Known risk of that rule. Some assistive technology can send a real mouse click at a control's centre without moving the pointer, for example a screen reader's "simulate mouse click" command, with no key press reaching the page. A person using it on a page where they only click (no typing) can be called AI agent. Keyboard activations, screen-reader default actions, touch, voice control that moves the pointer, dictation and password-manager autofill do not trigger it. If calling such a person an AI agent matters for an action, set that action's agent branch to review ("Hold for review") rather than deny, and keep the human path open through your own confirmation.
- Mouse clicks within a twentieth of a pixel of a control's exact centre, each after a single jump of the pointer, make a session read AI agent. Browser automation tools (Playwright, Puppeteer, browser-use, Stagehand, agent-browser and others) move the pointer once, straight onto the unrounded centre of a control, and press at once. When at least three trusted mouse clicks in one page in the last minute each land within 0.05 px of the centre of their control, that centre is between screen pixels, the pointer reached it in one jump of 20 px or more, and the press followed the jump within 2 ms or was released within 5 ms, the verdict is AI agent with the reason "Mouse clicks landed within a twentieth of a pixel of the exact centre of controls, each after a single jump of the pointer — a pattern of software driving the browser." A mouse, trackpad, head pointer or the pointer that voice control moves reports positions on the screen's pixel grid, so it cannot land there. Touch, pen, keyboard and accessibility activations never count. Older SDKs do not send these click details, so their clicks never count.
- Known risk of that rule. On macOS, an assistive tool that moves the pointer to the exact centre of a control between screen pixels and clicks within 2 ms has not been ruled out (we have not seen one). Set the agent branch of affected actions to review rather than deny.
- Capital letters typed without the Shift key make a session read AI agent. On a keyboard, a capital letter needs Shift or CapsLock, and the browser reports the letter that the keys produce. Automation tools that type into the page send capitals with no Shift (Playwright, Puppeteer), or report Shift with a lower-case letter and no Shift key press (browser-use). The page checks each letter key against its own key code, outside input-method composition, with CapsLock and AltGr off, and sends counts with the last three matching occurrence times: never the keys. When three matching occurrences are still within the evidence window in one page, and that page saw no input-method composition and no phone-keyboard key, the verdict is AI agent with the reason "Capital letters arrived without the Shift key (or Shift was reported without ever being pressed) — a pattern consistent with software typing into the page." Guards and regression fixtures cover CapsLock, Sticky Keys, non-US layouts, input methods, phone and on-screen keyboards; these are not a substitute for broad real-device validation.
- Known risk of that rule. A tool that posts upper-case characters with a letter's key code and no Shift (some text expanders on macOS) could reach the count; it needs the same letter's key code and three such capitals in one page.
- Typing with identical key holds and no gap between keys makes a session read AI agent.
type(text, {delay})in Playwright and Puppeteer holds every key for the same time and presses the next key the instant the previous one comes up. When the page sees eight or more printable keys in a row, each held at least 5 ms and within 1 ms of the first, each pressed less than 1 ms after the previous one was released, outside composition, the verdict is AI agent with the reason "Keys were typed with identical hold times and no gap at all between one key coming up and the next going down — a pattern consistent with software typing into the page." The regression fixtures cover fast, slow and one-finger typing, on-screen keyboards, switch scanning, dictation, autofill and paste. Real-device false-positive rates for these cohorts remain unmeasured. Separately, eight key presses in a row spaced within 2 ms of each other never count toward Human. - Known risk of that rule. An auto-type tool set to hold each key for a fixed time of 5 ms or more with no pause between keys would match. Tools that send keys in one batch (holds of about 0 ms) do not.
- An evidence upload that could not have come from the page itself keeps a session from being called human. Browsers label their own requests (Fetch Metadata). An upload that carries only part of that set, or a set that describes a page navigation rather than the page's own request, or a behaviour batch whose times run past its own page clock or whose page clock runs faster than real time, is not something a browser sends. The session then stays Unknown at best, with the reason "An evidence upload could not have come from the page itself (request headers or page clock impossible for a browser), so the session is not called human". It is never AI agent on this alone, and the upload is still accepted. Requests whose labels were removed on the way (some proxies and CDNs strip them) are not affected: missing labels are never treated as impossible.
- The agent is not named by these rules. Like every behaviour rule (and the behaviour combination below), they say software is driving the browser, not which. The agent is named only from separate evidence (a signature, a page marker, a self-declared token), and no AI model is ever named from them.
- Behaviour clues of two or more different kinds that agree make a session read AI agent. Each clue on its own is guesswork: a person can pause, react fast or scroll oddly. So the clues are grouped into four families, and only two or more clues from two or more different families, seen together in one page within the last minute, make the session read AI agent. A single family never decides, however many of its clues fire. The families and the clues that count (each with a deliberately high bar):
| Family | Clues that count toward AI agent |
|---|---|
| Timing | Long still pauses before clicks: three or more pauses of over 2 seconds, each ending in a mouse click, with no pointer movement, scrolling, selection or key press in between (at least 80% of such pauses). Reactions faster than a person reacts: three or more mouse presses under 50 ms after the page is shown or changes in-app, or key presses under 50 ms after a field was focused by script. Typing where at least half of the key gaps are under 1 ms (eight or more), with holds of 5 ms or more. |
| Pointer and scrolling | Straight, constant-speed pointer paths (three or more, two thirds of all) delivered in bursts rather than at a mouse's polling rate. Two or more controls scrolled to the middle of the view with no input and pressed within 100 ms. Two or more wheel scrolls at the top-left corner or the exact centre of the view, where the pointer never was. |
| Page side effects | Two or more screenshot-style text cursor flickers (cursors hidden on the fields and restored, as Playwright does while taking a screenshot). A debugging-bar-shaped slide of the page area (50–59 px in many small steps, window size unchanged, no focus or tab change) 10 seconds or more after the page opened, then a click within 5 seconds. Two or more fields focused by script (no click or Tab key) and filled with typed text within 50 ms, with no key press. |
| Network | Two or more requests your server verified in the last minute that the page itself never sent (needs request correlation, see Server API). An evidence upload a browser cannot make: a page clock running ahead of real time, or a complete set of browser request labels naming a navigation. |
Request absence needs complete, gap-free capture through the request window in every recently known page context. Missing coverage stays unknown. Late matching telemetry retracts an earlier absence, and repeated verification of one correlated request counts once. Older SDK batches without a capture-end timestamp can prove presence, but cannot prove absence.
The reason names the families and the clues in plain words, for example "Behaviour clues of 2 different kinds agree — timing: long still pauses before each click, with nothing moving; page side effects: a screenshot-style text cursor flicker — patterns of software driving the browser". The agent is shown as Not named, and no AI model is ever named from these clues. The verdict stays categorical; the detail explanation can show internal evidence strengths, explicitly not probabilities.
- People's patterns are left out. A page with touch or pen presses, or with input-method composition (Japanese, Chinese and other input methods, some dictation and phone keyboards), never counts any clue. Keyboard and screen-reader activations (two or more clicks with no pointer) leave out the timing clues. The clues are built so that voice control that moves the pointer onto a control (the move comes hundreds of milliseconds before the click), Mouse Keys (moves at the operating system's rate, not in bursts), remote desktop (bursty but curved), password managers and autofill (no input type), dictation (after a click), DevTools docking (one step after the window loses focus), operating-system window resizes (the window size changes), tab switches, and Chrome bars that slide in as a page first loads do not produce them. Every person case in the test suite, including a reader who rests the pointer on Next and clicks after long pauses, a power user with keyboard shortcuts, a DevTools user and a screen-reader user filling a long form, stays out.
- The site setting "Behaviour signals can call AI agent". Each Site has it (Control › Rules; API field
behaviourCallsAgent), on by default. Turned off, the same combination never makes a session read AI agent: it only keeps the session from being called Human, so it is capped at Unknown with the reason "…; this site has set behaviour clues not to call AI agent, so the session is not called human". Changes are audited and apply to evidence judged after the change (new uploads, within about a minute). See Server API. - Known risks of the behaviour combination. These clues are guesswork by design and have not yet been measured against labelled sessions of real people.
- A person who clicks with assistive technology that sends clicks without moving the pointer (a screen reader's simulated click, switch access item scanning) after long pauses meets the timing family. Two clues from other families are still needed, but if their page also does something below, they can be called AI agent.
- Network: a browser extension or the browser itself sending requests to your server with the page's session (prefetching, an extension calling your API) can count as "requests the page never sent". Beside the still-pauses clue that can call a reader an AI agent. Send request correlation only for actions people trigger from the page.
- Page side effects: a site that hides and restores the text cursor on all its fields twice within a minute (for example a theme switch), or a Chrome bar other than the debugging bar sliding in mid-page, looks like the screenshot flicker or the debugging bar.
- Timing: a voice-control or switch tool that moves the pointer and clicks within 5 ms after a long still pause is treated as a jump-then-click, like automation.
- If calling such a person an AI agent matters for an action, set that action's agent branch to review ("Hold for review") rather than deny, or turn the setting off so the combination only stops Human.
- Considered and left out of the live combination. In-app page changes with no click and long forms filled strictly in order stay shadow-only: the browser's Back button and app redirects change pages without page input, and screen-reader users fill forms in page order. Single large wheel steps (Windows "one screen at a time" scrolling), tab visibility flapping, full-page resizes and key-detail gaps also stay shadow-only.
- Trial rules (shadow) are listed under Technical. The behaviour stream model (behaviour-v2) and its technical notes (thinking pauses, too-fast reactions, pointer kinematics, typing gaps, screenshot cursor flicker, instant fills, scroll-to-centre clicks, wheel oddities, navigation and form order, a debugging-bar resize, upload header classes, and whether the page itself sent a request your server verified) stay recorded beside the session as the evaluation baseline. Only the stricter clues in the table above reach the verdict, and only through the two-family combination; behaviour-v2 itself never changes the verdict, score, name, policies, webhooks or what is chargeable. heuristic-v4.2 (the rules without the combination) is kept for evaluation comparisons.
The same ideas in other vendors' words
| Other vendors say | Here |
|---|---|
| Likelihood or probability | Not calibrated or claimed. Internal weighted evidence strengths explain the categorical verdict; they are not percentages. |
| Verified bot, signed agent | Verified (signed): a valid Web Bot Auth signature from a reviewed directory |
| Behavioural detection, biometrics | The live rules above (including the two-family combination), plus the shadow model under Technical |
| Headless or automation detection | AI agent from WebDriver, a headless browser or framework globals |
| Challenge, CAPTCHA | Not used. Hold for review (review) is the step-up |
| Likely automated, suspicious | Unknown: not enough evidence, never counted as human |
A verdict is never authorization
- Authenticate the user and check their permissions first, exactly as you would without Telltale. A human verdict never lets a user do something their account cannot.
- An agent verdict is not a reason to refuse work the user is entitled to. Decide per action: reading a report may be fine for agents, while exporting data, inviting teammates or changing billing may need review.
- Compare the identity returned by verify with the user your backend authenticated for the same request. If it names someone else, review or deny whatever the verdict.
- A verification failure (any error code) is not a verdict. Do not run the protected action, and never treat a failure as human.
Each action's policy maps human, agent, unknown and stale to allow, review or deny. verify returns the decision from that policy, and your backend applies it after its own checks. Riskier actions deserve stricter branches.
Unknown
Unknown gets its own policy branch. It never falls through to the human branch. A policy that allows unknown is saved only with an explicit acknowledgement (acknowledgeUnknownAllow), is audited and shows a warning in Control › Rules. For a sensitive action, send unknown to review, or deny it.
An action with no saved rule uses the default rule: Human: allow, AI agent: hold for review, Unknown: allow (until you save a rule that holds or denies it), No recent activity: deny. The default allows unknown because nobody has marked that action as sensitive; it is still the unknown branch, never the human one, and verify says the default decided (warnings: ["policy_missing"]). Save a rule for every sensitive action, with unknown set to review or deny. Write tools cannot run at all without a saved rule.
What your customer sees
Telltale answers your backend; it never shows anything to the person. Your app decides what a held or denied person sees, and a real person can be misread (someone using assistive technology, a kiosk, or someone who paused), so always give them a way through. Never tell the person they look like a bot or an AI agent.
Held for review (decision: review). Recommended message:
We need to confirm it's you before we finish this. Please confirm with your passkey or a code from your authenticator app.
Run a step-up check (a passkey, a two-step code, Turnstile or your own approval) and report the result with POST /api/v1/decisions/{decisionId}/step-up, or let the adapters do it with an onHold handler (Step-up for held actions, with Express and Next.js examples). A person who passes goes ahead at once. Without a step-up, the request waits in Control › Approvals › Waiting until one of your team approves it, for up to 15 minutes, and your app asks again.
Denied (decision: deny). Recommended message:
We couldn't complete this right now. If you think this is a mistake, contact our support team and we'll sort it out.
Point the person to a contact route or the same step-up check, and keep the rest of your site working for them: a denial covers one protected action, not the session. The rule editor in Control › Rules shows these messages, with a copy button, whenever a rule holds or denies.
Outdated activity (stale evidence)
Every policy has a maximum evidence age (maxAgeMs, 1 second to 5 minutes). When the latest evidence is older, verify returns stale: true, and the decision is the stricter of the stale branch and the current verdict's branch. Expired evidence can tighten a decision but never loosen it, so an agent that blocks the Telltale server cannot turn deny into allow. A policy with stale set to allow is saved only with acknowledgeStaleAllow and is audited.
Typing evidence uses the occurrence times of the supporting keys, not the time a heartbeat repeats a lifetime count. All three capital anomalies or all eight keys in a qualifying rhythm must still be within the evidence window. The recorder retains at most three timestamps for each capital anomaly and eight for the latest qualifying rhythm; keys, key codes and typed content are not sent. A new qualifying rhythm renews evidence even if it is shorter than a prior lifetime maximum. Older count-only summaries cannot prove recent typing; a fresh summary above a typing threshold with missing or invalid occurrence times caps the verdict at Unknown, with an explicit explanation, rather than claiming AI agent or Human. Valid expired occurrences allow subsequent human evidence to establish Human.
The current verdict also fades once its evidence leaves the 60-second evidence window, so a session nobody has touched for a while drifts back to unknown instead of keeping an old human verdict. A verified operator signature keeps a session agent until the signature expires or 10 minutes after it was last presented, whichever comes first.
The adviser model (analytics only)
Beside the verdict, the session detail shows a second opinion from an adviser model, for example "Adviser model: agent-like (first 30 seconds) · not used for decisions". It is a small machine-learning model trained on public research data, the FP-Agent dataset of people and AI browser agents doing web tasks, used with its authors' permission. It reads only timing shapes Telltale already collects in the first 30 seconds of a page: press holds, key holds and gaps, and scroll bursts. It never sees typed text.
The adviser only advises. It never changes the verdict, the action verdict, a protected action's decision, a policy, what is chargeable, the agent's name or a webhook that acts. You see it in the session detail and in label reports, so you can compare it with the verdict over time.
It says "no opinion" (Unknown) whenever it has too little to go on: fewer than two completed presses, key pairs or scrolls of one kind, a page shorter than its first time window, missing behaviour data, or values outside what it saw in training. On test-set research sessions it called no person an agent and no agent a person, but it gave no opinion on most of them, and research sessions are not your traffic. Its score is not a probability.
We also tested it on agents and tasks it had never seen: the model was retrained seven times, each time without one agent family, and three times without one task (the FP-Agent paper's holdout test). On unseen agents it still called no person an agent, but how many agents it noticed in the first 30 seconds varied widely: almost none for Atlas Agent (its fast scrolls and short presses lie outside anything the model had seen, so it says no opinion), about 1 in 5 for ChatGPT Agent and Manus, and about 8 in 10 for Browser Use and Claude. It also called a few unseen agents a person (4 of 794 ChatGPT Agent and 5 of 795 Claude sessions at 30 seconds). On an unseen task (Shopping) it called up to 5 of 48 people an agent in the first 2 seconds, and none at 10 and 30 seconds. So on agents or sites unlike its training data it can be wrong in both directions, which is why it stays an adviser. Exact counts are in models/fp-agent-early-xgb.meta.json under "holdouts".
Evidence sources and what each one can do
Each kind of evidence is kept separate, and each has a limit on what it can do to a protected action. Until test-set evaluations with real agents and assistive technology are published, only high confidence (a verified identity, an automation trace, injected input, sustained behaviour, a behaviour change, or several behaviour families agreeing without physical-device input) counts toward billing.
| Source | Where it comes from | Effect on the verdict | Most it can do to a protected action |
|---|---|---|---|
| Web Bot Auth signature checked by Telltale | Request headers your backend forwards in request, checked against the reviewed operator list | AI agent, named with strength signed (Verified) | Deny, per your AI agent rule |
| Strong automation traces | The browser SDK (for example automation-tool traces) | AI agent | Deny, per your AI agent rule |
| Injected input, sustained behaviour, behaviour change | The browser SDK: keys with no hardware delay (Chromium), and enough consistent behaviour evidence on those pages | AI agent, high confidence | Deny, per your AI agent rule; chargeable |
| Several behaviour families agreeing | The browser SDK: keyboard timing, pointer and clicks, text insertion on one page, no physical-device input on the session | AI agent, high confidence | Deny, per your AI agent rule; chargeable |
| Behaviour patterns alone | The browser SDK (timing and movement patterns) | AI agent, medium confidence, shown as "AI agent" in the dashboard and analytics | Review (step-up) by default; Deny only if the site blocks medium confidence; never charged |
| Page markers and self-declared user agents | The browser SDK, or a forwarded request | None on their own; they name an agent only beside an AI agent verdict | Nothing on their own |
| Cloudflare (customer's edge) | evidence.cloudflare on verify, server key only | None: recorded beside the verdict | Deny only for a Cloudflare-verified signed agent; review for a bot score below 30 or a verified bot; nothing for the rest |
| Fingerprint (customer's account) | evidence.fingerprint on verify, server key only | None: recorded beside the verdict | Review for bot bad or good; nothing for tampering, virtual machine and the other signals |
For the two edge sources the last column is a ceiling (mayLeadTo in edgeEvidence), and edge evidence only ever tightens a decision: it raises Allow to Hold for review (review), and raises to Deny only when mayLeadTo is deny. It never goes past the action's AI agent rule (it stands in for an AI agent reading, so a site whose AI agent rule allows agents is not overruled by its own edge), never lowers a decision and never changes the verdict, so it never makes Unknown human. When it changed the decision, appliedToDecision is true and raisedFrom names the decision before; a hold it caused offers step-up with reason edge_evidence. Edge evidence alone is never chargeable: what is chargeable follows the verdict, and edge evidence never makes one AI agent. It is stored with the decision for your own rules and for audit. A Cloudflare signed-agent result is Cloudflare's check, not Telltale's, so it never becomes a Verified attribution; forward the Web Bot Auth headers to have Telltale check the signature itself. No source, edge or browser, can make a session human on its own: a high Cloudflare score or Fingerprint's "not detected" is context only. See Edge evidence for the fields and the Cloudflare Worker.
Evidence coverage and historical explanations
Session details expose evidenceCoverage: accepted SDK events, rejected events, duplicate/out-of-order events and events removed from the retained buffer. Counts carry a scope: session-lifetime for newly tracked sessions, since-tracking-start for existing sessions that began tracking later, or retained-only when no counters exist. Missing historical totals are unknown, not zero. Oldest retained observation and known revoked/expired status help explain coverage; a sequence gap or silence alone does not establish packet loss or a broken SDK.
Meaningful detection history retains a bounded explanation and classifier basis independently of raw evidence. These historical explanations never extend current protection decisions or chargeable activity. Legacy numeric score fields remain for compatibility but are deprecated and uncalibrated; scoreSemantics states this explicitly. Use verdict, reasons and freshness rather than interpreting a score as a probability.
Confidence in the dashboard
Every AI agent verdict in the dashboard (Sessions, the session drawer, Approvals, Your agent report and the Ledger) reads AI agent · High confidence or AI agent · Medium confidence; press or hover the confidence for how we know it (signed requests, automation traces, injected input, sustained behaviour, a handover to software input, several behaviour signals agreeing or Claude's cursor driving the clicks for High; behaviour patterns, how it moved, clicked and typed, for Medium). A reading with neither confidence nor agentEvidence, such as one from before confidence was recorded, shows "Confidence unknown". These are levels, not measured probabilities: there are no percentages. Chargeable: High confidence. Never charged: Medium confidence. Sessions can be filtered by confidence (the Confidence menu, or confidence=high|medium|low|unknown on GET /api/admin/sessions, which also returns page.confidenceCounts; the earlier evidence= values still work), and sorting by Verdict orders agent sessions High first. The API values (agentEvidence, confidence) are unchanged.
Detection history and current control
Sessions preserve the last meaningful detection separately from the current verdict. An Unknown observation or a quiet period does not erase an earlier AI agent or Human detection. Older sessions use retained timeline evidence where available; missing history is not invented.
The session details distinguish recent evidence, no recent evidence, and an inconclusive current driver with a previous detection. “No recent evidence” may mean inactivity or missing telemetry; it does not prove that the browser is idle. Human patterns describe observed behavior, not proof of a person. AI agent includes generic automation and does not establish a specific AI model.
A supported Human result can supersede the last AI agent detection; a single ordinary-looking click is insufficient under the existing human-pattern rules. Historical detection is presentation context only: it never extends current protection evidence, grants authorization, or creates chargeable agent minutes.
Related
- Edge evidence: Cloudflare and Fingerprint as labelled sources.
- Server API and recovery: the verify response fields.
- Errors and retries: what to do when verification fails.
- How Telltale works: which signals are observed and which agents can be named.
Changelog
Earlier revisions of the rules, newest first. Each entry says what changed at the time; where an entry and the sections above disagree, the sections above are current.
Current revision: edge people read Unknown, never AI agent (heuristic-v4.33)
Heuristic-v4.33 (2026-11-04) moves two readings that could come from a real person from AI agent at medium confidence to Unknown. Nothing else changed: every other rule, threshold and band is exactly as in heuristic-v4.32 below.
- Remote browser isolation. Injected input that is the only sign of software, on pages whose input is otherwise shaped like a person's, from a published data-centre address (the conditions in the next section) now reads Unknown instead of medium. Your Unknown rule decides a protected action, nothing is chargeable, and the reasons say "a person may be driving it, so the session is not called AI agent".
- VoiceOver: activate and paste. On a page where every mouse press arrived with no pointer travel (VoiceOver's activate command, or the pointer following the VoiceOver cursor and resting before the press) and nothing was typed (at most two keys, such as Cmd+V), jump clicks are no longer AI agent evidence, alone or with a paste. Such a page reads Unknown, not Human and not AI agent.
- Proof is unchanged and stays high: an automation trace, a verified signature, an AI agent's cursor driving the clicks, sustained machine input, and injected input from any address that is not a data centre.
The cost: an AI agent built to look human that runs in a cloud browser and passes every shape check, or one that clicks without pointer travel and waits before each press, is now missed (Unknown) instead of medium. Missing an agent is acceptable; calling a person an AI agent is not. Numbers: accuracy report (opens the public report page).
Earlier revision: remote browser isolation (heuristic-v4.32)
Heuristic-v4.32 (2026-11-03) changed only the band of some injected-input verdicts. Remote browser isolation services (Cloudflare Browser Isolation, Menlo, Zscaler) and the "take over" live view of a cloud browser forward a real person's keys and pointer into a browser running in a data centre. That input reaches the page through the browser's software input path, so it arrives without the hardware delay a real mouse or keyboard has, exactly like an AI agent's injected input.
So injected input was held at medium confidence, never high (since heuristic-v4.33 it reads Unknown), when all of these hold: it is the only sign of software (no automation trace, no verified signature, no AI agent cursor, no agent page marker and no other behaviour signal, apart from the mouse hardware and a paste), the input is otherwise shaped like a person's (pointer travel before every mouse click, humanly possible and varied key timing, at least 10 keys or 3 such clicks), and the connection comes from a published data-centre address range. Under heuristic-v4.32, medium still showed as AI agent and was held for review; since heuristic-v4.33 the session reads Unknown. The reasons say why: "Input arrived without hardware delay, but everything else looks like a person and the connection comes from a cloud provider's address".
Injected input from any other address (a home or office network, a privacy relay, an unknown address, or an AI agent provider's own published range) stays high. The cost under heuristic-v4.32: an AI agent built to look human that runs in a cloud browser read medium instead of high (since heuristic-v4.33, Unknown). The frozen test-set results are unchanged, because no test set records the connection address (see the accuracy report (opens the public report page)).
Earlier revision: a person reaches Human sooner (heuristic-v4.31)
Heuristic-v4.31 (2026-11-03) changes only how quickly a person on a physical mouse and keyboard reads Human. No AI agent rule, threshold or confidence band changed, and the physical-device requirement for Human stays.
Strong device evidence. On a Chromium page (Chrome, Edge, Brave, Opera, Chrome on Android), the evidence is strong when the page's input shows both:
- a hardware delay: at least 10 delay samples from presses, keys and wheel steps, a typical (median) delay of at least 4 ms, and at most a fifth of them near zero; and
- merged pointer samples: at least 20 mouse moves that each carried two or more samples (a mouse polled faster than the screen redraws), making up at least 60% of all moves, with under 10% in bursts.
Software input does not show both. Input dispatched through Chrome's debugging protocol arrives with no delay, and a script that forges the delay still sends one pointer sample per move: on our tuning runs it merged 29-31% of moves, while real people merged 81-89%.
With strong device evidence, either of these is enough for Human (the other checks of the human rule still apply: trusted input, mouse clicks reached by real pointer movement, no impossible or metronomic typing, no machine-regular timing):
- 3 mouse clicks reached by real pointer travel, with press holds that look physical (none under 20 ms, and varied once there are three measured holds). No typing is needed. Before, a click-only task needed about 11 clicks.
- 5 key or click intervals instead of 10, so a few words of typing are enough.
Without strong device evidence (Safari, Firefox, an older SDK, or a mouse that rarely merges samples, such as on some high-refresh displays) the rule is unchanged: 20 interactions of three kinds, 10 key or click intervals and the device delay.
On the live demo session a person drove by hand (mouse and scroll, no typing), Human now arrives 5.3 s after the first input instead of 22.3 s. In the FP-Agent research recordings, replayed as if every page came from real hardware, people who reach Human go from 436 to 470 of 546 (125 to 135 of the 159 in the test split), those who end the visit as Human from 423 to 457 (120 to 130), and no agent reaches Human even when it is given the same device evidence.
Not added: Human from mouse movement alone. The device delay is measured on presses, keys and wheel steps, not on pointer moves, so movement alone cannot show it, and smoothed or replayed mouse paths are exactly what humanising scripts copy. A movement-only path is built but switched off until we have fresh recordings of real people and a delay measured on pointer moves.
"Looks like a person so far": a display state, not a verdict.
While the verdict is still Unknown, the live demo and the dashboard may show Looks like a person so far as soon as the page's first input shows real hardware: at least 3 delay samples with a typical delay of at least 4 ms, and mouse moves that carry merged samples. On the live demo session that happens about 2 s after the first input.
It is not a verdict. The verdict stays unknown (provisional: 'looks-human' and provisionalSince appear beside it on the session view and the demo's own answer only). Protected actions, your Unknown rule, chargeable use, the usage ledger, webhooks, counts and reports never read it. AI agent evidence replaces it at once, including a handover. The order a visitor sees is: Monitoring, Looks like a person so far, Human activity once the evidence above is met, or AI agent activity at any point.
Earlier revision: VoiceOver when the pointer follows its cursor (heuristic-v4.30.1)
Heuristic-v4.30.1 (2026-11-03) closes one gap for screen-reader users. VoiceOver can move the mouse pointer to each control it reads ("mouse pointer follows VoiceOver cursor"). Its clicks then come after one pointer move and a pause, with pressure 0, which looked like software to two families at once. Now, on a page where nothing was typed (at most two keys, such as a Cmd+V paste) and every mouse press came after at most one pointer move and at least 200 ms with the pointer still, pointer and clicks and the mouse hardware do not count toward "several behaviour signals agree", exactly like VoiceOver's activate clicks. Such a page could still read AI agent at medium confidence; since heuristic-v4.33 it reads Unknown. Quick software clicks (about 100 ms after the move) are not affected, and neither is Claude's cursor driving the clicks. On FP-Agent and the Claude in Chrome bench, no high reading was lost.
Earlier revision: the mouse hardware, and Claude's cursor (heuristic-v4.30)
Heuristic-v4.30 (2026-11-03) keeps everything in heuristic-v4.29 below and reads two new things the script tag reports about the mouse (counts and fixed labels only: no position, pressure value or key leaves the page). Both work only in Chromium-based browsers (Chrome, Edge, Brave, Arc, Opera); Safari and Firefox get neither yet.
The mouse hardware is a fourth family for "several behaviour signals agree" (behaviour-corroborated, how we know: "Strong evidence: several behaviour signals agree", with "mouse hardware" among the families in the reason). It holds on a page when both of these point to software:
- every mouse press reported a pressure of 0 (at least three presses). A real mouse in Chrome reports 0.5 while a button is down; software that sends clicks through Chrome's debugging protocol reports 0 unless it sets one;
- no mouse move carried more than one merged sample (at least three moves), in a browser that supports merged samples. A real mouse often delivers several samples per move; injected moves carry exactly one.
Neither alone is enough (a person's mouse on a fast display often sends one sample per move too). The family also needs the page's input timing to be present, so the physical-device exception can always be checked: without timing (an older SDK, the behaviour stream turned off) it never counts. It is a clue, never a rule on its own: it only raises an AI agent verdict that behaviour already made, the physical-device exception applies to it, and VoiceOver's clicks (which also report pressure 0) leave it exactly as they leave pointer and clicks. So pointer and clicks plus the mouse hardware, on a page with no hardware delay anywhere in the session, is high confidence. That is what an agent that only clicks (no typing, no paste) can now reach.
Claude's cursor driving the clicks is proof (agentEvidence: 'cursor-driven', high, how we know: "Claude's cursor is driving the clicks"). While Claude in Chrome's on-screen cursor is displayed, at least two mouse presses landed on it (within 8 px of its tip or centre), at two or more different spots, the cursor moved between presses, and every press on the page came with no pointer travel of its own. A leftover cursor that sits still can't produce this: someone clicking beside it never makes it move. It makes an AI agent verdict on its own, outranks the physical-device exception (Claude drives your visitor's own Chrome, where that person may have typed earlier), and switches a session that read Human, like other proof. The page marker names Claude in Chrome beside it, as before.
Not added: clicks after a long wait. Agents that teleport the pointer and wait 200-1500 ms before pressing look exactly like voice control and switch access, so that shape is not a rule. Such an agent stays Unknown unless its cursor or another signal gives it away. Missing an agent is acceptable; calling a person an AI agent is not.
Measured: FP-Agent and our own recordings of a person carry no mouse-hardware fields, so their numbers don't move; three Claude in Chrome bench kinds driven over Chrome's debugging protocol move from medium to high (quick clicks) and from Unknown to high (slow clicks with the cursor displayed), and stay Unknown with the cursor hidden. No real person has been recorded with the new fields yet.
Earlier revision: a person stays Human while they use the page (heuristic-v4.29)
Heuristic-v4.29 (2026-11-03) changes only how a person keeps a Human reading. Every AI agent rule, threshold and confidence band is exactly as in heuristic-v4.28.1.
- Human holds while you keep using the page. The human rule reads every interaction on the page in the last 60 seconds since the last pause, not only the last 80. Pointer and scroll events arrive several times a second, so under heuristic-v4.28.1 they pushed older clicks out of the 80 within 10 to 15 seconds of ordinary mouse use, and a person who was still moving and scrolling fell from Human to Unknown. On the real session that showed it (mouse and scroll, no typing), Human lasted 8 seconds under heuristic-v4.28.1 and holds until the person stops under heuristic-v4.29.
- Human resumes after a pause. A pause of more than 10 seconds, or switching to another tab and back, starts a fresh stretch of evidence. Before, a person needed about 11 more clicks (or some typing) to read Human again, so a protected action taken right after a pause was decided on your Unknown rule. Now Human carries over when all of this holds: the session read Human within the last 5 minutes; nothing was typed or clicked while the tab was hidden; the input since the pause passes the human rule's checks (trusted events, mouse clicks reached by real pointer movement, no machine typing); and that input has its own physical-device delay (at least two samples, a median of at least 2 ms, none under 0.2 ms). Software that takes over in the pause sends input with no hardware delay, so its first click does not resume Human: the session reads Unknown, or AI agent once its own evidence is enough. A controller marker, an automation trace or injected input works exactly as before.
- Unchanged: the first Human reading still needs varied input of several kinds (at least 10 key or click intervals) and the physical-device delay. Without the behaviour stream (an older SDK, or
behaviourStream: false) Human cannot resume after a pause.
Earlier revision: several behaviour signals agreeing (heuristic-v4.28.1)
Heuristic-v4.28.1 (2026-11-03) adds one way to reach high confidence. Detection itself is unchanged: the same sessions read AI agent, Unknown and Human as under heuristic-v4.28; only the band of some behaviour-backed AI agent verdicts moves from medium to high.
Two or more independent behaviour families agreeing on one page are high confidence (agentEvidence: 'behaviour-corroborated', shown as "Strong evidence: several behaviour signals agree"). A family is one kind of measurement; however many of its clues fire, it counts once:
| Family | Its clues |
|---|---|
| Keyboard timing | keys held for machine-short or machine-even times; machine typing (identical holds, no gap between keys); capitals without Shift; the behaviour stream's zero-gap typing |
| Pointer and clicks | jump clicks (every press on the page with no pointer travel), quick jump clicks (page or visit), clicks at the exact centre of controls, paired press-and-release dispatch |
| Text insertion | a paste on the page; fields focused and filled by script |
- Independent means different families: capitals and machine typing together are still one family (keyboard timing) and stay medium. Clues on two different pages are not two families agreeing.
- Nothing else counts toward a family: reaction times, pointer paths, wheels, page side effects and network facts do not.
- Screen-reader clicks do not count toward pointer and clicks: on a page where every mouse press arrived with no pointer movement at all and nothing was typed (at most two keys, such as a Cmd+V paste), which is how VoiceOver's activate command clicks, those clicks leave the family. Under heuristic-v4.28.1 to v4.32 they still made a medium-confidence AI agent verdict; since heuristic-v4.33 they make none (Unknown).
- The reading must already be AI agent from behaviour alone; this only says how strongly.
The physical-device exception. If the session shows physical-device input, the reading stays medium: the heuristic-v4.27 device trait (a real hardware delay) on any page of the session or on the page where the families agreed, or the same delay on as few as three samples (all input, or keys alone: a median of at least 2 ms and none under 0.2 ms). Remote desktop, VoiceOver users who type, touch-screen kiosks and barcode scanners go through the operating system's input path and keep that delay. Where device timing is unavailable (an older SDK, the behaviour stream turned off, a replay), two families are enough.
Human still holds against guesses. After a Human reading, several behaviour signals agreeing reads Unknown, not AI agent. Only proof (injected input, an automation trace, a verified signature) or a sustained behaviour change makes it AI agent.
Accepted risk. When the browser can't report hardware timing, several behaviour signals agreeing is treated as high confidence. That can include people using remote desktop, kiosks or scanners. Hardware timing is missing with an older SDK, when the behaviour stream is turned off (it is on by default), or when the session's evidence is out of date; with it, those people stay medium. No FP-Agent participant (546 people) showed two families. Numbers: accuracy report (opens the public report page).
Earlier revision: injected input, sustained behaviour and behaviour change
Heuristic-v4.28 (2026-11-03) adds three ways to reach high confidence, and makes a person's session harder to read as an agent.
Input injected by software is high confidence. Heuristic-v4.27 measured the delay between each press, key and wheel event's own timestamp and the page (below), and asked for a device-like delay before calling anyone Human. Read the other way, for keys: when at least 10 of the 20 most recent key events on a page have a typical (median) delay under 1 ms and at least a tenth of them arrive with no delay at all (under 0.2 ms), they were stamped as the browser received them, not by an operating system's input pipeline, so software injected them. The session reads AI agent with agentEvidence: 'injected-input' and the reason "Input arrived without hardware delay: injected by software", instead of v4.27's Unknown.
- Only keys count. Mouse presses are left out on purpose: a screen reader's or voice control's "click" is an accessibility action the browser creates itself, so it can arrive with no delay from a person. Wheel steps are left out because injected scrolling showed a delay of several milliseconds in our tuning runs. An agent that only clicks or scrolls is not caught by this rule; we accept that.
- It applies only on browser engines where the measurement is known to be reliable on real hardware: Chromium-based browsers (Chrome, Edge, Brave, Opera, Chrome on Android), which our recordings of real people cover. On Safari and every iOS browser (WebKit) and on Firefox (Gecko) such sessions stay Unknown until a check with real people in those browsers confirms it. The engine is read from the browser's User-Agent header as a fixed label (
chromium,webkit,geckoorother); the header itself is not stored. - The thresholds were chosen on development data only, with a wide margin from people (we would rather miss an agent than call a person one): the user's four confirmed human recordings have a typical delay of 7.6-8.9 ms over their presses and wheel steps and not one event under 0.2 ms; the adversarial tuning runs type with a delay of about 0.2 ms. Those recordings contain no typing, so the margin for real people's keys is still to be measured: the real-browser check asks people to type. Borderline input, a low delay with almost no zero-delay events, stays Unknown. People's recordings never read AI agent under the new rule.
- With Behaviour signals can call AI agent turned off, injected input only stops a session from being called Human.
Sustained behaviour is high confidence. A behaviour-based AI agent reading becomes sustained-behaviour as soon as enough evidence has accumulated, with no fixed time (elapsed time is reported, never a gate):
- Enough: at least 10 trusted input events since the last Human reading, on pages where input was injected by software. Only those pages count, so assistive technology, kiosks, remote desktop, barcode scanners and password managers, which go through the operating system's input pipeline or send no keys at all, never reach it.
- Consistent: no Human reading in between.
- Corroborated: at least two independent behaviour signals agree, for example injected input together with teleporting clicks or machine typing. Two rules that measure the same thing count once.
A brief odd moment is not a handover; a sustained change is. Once a session has read Human (a person on a physical device), a later reading backed only by behaviour patterns does not make it AI agent: it reads Unknown at most ("Human holds against guesses, not against proof"). Two things do switch it:
- Proof, at once: injected input, an automation trace or a verified signature.
- A sustained change (
agentEvidence: 'behaviour-change', "Behaviour changed"): sustained behaviour as above since the Human reading, with physical-device input seen to stop on the page. It is a handover, high confidence, and chargeable.
When physical-device input returns, new actions read Human again; the timeline keeps that an AI agent was driving earlier, and protected actions keep treating a later Human reading as Unknown, as before.
High confidence is chargeable from the moment it qualifies (earlier minutes are not charged afterwards) and follows the AI agent rule, Deny included. A verified signature still outranks every other level.
Previous revision: Human needs input from a physical device
Heuristic-v4.27 (2026-11-03) makes Human harder to earn. Input that merely passes the human pointer and key checks (curved mouse paths with real travel before each click, varied timing, human-length key holds) is no longer enough on its own: those checks describe what input looks like, and a script can copy that. Human now also needs positive evidence, from the same page, that the input came through a physical device:
- Input-pipeline delay. Each mouse press, key and wheel event carries the time it happened. Real devices are stamped by the operating system before the browser processes the event, so the page sees it a few milliseconds later. Input injected by automation (the Chrome DevTools Protocol that agents and test tools use) is stamped as the browser receives it and reaches the page almost at once. We need at least 10 such events on the page, a typical (median) delay of at least 2 ms, and no more than 5% of them under 0.2 ms.
- Or steady device polling: pointer samples arriving at a fixed device rate, with a typical delay of at least 1 ms.
Without either, the session stays Unknown, with the reason "Human-like input, but nothing showed it came from a physical device …". It is never called AI agent for this: a missing device trait is missing Human evidence, nothing more. In the live demo that reads "Can't confirm a person".
Why: the test-set adversarial bench in the accuracy report (opens the public report page) drove a stealth headless Chrome (normal user agent, webdriver hidden) with smoothed or replayed human mouse paths, a pause before each off-centre click and log-normal typing. Under heuristic-v4.26, 15 of its 20 test-set runs read Human, so a protected action would have treated them as a person. Under heuristic-v4.27, re-run on the same test-set seeds, all 20 read Unknown and none Human. They are still not caught as AI agent: this closes the door to Human, it does not detect them.
What it did to people, honestly: the user's own confirmed recordings still reach Human at the same moments as before (one person, one machine). In the FP-Agent research replay, which has no device timing at all, no session can reach Human any more: people who read Human there (317 of 546 sessions, 91 of 159 in the test split) now read Unknown, while agents are unchanged (7,025 of 7,182 AI agent, none Human) and no person reads AI agent. That replay figure is tuned on that data and says nothing about real visitors; the real shift for keyboard-only users, other browsers, touch and assistive technology is not measured yet. The rule was not chosen on any FP-Agent row. Full tables: accuracy report (opens the public report page).
What it costs, all toward Unknown, never toward Agent:
- The device trait comes from the SDK's behaviour stream. A site that turns it off (
behaviourStream: false) or runs an old SDK can no longer get Human verdicts. - Browsers or input methods that stamp events at dispatch, very short visits (fewer than 10 presses, keys and wheel steps on the page) and replays of recorded events (the FP-Agent research replay has no device timing) stay Unknown. More people will read Unknown than before. Unknown is not Human, and your Unknown rule decides what a protected action does.
- It raises the bar; it is not proof of a person. Automation that forges event times, or a page so busy that injected events queue, can show a delay too.
Agent detection, agentEvidence, and what an AI agent verdict may do were unchanged by v4.27. Heuristic-v4.28 (above) reads the same delay the other way on Chromium: no delay at all is injected input.
Earlier rule: only verified identity or an automation trace blocks or is chargeable (refined 2026-11-03 by the confidence bands above)
The confidence bands above refine this rule: high confidence (now also injected input, sustained behaviour and behaviour change) follows the AI agent rule and is chargeable; medium confidence is held for review by default and never charged.
Heuristic-v4.26 (2026-11-03) changes what an AI agent verdict may do, not how it is detected. Until test-set evaluations with real agents and with assistive-technology users are published, only two kinds of evidence may deny a protected action or count as chargeable:
- Verified identity: a valid Web Bot Auth signature from a reviewed operator.
- A strong automation trace: the browser's automation flag (webdriver), an automation framework or tool trace in the page, or a headless browser.
An AI agent verdict that rests on behaviour alone (how the pointer, clicks, keys and timing look, with neither of the above) still reads AI agent in the dashboard and agent in the API. But:
- Protected actions hold it instead of denying it. If the action's AI agent rule says Deny, the decision is Hold for review (
review) withheldInsteadOfDeny: true. Your backend can settle the hold with its own check, such as a passkey or MFA prompt, Turnstile, or its own approval: see step-up. Allow and Hold for review rules apply as set. The No recent activity rule still applies to old evidence, as it does to every verdict, and a WebMCP tool call keeps the AI agent rule in full because it is agent-initiated by definition. - Its time is shown, never charged. Its agent minutes and completed work are counted and shown, marked
billable: false(billableis shown as chargeable in the dashboard), and never metered, included or priced.
Every AI agent verdict carries agentEvidence, which says what backs it: verified, automation-trace, injected-input, sustained-behaviour, behaviour-change (since v4.28), behaviour-corroborated (since v4.28.1), cursor-driven (since v4.30) or behaviour. A medium-confidence verdict also lists the reason "Behaviour patterns (medium confidence): ...". Detection itself is the same as heuristic-v4.25.
This replaces the 2026-11-02 rule of heuristic-v4.24 below, which let behaviour-only verdicts deny and be charged. It also goes further than the "analytics only" revisions before that: every behaviour rule is covered now, not only the four newest. The setting Behaviour signals can call AI agent stays the off switch: turned off, behaviour alone never calls a session an agent at all.
Why: these behaviour rules were tuned on research recordings that contain no assistive-technology users. Someone whose voice control, switch or dwell clicker clicks like software must not be locked out of an action or charged as an agent on that basis.
Previous revision: quick teleporting clicks counted across the visit
Heuristic-v4.25 applies the quick-teleporting-clicks rule (below) to the whole visit as well as to each page. Some agents click only once or twice per page, so no single page ever had three clicks. Now the last 16 clicks of the visit are judged together. It only applies while the visitor is still active: the newest of those clicks must be on a page that is still sending activity. In the FP-Agent research recordings (tuned on this data, so not an accuracy estimate) this raises the total to 7,025 of 7,182 agent sessions, with none of 546 people flagged. Test-set results are in the accuracy report (opens the public report page).
Previous revision: everything we catch counts (replaced by heuristic-v4.26)
Heuristic-v4.24 removed the "analytics only" limit. The behaviour rules below (quick teleporting clicks, teleporting clicks with robotic key holds or a paste, and rapid paired mouse transitions) used to label a session AI agent activity in dashboards only. Now the same verdict is used everywhere: protected actions apply the site's AI agent rule, and the usage counts as chargeable agent usage.
A site that does not want behaviour alone to call a session an agent can turn off Behaviour signals can call AI agent in its settings. Behaviour then only stops a session from being called Human.
The risk this accepts: these rules were tuned on research recordings that contain no assistive-technology users. Someone whose voice control, switch or dwell clicker clicks like software would now be treated as an agent at protected actions, not just labelled in a report.
Previous revision: quick teleporting clicks label an agent on their own (analytics only)
Heuristic-v4.23 adds one more analytics label. A page is labelled AI agent activity when it has at least three mouse presses, the pointer never travelled to any of them, and the typical press came within 200 ms of the pointer appearing at that spot. Software clicks the moment the pointer lands; in the FP-Agent recordings agents pressed a median of 0 to about 106 ms after the pointer arrived. A press that lands somewhere the pointer never was (some tools press at a new spot without moving the pointer at all) counts as instant.
The 200 ms limit is what protects people using assistive pointers. Voice control moves the pointer and clicks only once the command has been recognised, and switch scanning and dwell clicking wait for a timer, so they press hundreds of milliseconds after the pointer stops. Those patterns are modelled in our tests and never get this label. We have not yet checked the limit against real recordings of voice control, grid clicking, switch access or dwell clicking.
In the FP-Agent research recordings (tuned on this data, so not an accuracy estimate), together with the rules below, this labels 6,928 of 7,182 agent sessions and none of 546 people. Like the two-clue rule, it appears in dashboards and reports only and is never used for blocking, protected actions or billing.
Previous revision: two robot clues on one page, counted across the whole page (analytics only)
Heuristic-v4.22 keeps the two-clue rule below and widens it in two ways:
- The whole page counts, not just the last minute. We keep the last 16 mouse presses on each page, each with how far the pointer moved in the 1.5 seconds before it. If there are at least three and the pointer never travelled to any of them, the page has jump clicks. Slow agents that click less than once a minute were previously missed.
- A paste can be the second clue. Jump clicks together with text pasted on the same page now label the session as an agent too. Some agents (ChatGPT Agent, Atlas, Comet) hold keys like people, but every one of their recorded sessions pasted text.
Each clue alone is still not enough. Voice control, switch access and dwell clicking jump the pointer, and many people paste. A paste never stops a session from being called Human. Like the rule below, this label appears in dashboards and reports only; it is never used for blocking, protected actions or billing.
In the FP-Agent research recordings (tuned on this data, so not an accuracy estimate), with both clues required on the same page, this labels 5,901 of 7,182 agent sessions and none of 546 people (14 people pasted, none on a page with jump clicks). The rule was chosen after looking at that data, and the recordings contain no assistive-technology users. An assistive-technology user who jump-clicks and also pastes on the same page would be labelled an agent in analytics, but never blocked or charged.
Previous revision: two robot clues together label an agent (analytics only)
Heuristic-v4.21 labels a session Agent for analytics when one page shows both of these: at least three mouse clicks in the last minute with no real pointer travel before any of them (the pointer jumped straight onto the spot), and machine-short or machine-even key holds (described below). Either clue alone is not enough, because voice control, switch access and eye-gaze dwell clicking also jump the pointer, and on-screen keyboards also hold keys for about 0 ms. This label appears in dashboards and reports; it is never used for blocking, protected actions or chargeable use, which still need certain evidence such as the browser's automation flag or a driver trace.
In the FP-Agent research recordings (tuned on this data, so not an accuracy estimate) this labels 2,670 of 7,182 agent sessions (Browser Use, Skyvern, Manus, Claude and Comet; not ChatGPT Agent or Atlas, whose key holds look human) and none of 546 people. The rule was chosen after looking at that data, and the recordings contain no assistive-technology users. Everything in heuristic-v4.20 is unchanged.
Previous revision: Human needs human key holds
Heuristic-v4.20 adds a second safety check before Human. When a page has at least eight key presses, we look at how long each key was held down (timings only, never which key). If the typical hold is under 25 ms, or every hold is almost exactly the same length (spread under 5% of the average), the session is not called Human and stays Unknown. It never calls anyone Agent: on-screen keyboards and auto-type tools also hold keys for about 0 ms.
Why: in the FP-Agent research recordings (tuned on this data, so not an accuracy estimate), none of the 445 people who typed at least eight keys on a page met either condition, while every Browser Use, Skyvern, Claude and Comet session that typed did, and most Manus sessions. ChatGPT Agent holds keys for a human-like length, so this check does not affect it; the mouse-travel check below still does. Thresholds were chosen after looking at that data. Everything in heuristic-v4.19 is unchanged.
Previous revision: automation tool traces count as proof
Heuristic-v4.19 treats traces that only an automation driver leaves in the page as strong evidence, like the browser's own automation flag: ChromeDriver's cdc_ names, Playwright's bindings and init scripts, Selenium's and older WebDriver hooks, PhantomJS and Nightmare. One of them is enough for AI agent, even when the automation flag has been switched off. Puppeteer's binding names and nodriver's click flash stay diagnostic, because a page or an extension can plausibly produce them. A trace names the framework only when the automation flag is also present, and it never names an AI model or vendor. Everything in heuristic-v4.18 below is unchanged.
Previous revision: Human needs real mouse travel
Heuristic-v4.18 makes Human harder to reach. When a stretch of activity includes mouse clicks, at least half of them (and at least one) must follow real pointer travel: three or more distinct mouse positions in the 1.5 seconds before the press, not a single jump onto the spot. If they don't, the session stays Unknown; this rule never calls anyone Agent. Keyboard, touch and click-free activity are unaffected.
Why: we replayed the public FP-Agent research dataset (seven commercial browser agents and 56 student participants on three tasks) through the detector. About 70,000 agent clicks; none followed real pointer travel, while 491 of 494 people who clicked did. Under heuristic-v4.17, 637 of 7,182 agent sessions were called Human at some point; under v4.18, none were, and people recognised as Human fell from 439 to 435 of 531. That replay lacks automation flags, element positions and some page measurements, it covers one website and desktop participants, and the rule was chosen after looking at that data, so treat these numbers as a check, not an accuracy figure. People who move the pointer with voice control, switch access or other assistive software may stay Unknown; Unknown is never treated as Human or Agent.
Previous revision: more sensitive analytics
Heuristic-v4.17 (kept unchanged in v4.18) retains the held-click pattern for analytics detection. Two trusted mouse presses can establish Agent when both jump directly onto different known controls, the controls are over 100 pixels apart, the next press starts within 200 ms of the previous release, and all four measured press/release delivery delays are positive. At least three must be below 1 ms; a single small scheduling outlier may be below 2 ms. Two delays at or above 1 ms, a delay at or above 2 ms, and missing or ambiguous zero timing do not qualify. The presses need not be unusually short. Complete telemetry, matching releases, stationary holds, a current visible segment and the existing keyboard, touch, pen and cancellation exclusions still apply.
The analytics rule can also use one matching dense pointer sample when the second move falls inside the normal stream’s 15 ms sampling interval. It requires the preceding sparse singleton and all the same pairing, completeness and transition checks. This reuses existing telemetry; it does not infer missing motion or add another evidence vote. Historical v4.14 and v4.15 remain replayable with their original limits.
The single-outlier allowance addresses recorded timing-sensitive misses. It is a bounded development heuristic, not a measured human/agent separation threshold. All four delays are retained in the evidence summary so the allowance can be audited; the strict protection and billing rule still requires every delay below 1 ms.
The same single-outlier allowance also applies to the existing short-press pattern for analytics: both matched holds must be positive and below 20 ms, with the original complete placement evidence and presses no more than ten seconds apart. Distinct known controls may occupy the same screen position after scrolling; otherwise an observed displacement over 20 pixels is required. This separate short pattern does not relax the held pattern’s rapid-transition requirements. Historical v4.16 remains replayable.
This is one combined behavioral signal. Its timing, placement and displacement do not earn separate votes; overlapping behavioral rules use the strongest family weight. A conflicting supported human pattern still produces Unknown unless independent strong automation evidence resolves it. No timeout forces a label.
The new pattern can resemble human-operated assistive software. When it is the only qualifying automation evidence, Agent is an analytics-only observation: it must not by itself trigger agent-based blocking or chargeable agent usage. Protected actions use the stricter action verdict and the customer's policy, including that policy's Unknown branch. This is not automatic permission to proceed. Existing stronger automation evidence remains eligible under the existing rules. The rich /api/v1/verify response exposes verdict, actionVerdict and analyticsOnly; its decision uses actionVerdict. The narrow compatibility /v1/verify response returns the strict action verdict. Updated server adapters validate the distinction; older adapters may reject differing branches and should be updated.
The result remains categorical, not a probability or proof of an AI vendor. Genuine human recordings and synthetic boundary tests are checked separately; neither a few passing recordings nor a constructed collision establishes a population false-positive rate.
Earlier rules retained from heuristic-v4.7. Rounded-centre pointer evidence requires repeated jumps between locations more than 20 CSS pixels apart, each landing within 1 CSS pixel of a control centre, with one non-coalesced move within 100 ms of the press. The timing clue is a matched mouse release under 20 ms. Agent requires either three jumps plus three short releases making up at least 75% of matched holds, or three jumps whose own matched releases are short. The latter binds both clues to the same interactions, so unrelated slower clicks do not erase positive evidence. A first press alone cannot establish a jump. These clues cannot borrow an unrelated signal to establish Agent. Keys, keyboard activations, untrusted buttons, touch, pen or composition exclude this pointer rule. Behavioural page combinations require a complete stream window: dropped samples or missing batch sequence numbers cannot establish an absence of human input. Gaps are counted only between retained batches of the same stream epoch, not before the start of the retained window. Independent direct automation evidence remains usable.
Corroborated element-labelling control. A separate pair recognises at least four single pointer jumps across at least three distinct landing positions, more than 20 CSS pixels apart, within 1 CSS pixel of interactive control centres. Each press must follow its one non-coalesced move within 250 ms and be within two seconds of a bulk element-labelling observation (the same nonstandard attribute changed on at least 25 elements in one observer batch). Common class, style, ARIA, form-state, Telltale and known password-manager/Grammarly attributes are excluded by collection. Ordinary travelled mouse paths, bulk DOM changes alone, pointer jumps alone, and stale inspection changes do not qualify. The same key, touch, pen, composition, untrusted-input and stream-loss exclusions apply. This independently combines pointer movement with page side effects; it does not rely on a named-agent marker or require very short holds.
The 250 ms arrival-to-press and two-second corroboration bounds are development-calibrated limits, not validated human/agent separation thresholds. They accommodate scheduling delays while keeping the observed page-labelling work close to the input. A person using assistive software that both bulk-labels elements and warps/clicks controls with this pattern can still be classified as automation. Real accessibility trials remain required; use review rather than automatic denial where that ambiguity matters. This does not identify an AI vendor or establish a calibrated probability. Versions 4.5 and 4.6 remain available for historical comparison.
Mouse-only navigation can now establish Human from repeated measured approaches, off-centre targeting, varied holds and varied click cadence, with no automation cap. It still needs at least 20 input events and ten click intervals; at least eight clicks and 75% of eligible clicks must have three or more approach moves, no jump, an offset over 2 pixels and a hold of at least 20 ms. Hold variation must reach 0.15 and within-kind cadence variation exceed 0.35 (coefficient of variation). Mixed input also needs variation within an input kind; two constant rates cannot manufacture human variation by pooling. Keyboard-only recognition remains limited; absence of a mouse is never Agent evidence.
These are heuristic thresholds, not an accuracy guarantee. Assistive software that synthesizes the same centred jumps and short mouse clicks without keyboard events can still look identical. Synthetic negative cases are regression checks, not real-human validation. Detection requires enough activity within the 60-second window; it is not forced by a timeout, and historical labels do not add agent minutes.
Fixes from the detector audit (heuristic-v4.28)
- Only trusted events switch the centre-click rule off, so a single fake page event no longer hides it.
- Automation globals a page or extension could define (the framework flag, PhantomJS, Nightmare, Selenium and DOM-automation globals) count as an automation trace only together with the webdriver flag; alone they only stop a session from being called Human. Driver-defined traces (Playwright's binding, ChromeDriver's names) stay strong.
- Requests the page never sent are review evidence only: they are no longer one of the behaviour families an AI agent verdict needs.