File DA-021 View as Markdown

Verdict

The verdict is what await doubleagent.ready() gives you: who is on the page (human, bot or AI agent), how sure Double Agent is, and what it suggests you do. This page explains each field, the da_* properties your tools receive, and which field to act on.

Nothing here is enforced. Double Agent labels the visit; your code decides what to do.

A verdict

{
  "sessionId": "k2f9x0a1b2c3d4e5f6g7",
  "class": "agent",
  "probability": { "human": 0.04, "bot": 0.03, "agent": 0.93 },
  "confidence": 0.81,
  "evidence": "sufficient",
  "agent": { "family": "openai", "id": "openai.chatgpt-agent", "operator": "openai", "controller": "playwright.automation", "verified": false, "method": "marker" },
  "reasons": [{ "code": "rhythm.think_then_act", "weight": 1.1 }],
  "scores": { "automation": 0.96, "environment": 0.42, "driving": 0.88 },
  "recommendation": "tag",
  "behavior": { "version": 1, "label": "neutral", "risk": 0, "source": "browser", "scope": "observation", "reasons": [] },
  "authorization": { "decision": "unknown" },
  "profile": "ecommerce",
  "action": "checkout",
  "stage": "provisional",
  "model": "doubleagent-2026.10.1",
  "ts": 1791000000000
}
FieldWhat it means
classhuman, bot or agent. The most likely of the three
probabilityThe chance of each class. They add up to 1
confidence0 to 1: how much evidence the verdict rests on. A low-confidence human means "no sign of automation yet", not "proven human"
evidenceinsufficient when there was a hint of automation but not enough to call it. Read it as "unverified"
agentWhich agent, when one is found: id (catalog id), operator (who runs it), controller (the automation tool driving the browser), family (a coarse label), verified and method (what proved it)
reasonsThe evidence, strongest first. Prefixes below
scoresSub-scores from 0 to 1. A clean environment with machine-driven input usually means an agent; a broken environment usually means a bot
recommendationallow, tag, challenge, step_up or deny, for this site profile and action. rate_limit is reserved: no profile returns it today
behavior, authorization, integrityHow the visitor behaved, whether your policy allows it, and whether the report can be trusted. See Conduct
profile, actionThe site profile and the action the verdict was made for, such as checkout
stageprovisional in the browser, final once the server has checked it
modelThe detection model version
judgeThe model that gave a second opinion, when the Handler ran. Absent today
tokenThe signed token, after check() or getToken(). Verify it on your server with @doubleagent-so/node

Families: claude, openai, perplexity, google, browser_use, browserbase, skyvern, manus, amazon, unknown.

agent.verified is true only when the server checked a Web Bot Auth signature from a known operator, or a published IP list. A user agent or a DOM marker in the browser is a claim, never proof. See Verified agents.

Which field to act on

  • To filter reports, use class.
  • To decide on a risky action (signup, login, checkout), use recommendation. It already weighs probability

against your site profile.

  • For anything that matters, call check() or getToken() and verify the token on your server. A browser verdict can

be faked by a visitor; a signed token cannot.

Reason prefixes

PrefixEvidence
auto. global. marker.Automation and agent-browser traces in the page
env.The browser environment does not add up
drive.How input is driven (synthetic events, remote control)
rhythm.Pauses that look like a language model thinking
bio. human.Pointer and typing patterns
edge. ua. net.Request headers and network, checked on the server
verified.Identity proven on the server. See Verified agents
evidence.Not enough evidence to call it
judge.The Handler, when it runs

The engine's full list of codes is in Agent Detector.

Conduct

Class says what the visitor is. Conduct says how it behaved and whether your rules allow it. They are separate: a verified agent can still break your rules, and a bot can be one you allow.

FieldValuesWhat sets it
behavior.labelfriendly, neutral, roguefriendly: a verified agent your policy allows for this action, with nothing suspicious. rogue: a rule it broke, such as a denied action, too many failed logins or a trap it touched. neutral: everything else
behavior.risk0 to 100How serious the worst finding is. A rule severity, not a probability
behavior.reasonsCodes such as policy.action_denied, abuse.repeated_auth_failure, identity.invalid_signatureWhat was found
authorization.decisionallowed, denied, unknownYour permission rules for this agent and action. allowed needs a verified identity
integritytrust 0 to 1, quarantined, reasonsWhether the browser's report looks genuine. Server verdicts only

In the browser, behavior is always neutral and authorization is unknown. The server fills them in, using what your backend reports through evaluate() and the rules you set in Sites › your site › Settings › Agent behaviour policy. In Monitor mode (the default) conduct is only a label. In Enforce mode a rogue or denied result changes recommendation to deny, and a friendly one changes it to allow. See The portal.

Properties and events

Every tool Double Agent sends to (GA4, GTM, Meta, Mixpanel and the rest) gets the same nine fields:

PropertyValues
da_classhuman, bot, agent
da_agentAgent family, or none
da_score0 to 100: the chance it is not human
da_bucket0-20, 20-50, 50-80, 80-100
da_recThe recommendation
da_verifiedtrue only when the server verified the agent
da_behaviorfriendly, neutral, rogue
da_behavior_risk0 to 100
da_authorizationallowed, denied, unknown

Events: da_classified once per session, when the first verdict lands. da_final once, when the Handler sends a final verdict. The Handler is off today, so da_final and doubleagent.on('final', fn) don't fire yet. A server check through check(), getToken() or a protected form updates the verdict and fires doubleagent.on('verdict', fn).

See Browser API.

Default policy

  • Every tool gets the da_* fields, as long as the visitor consented to that tool's category.
  • Ad conversions (Meta, TikTok, Google Ads) are held back when the class is bot with a bot probability of 0.8 or

more. Change it with block.adConversions: bot (default), bot+agent or none. See Meta Pixel.

  • Agents are tagged, never blocked.

Next: Browser API for check() and tokens, or Site profiles to see how the recommendation is picked.