How Telltale works

View as Markdown

Telltale watches how a signed-in page is used and tells you whether a person or an AI agent did it, with how it knows, so your own application can decide what to allow. It runs the live classifier heuristic-v4.33.

For developers, the path is: browser SDK, then session token, then your authenticated backend, then verification, then your own authorization decision.

The session

  1. The hosted tag starts recording on page load. A site with a consent banner holds it (data-telltale-wait-for-consent, or waitForConsent: true), and then the SDK does nothing until your consent manager permits collection. Once collecting it opens a session with the Telltale server and observes coarse interaction and environment signals: pointer, keyboard timing, scrolling, focus, navigation and automation traces. It never records typed values, cookies, credentials or request-body values.
  2. The Telltale server keeps the evidence server-side and classifies the session as human, agent or unknown. Legacy scores (1, 99 and 50) are categorical labels, not probabilities. Separate weighted evidence groups correlated observations, keeps human support distinct and explains the result; it is not a calibrated probability. Unknown means the evidence is insufficient; it is not counted as human and never treated as human.
  3. client.identify() may attach user and account IDs from the page (browser-supplied). They label telemetry and are not verified.
  4. client.getSessionToken() returns an opaque, signed, expiring reference to the session. It contains no evidence, identity or verdict.
  5. Your backend sends that token with the server key to POST /api/v1/verify immediately before the protected action and receives the verdict, freshness, the optional agent name with how we know it (attribution) and the decision from the action's policy (allow, review or deny).
  6. Optionally, your backend calls POST /api/v1/identify to attach identity from your server (server-associated), derived from its own session.

Analytics and consequential decisions

What backs an AI agent verdict is its agentEvidence, and its confidence band follows from it (a strength level, never a probability). High confidence: Verified (a valid Web Bot Auth signature), an automation trace (webdriver flag, driver-defined trace or headless browser), input injected by software (keys with no hardware delay), sustained behaviour (enough consistent behaviour evidence on those pages, two independent signals agreeing) a behaviour change after a person (a handover), or several behaviour families (keyboard timing, pointer and clicks, text insertion) agreeing on one page when the session shows no physical-device input. Medium confidence: behaviour patterns alone, or several families when the session shows physical-device input. High confidence follows the action's AI agent rule, Deny included, and is chargeable. Medium confidence is held for review (step-up) by default, the site owner may switch it to block, and it is never charged. A session that has shown a person on a physical device is not turned into an AI agent by a brief odd moment, only by proof or a sustained change. Related pointer and timing observations count as one behavioural family, not several votes. See Verdicts for the table and its assistive-input limitations.

Human needs more than input that looks human. The page's behaviour stream must also show that the input came through a physical device: the few milliseconds between an event happening and the page seeing it, or pointer samples at a steady device rate. Without that the session stays Unknown. A site that turns the behaviour stream off (behaviourStream: false) therefore gets no Human verdicts. On Chromium-based browsers, input with essentially no delay at all (at least 10 recent key events, typical delay under 1 ms, a tenth of them with no delay at all; mouse presses and wheel steps are left out) was injected by software and reads AI agent at high confidence; on Safari, iOS browsers and Firefox it stays Unknown until checked with real people there. See Verdicts.

Who decides what

Browser probes

The SDK's probes send fixed labels only, never raw values: no user-agent strings, client-hint brands, renderer names, stacks, sizes or property names. Probes read property descriptors and call built-in methods captured when the SDK loads, so a page that later replaces a built-in is never invoked by a probe.

Ordinary people can trip some diagnostics: open DevTools (console serialization), user-agent or privacy extensions (worker, shared-worker and client-hint checks), and page libraries that patch document methods. That is why they are diagnostics, not verdicts.

Behaviour and environment diagnostics

These are recorded per session as labels, counts and rounded measures and shown with the other probe and input diagnostics. None of them changes a verdict, a score, a reason or the heuristic-v5 shadow rule: they are collected so their prevalence can be measured on test-set human trials before any is considered as evidence. Nothing here collects typed content, key identities or values.

Behaviour stream and the behaviour-v1 shadow model

After consent, the SDK also records a compact behaviour stream and sends it with its ordinary event uploads (one batch per upload, at most 16 KB, normally 1 to 2 KB). The Telltale server turns it into features and runs a separate rule set, behaviour-v1, in shadow: its result is stored with the session and shown under Technical as "Behaviour shadow model, not the verdict". The shadow model itself never changes the verdict, score, reasons, driver, attribution, policies, webhooks or what is chargeable, and there is no switch that promotes it; that needs a code change after a test-set evaluation shows no added human false positives. Since 2026-10-28 a few stricter cuts of its features reach the live verdict, only when clues from two or more different families agree in one page (timing, pointer and scrolling, page side effects, network); the Site setting "Behaviour signals can call AI agent" decides whether that makes the session read AI agent or only keeps it from reading Human. Verdicts lists the clues, the exclusions for people and the known risks. Unknown is never human.

What a batch contains, all as small integers:

What is never collected: key values or codes (which key or character), typed text, field values or their contents, clipboard contents, element names, selectors, attributes or page content, and nothing at all from password fields or from elements inside [data-telltale-ignore]. There are no identifiers: press numbers restart on every page. Under pressure the SDK thins pointer samples first, then drops the oldest rows, and counts what it dropped.

Withdrawal (optOut, a refused or withdrawn preference, reset) discards the pending batch, and a revoked session's raw batches are deleted on the Telltale server. behaviourStream: false in init turns the stream off.

Retention: raw batches are kept for the server's raw-behaviour window (default 7 days, never more; an operator can set it shorter) and at most 600 per session; features (rounded statistics, no samples) and the shadow result stay with the session and leave with it. Subject erasure deletes both.

Features: pointer strokes (straightness, speed variation, turning angle, acceleration changes, jerk), coalesced samples, press hold times, presses the pointer never travelled to, click offsets from the target centre, dispatch latency, key hold and gap times, overlapping keys, text inserted without key presses, paste, wheel and scroll cadence. Rules: a strong rule alone decides agent (pointer presses released within 5 ms; presses at points the pointer did not travel to; several characters inserted at once without keys, paste or composition). Supporting signals (exact-centre clicks, no dispatch delay, machine-regular key timing, straight constant-speed paths, identical wheel steps, script-dispatched input, scroll jumps without input, text without key presses) decide agent only in pairs. Human needs at least 30 trusted interactions, curved paths with varying speed reaching each press, human press and key timing, a hardware-like trait (coalesced samples, overlapping keys or varied dispatch delay) and no agent signal. (The live verdict borrows the dispatch-delay and steady-polling part of that trait as its Human requirement; the shadow model itself still never decides.) Everything else is unknown. Labelled evaluation snapshots keep the features, not the samples, and the evaluation report lists behaviour-v1 beside the live classifier and heuristic-v5.

The SDK sends the first batch straight after init, uploads early once 50 events are queued, and sends the three instant environment booleans with init itself, so a WebDriver-flagged or headless browser is answered by the init response using the existing rules; nothing from init is stored.

The session timeline

Every session's timeline begins with a started entry: type started, at, verdict (the verdict when the session opened, normally unknown), browser and os. The Telltale server derives browser (Chrome, Safari, Firefox, Edge or other) and os (macOS, Windows, Linux, iOS, Android or other) from the User-Agent header of the request that opened the session and keeps only those labels; the raw user agent is never stored. They are display labels, not evidence: a user agent can say anything, so they never affect a verdict or an attribution. The session view returns the entry in transitions and again as started.

The started entry is not a verdict change. Later entries are verdict_change (a classification change, with the attribution at that moment and, for a change to agent, the handover latency) or controller_change (attribution changed while the verdict stayed the same). The latest takeover, session.verdict_changed, session.identified (which needs a real verdict change first) and analytics count verdict changes only.

Which agents can be named

An agent is named only from a public signal, always with how we know the name: a Web Bot Auth signature from a reviewed operator directory (Verified, signed), a renamable page marker beside an agent verdict (Unconfirmed, weak-marker), a self-declared user-agent token beside an agent verdict (Self-reported, declared), or a crawler or fetcher verified against its operator's IP-range list or by forward-confirmed reverse DNS (Verified by network address, ip-verified). Google says Google-Agent is "used by agents hosted on Google infrastructure" and signs only a subset of its requests while the protocol is experimental; its directory uses short key IDs instead of JWK thumbprints, which this Telltale server accepts for that reviewed operator only. Google-Agent is named as Google publishes it, not as any particular Google product.

Signing operators

Every operator below names a platform or operator, never the user, the customer agent or the AI model. Keys are never built in: each directory is fetched when a signature arrives and cached for its Cache-Control max-age minus the response's Age (CDN copies arrive partly aged), never past the earliest key expiry still ahead. When a signature names a key that the cached copy lacks or shows as expired, the directory is refetched once, at most every 30 seconds, before the signature fails. Kernel, for example, republishes the same key with a sliding one-hour validity window, and ChatGPT's key expiry is always about seven days after each fetch. Documented says whether the operator itself ties the name to the directory.

Type follows Cloudflare's signed-agent field: Direct means only the operator acts through this identity; Intermediary means a platform that many customers' agents run on. A Verified name for a cloud browser platform (Intermediary) names the platform its customers' agents run on, not the customer agent. The attribution carries it as operatorType (direct or intermediary).

Signing operators
OperatorSignature-Agent originTypeDocumented
ChatGPT agenthttps://chatgpt.comDirectYes (OpenAI)
Google-Agenthttps://agent.bot.googDirectYes (Google; experimental)
Browserbasehttps://www.browserbase.comIntermediaryYes (Browserbase identity docs)
Anchor Browserhttps://api.anchorbrowser.ioIntermediaryYes (Anchor; per session, off by default)
Kernelhttps://www.kernel.sh (the bare kernel.sh redirects and is not accepted)IntermediaryYes (Kernel bots page)
Cloudflare Browser Runhttps://web-bot-auth.cloudflare-browser-rendering-085.workers.dev (Cloudflare may change this host)IntermediaryYes (Cloudflare Browser Run docs)
Manushttps://api.manus.imDirectNo: operator mapping undocumented, inferred from the domain. Manus's local Browser Operator does not sign
Hyperbrowserhttps://www.hyperbrowser.ai and https://api.hyperbrowser.ai (same directory)IntermediaryNo
Cursor-hosted agenthttps://cursorusercontent.comDirectNo: an Anysphere (Cursor) domain. Named by its domain only, not by which product or customer signed

Keys are found the way the Signature-Agent header says (draft-ietf-webbotauth-httpsig-protocol-00): type=directory (the default) reads the operator's well-known key directory; type=jwks_uri (a JWK Set URL) and type=cimd (an OAuth Client ID Metadata Document, whose client_id must equal its own URL and which carries jwks or one jwks_uri) are accepted only for a reviewed operator whose entry names that exact URL. Anything else is unreviewed-operator and is never fetched; a redirect or any status other than 200 is directory-unavailable. None of the operators above publishes such a URL yet.

Not listed: www.browserless.io (its directory has no keys), www.meta.com (Meta does not document what it signs for) and search.bot.kernel.sh (Kernel's search crawler, a separate identity). Amazon Bedrock AgentCore Browser is reviewed but not yet listed (2026-11-03): AWS documents that it signs with Web Bot Auth (preview, turned on per browser), but does not publish the Signature-Agent origin, so there is no key directory to check. A Cloudflare customer still sees it through Cloudflare's own signed-agent result (Edge evidence). Google-Agent was rechecked the same day against Google's page (updated 2026-10-13, still experimental) and its directory, and stays listed. Only tag="web-bot-auth" signatures are verified. Visa's Trusted Agent Protocol tags (agent-browser-auth, agent-payer-auth) are not accepted: TAP keys come from Visa's key store by key ID rather than a Signature-Agent directory, and TAP uses rsa-pss-sha256 with a required nonce and an 8-minute window, which this Telltale server does not yet implement.

Page markers

Claude in Chrome (active overlays only; since 2026-08-12 its side panel is Claude Cowork, so a sighting is shown as Claude in Chrome, possibly a Cowork session), Perplexity Comet, OpenClaw and the browser-use framework. Two more frameworks are named from their own source (names used as facts, notices in licenses/): Stagehand, from its opt-in cursor overlays and the style tag it injects while taking a screenshot (browserbase/stagehand, MIT), and agent-browser, from the attribute its snapshot sets on elements for a moment (vercel-labs/agent-browser, Apache-2.0). Both name a tool, never an operator or a model. Claude's idle static-UI buttons and its page-world helper globals are reported separately as diagnostics (tooling present, not control) and never name anyone, because no independent public source corroborates them; its residual animation style tag is reported apart as well. Two third-party observed heuristics from botscent (MIT) are also weak markers: ChatGPT for Chrome (a data-codex-favicon-badge attribute on an element in the page head, or in a favicon link's href; the badge can outlive the task) and the Codex in-app browser (at least two of three shell signs: a 29-character anonymous native window.prompt, an empty keyboard layout map in Chromium, and a top-level shadow-root overlay with an unrecognised id at the maximum z-index; one sign alone never names it). Neither is documented by OpenAI.

More frameworks are named from their own source (added 2026-10-28; names used as facts): Eko (framework) from its highlight container and highlight attribute (FellouAI/eko, MIT; named as the framework, never as the Fellou browser), Skyvern from the window property it sets by default (Skyvern-AI/skyvern; the name only), AgentQL from the element attribute its SDK stamps (agentql, MIT) and Magnitude from its injection flag (magnitudedev/browser-agent, Apache-2.0). agent-browser is also named from its annotation layer and recording cursor, and Stagehand from its mask attributes. The legacy browser-use highlighter that many forks still copy is named browser-use-derived DOM highlighter: it names a code lineage, not a product. Each names a tool, never an operator or a model, and only beside an agent verdict. Generic signs such as a nodriver pointer flash or a Playwright screenshot caret flash never name anyone.

Two joint rules from botscent (MIT, reimplemented) name Muse and Instinct as Unconfirmed third-party observations, beside an agent verdict only. The page sends only the combined outcome (match or no-match), never the parts, and a single part never names anything. Muse is never named from Meta's www.meta.com signing directory, whose purpose Meta does not document.

Runs from a cloud computer. When the verdict is already agent, the connection comes from a published data-centre range, and the browser shows two or more cloud-computer signs or a software renderer, the attribution also carries cloudRun ("Runs from a cloud computer", Unconfirmed). It describes where the agent runs; it never names an agent, a product or a model, and it is never verdict evidence.

Declared user agents

Some agents name themselves in their user agent. A declaration is a claim anyone can copy or remove, so it is attribution only: it never changes the verdict, never selects a usage category and never appears as a named usage row. It names the controller (strength declared) only beside an agent verdict; otherwise the session and verify responses carry it as declaredAgent, a labelled diagnostic. The user-agent string is never stored.

Declared user agents
TokenNamed asSourceSource strength
Agent-NovaAct/Amazon Nova Actaws/nova-act README ("look for NovaAct in the user agent string"); default suffix in its source (Apache-2.0), appended only when no custom user agent is setmedium: vendor-documented, but absent with a custom user agent
Cursor/<version> in an Electron user agentCursor in-app browsermeasured by a third party (botscent, Cursor 3.23.12): the in-app browser keeps Electron's default user agent; Anysphere documents nothinglow: names a browser surface inside the IDE, not which agent or model drives it

A GrokAgent/ token has been reported by a single press source; it is not used, because it is unconfirmed and its suffix is an account-derived identifier. Manus-User and Devin/ appear only in third-party lists and are not used.

These agents have no public signal (checked 2026-10-25; entries revised 2026-10-26 or added 2026-10-28 are marked in the API), so their sessions stay unnamed agents (unattributed-automation) when the evidence shows an agent. Each is reserved and will be added only when a first-party marker or signing directory can be verified.

Declared user agents, table 2
AgentFindingSources checked
Gemini SparkSince 2026-07-30 it can drive the user's own desktop Chrome; Google documents no signature, user-agent token or page marker for it, and gemini.google.com and www.google.com have no directory (404). Google-Agent is not said to be Spark (checked 2026-10-28)blog.google Gemini Spark update (July 2026); 9to5google (2026-07-30); support.google.com/gemini/answer/17094507; gemini.google.com and www.google.com directory paths
OpenAI DotsAlways-on agents with their own cloud machine and browser (DevDay, 2026-09-29); no documented signature, user-agent token or IP list; openai.com has no directory (404); chatgpt-agents.json is Codex cloud egress, not Dots (checked 2026-10-28)infoq.com DevDay 2026 report; androidheadlines.com (2026-09); developers.openai.com/api/docs/bots; developers.openai.com/api/docs/guides/ip-addresses; openai.com directory path
Gemini in ChromeNo directory on gemini.google.com (404); its overlay is a chrome:// WebUI page, not a page-visible marker; Google-Agent's directory does not name Geminigemini.google.com/.well-known/http-message-signatures-directory; developers.google.com/crawling/docs/crawlers-fetchers/web-bot-auth; chromium/src ce6c06cc chrome/browser/resources/actor_overlay
Microsoft Copilot (Copilot Mode in Edge)copilot.microsoft.com redirects to www.bing.com, which has no directory (404); no first-party marker or signing documentationcopilot.microsoft.com and www.bing.com directory paths
ChatGPT Atlas agent modeRetired 2026-08-09; no OpenAI document says it signed requestshelp.openai.com/en/articles/12628199; help.openai.com/en/articles/6825453-chatgpt-release-notes
OpenAI Codex coding agentNo documented signature or marker; no directory on openai.com (404). The Codex in-app browser and ChatGPT for Chrome now have third-party observed heuristics and are named separately as Unconfirmed (weak-marker) (revised 2026-10-26)developers.openai.com/codex/changelog; openai.com directory path; botscent page rules (commit 8c1fb53)
Cursor browser toolA web view inside the IDE; cursor.com answers the directory path with an HTML page, not a key directory. Its Cursor/<version> user-agent token is recorded only as the self-declared surface "Cursor in-app browser" (revised 2026-10-28)cursor.com/docs/agent/browser; cursor.com directory path; botscent page rules (commit 8c1fb53)
Grok (xAI)No directory on grok.com or x.ai (404); no first-party documentation. Only unconfirmed third-party reports exist, and none is used: a GrokAgent/ token from one press report, and a third-party catalog's mapping of the cursorusercontent.com signer, which is an Anysphere (Cursor) domain named only as a Cursor-hosted agent (revised 2026-10-26)grok.com and x.ai directory paths; runtimewire.com (2026-08-12); cursorusercontent.com directory path
Claude CoworkIn Chrome, Cowork runs through the Claude in Chrome extension, so it is shown only as "Claude in Chrome, possibly a Cowork session". Its built-in desktop browser documents no signature, user agent or marker; no directory on claude.ai or claude.com (404) (revised 2026-10-26)claude.com/blog/cowork-chrome-side-panel; claude.com/blog/cowork-built-in-browser; claude.ai and claude.com directory paths
Opera NeonNo documented signature, user-agent token or marker; no directory on opera.com, neon.opera.com or operaneon.com (checked 2026-10-26)those directory paths; 2025 launch press
Dia (The Browser Company)No documented agent identity, signature or marker; no directory on www.diabrowser.com (checked 2026-10-26)www.diabrowser.com directory path
Genspark AI BrowserRuns locally; no documented signature, user-agent token or marker; no directory on www.genspark.ai (checked 2026-10-26)www.genspark.ai directory path; genspark.ai/blog/genspark-ai-browser

Muse and Instinct left this table on 2026-10-28: the joint rules above now name them, Unconfirmed. Neither vendor documents a signature or marker, and instinct.ai has no directory (404).

Verified crawlers and fetchers

Some crawlers and user-triggered fetchers name themselves in their user agent and their operators publish the IP ranges they use. The Telltale server recognises these user agents and checks the request IP against the operator's own JSON list: CF-Connecting-IP when the request came through the public edge listener, the socket address otherwise (a CF-Connecting-IP header sent to the loopback listener is ignored).

Verified crawlers and fetchers
NameOperatorKindPublished list (fetched and checked 2026-10-25)
GPTBotOpenAIcrawlerhttps://openai.com/gptbot.json
OAI-SearchBotOpenAIcrawlerhttps://openai.com/searchbot.json
OAI-AdsBot (added 2026-10-28)OpenAIcrawler (checks the landing pages of ChatGPT ads)https://openai.com/adsbot.json
ChatGPT-UserOpenAIuser-triggered fetcherhttps://openai.com/chatgpt-user.json
ClaudeBot, Claude-SearchBot (added 2026-10-28), Claude-UserAnthropiccrawler, crawler, user-triggered fetcherhttps://claude.com/crawling/bots.json (one list for Anthropic's bots)
PerplexityBotPerplexitycrawlerhttps://www.perplexity.ai/perplexitybot.json
Perplexity-UserPerplexityuser-triggered fetcherhttps://www.perplexity.ai/perplexity-user.json (Perplexity's docs now cite www.perplexity.com, which redirects; the .ai URL is fetched because redirects are never followed)
GooglebotGooglecrawlerhttps://developers.google.com/static/crawling/ipranges/common-crawlers.json (the older googlebot.json URL now redirects there)
Google-AgentGoogleagent hosted on Google infrastructurehttps://developers.google.com/static/crawling/ipranges/user-triggered-agents.json
Google-GeminiNotebook (added 2026-10-28; the former Google-NotebookLM token also matches)Googleuser-triggered fetcherhttps://developers.google.com/static/crawling/ipranges/user-triggered-fetchers-google.json
BingbotMicrosoftcrawlerhttps://www.bing.com/toolbox/bingbot.json

OpenAI's bot documentation moved to developers.openai.com/api/docs/bots.

Network and timing diagnostics

The Telltale server derives a few labels and counts itself, at ingestion. They are stored on the session as networkSignals and timingSignals, appear in the session JSON and under Technical details as "Not used for the verdict", and never change a verdict, score, attribution or policy decision.

Connection origin. At SDK init and with each evidence batch, the client address the Telltale server already sees (the socket address; CF-Connecting-IP on the public edge listener; the TRUST_PROXY hop of X-Forwarded-For when TRUST_PROXY is set) is matched against published provider IP ranges. The session keeps only:

The IP address itself is never stored, logged, hashed or returned. Lists (checked October 26, 2026): AWS ip-ranges.amazonaws.com/ip-ranges.json, Google Cloud gstatic.com/ipranges/cloud.json, Oracle Cloud public_ip_ranges.json, the DigitalOcean and Akamai (Linode) geofeeds, Cloudflare ips-v4/ips-v6, the Tor Project's bulk exit list, and the agent egress lists published by OpenAI (ChatGPT-User), Anthropic, Perplexity (Perplexity-User) and Google (user-triggered agents). Azure, Hetzner, OVH, Vultr and Cloudflare WARP egress are not included: none publishes a stable machine-readable list. Since 2026-11-03 Apple's iCloud Private Relay egress list (mask-api.icloud.com/egress-ip-ranges.csv) is included as relay: real people use Private Relay heavily, so it is never labelled a data centre. When several lists match, an AI agent provider wins over a relay, a relay over Tor, and Tor over a data centre. A compact snapshot of every list but Tor ships with the server (refreshed with each release) and labels addresses from the first request until each live download is fresh; a snapshot entry is used for at most 60 days. Sources and terms: licenses/network-ranges.md.

Two service egress lists were added on 2026-10-28. Each names only the operator's egress for one service, never a product, an agent or a model:

Like the other agent-provider lists, a match keeps a person-looking session at Unknown ("not called human") and never makes it agent.

Lists download in the background at startup and are refreshed daily (Tor every six hours); a request never waits for or starts a download. A list older than three days (Tor: one day) is ignored. If any list is missing or stale, an address that matches nothing is unknown, never consumer-or-other. A data-centre, Tor or agent-provider label is not proof of automation: VPNs, corporate proxies and cloud desktops use these networks. The admin endpoint /api/admin/network-origin-lists shows each list's fetch time, version, prefix count and last error. Set TELLTALE_NETWORK_RANGES=off to disable fetching.

Transport. What the listener that received the request can actually measure:

The standalone network collector (npm run network:collector) still measures JA4, ALPN and HTTP/2 settings on its own TLS port for the lab page only; it is not joined to ordinary sessions.

Action-to-input timing. Where request capture is on, the SDK notes in page memory when the last trusted pointerdown or keydown happened (never the key, target or position). Each captured request shape and each WebMCP tool call start carries the whole milliseconds since then, or null when there was none. The Telltale server keeps only a count per bucket: under 300 ms, under 2 s, under 10 s, over 10 s, none.

Page rhythm. From the evidence events the SDK already sends (navigation, trusted click and keydown, on the page's own clock): time from page start to its first trusted input (under 1 s, 3 s, 10 s, 30 s, over 30 s, none), dwell per page (under 5 s, 30 s, 2 min, 10 min, over 10 min), the number of pages and navigation cadence in pages per minute (rounded to one decimal and bucketed: single page, under 1, 1 to 3, 3 to 10, over 10).

Cost: under 1 KB per session (about 440 bytes of origin and transport, 290 of timing counts and about 130 of open-page bookkeeping, up to 20 open pages), and one extra integer field on each request-shape and tool-call upload. Erasing a subject deletes their sessions and these fields with them.

Optional action discovery

When a workspace owner turns discovery on for a Site, the SDK also observes the structure of same-origin JSON requests: methods, path shapes, query and property names and types, media types and statuses. It does not keep values, cookies, authorization headers or raw responses. Structures become proposed agent tools and workflows that stay disabled until someone reviews and enables them. Approval is rechecked before every call, schema drift disables a tool, writes need confirmation, and your application's own backend authorization still applies to every request a tool makes.

Words we use

The dashboard, the demo and these guides use one plain word per idea. The API keeps its own names, shown here in code.

Words we use
In the dashboardAPI nameWhat it means
Human, AI agent, Unknownverdict: human, agent, unknownA category, not a probability. Unknown is not counted as human.
Agent nameattribution.controllerWhich agent product, when the evidence names one.
How we knowattribution.strengthHow the name was established. Always shown beside the name.
Verifiedsigned (or ip-verified for crawlers)The operator signed its requests, or the request came from an address the operator publishes. It names the operator, not the person or the AI model, and authorizes nothing.
Unconfirmedweak-markerNamed from something the agent's tool leaves on the page (a page marker). Anyone can rename or fake it.
Self-reporteddeclaredA browser agent named itself in its user agent. Anyone can send or remove it.
Declaredclient.name on MCP and API callsThe name an MCP or API client gives for itself (for example Claude Code). What the software says it is, never a verified identity.
Not named / Unnamed agentunattributed-automationAutomation is driving, but nothing reliable says which agent or AI product.
No recent activity, OutdatedstaleNothing arrived within the 60-second evidence window, or the newest activity is older than the policy's limit.
Technical notediagnosticA detail that never changes the verdict.
From your server / From the page (unconfirmed)server-associated (/v1/identify) / browser-supplied (identify())Who the session belongs to, and whether your backend or the page said so.
Activity minutesinteraction minutesMinutes in which a click, key, scroll or request arrived. Not elapsed, worked or chargeable time.
Mixed minutesmixedMinutes in which activity with more than one verdict arrived for the same account (for example Human and AI agent, or Human and Unknown). Counted once, apart from human, AI agent and unknown minutes.
Hold for review, held for reviewreview, held actionA person decides. Approving still needs your backend's own authorization.
Paused until consentwaitForConsent (held)Nothing is collected until your consent manager calls optIn().
Changed since approvaldriftA tool's request format changed since you approved it, so it is off until reviewed again.
Telltale servercollectorThe Telltale server your SDK and backend talk to (endpoint in configuration).

Where the pieces live

Continue with the Quickstart.