Tactical Gate — policy reference
What a policy is, what a rule can match and do, where it is enforced, and what Gate will never do.
Tactical Gate lets a store decide what AI agents are allowed to do. A policy is an ordered list of rules. Rules apply in order, the first match wins, and everything else is allowed. Every policy starts in Observe mode, where rules only tag what they would have done; a merchant turns enforcement on after watching for a few days.
Two things hold whatever a policy says: a visitor Tactical reads as a person, or isn't sure about, is never restricted, and search engines are never restricted unless a rule names one by id and carries an explicit SEO acknowledgement. Tactical's reading can be wrong (see Session reputation). See SEO safety.
Where it runs
| Enforcement point | Covers | Page requests | Add to cart | Checkout | Throttle scope |
|---|---|---|---|---|---|
| WooCommerce plugin (1.2.0+) | WooCommerce stores | yes | yes (validation) | yes (checkout process) | per site |
@tactical-app/agent-analytics/gate (Express) |
Node storefronts | yes | inferred from path | inferred from path | per process |
| Cloudflare Worker (Connect Cloudflare) | any store behind Cloudflare, incl. Shopify | yes | inferred from path | inferred from path | per Worker isolate |
| Shopify agentic channels (ChatGPT, Meta, Copilot, Google) | orders placed on the AI platform | no gating; Shopify's own product-level controls apply |
Each point fetches the store's compiled policy every five minutes with an ETag, evaluates every request in microseconds, and reports decisions in batches (allows are sampled). With no policy, a failed fetch, or any error, the request passes untouched.
A rule
{
"id": "drop-protect",
"name": "No agent checkout on limited drops",
"enabled": true,
"match": {
"categories": ["browsing_agent"],
"traffic_class": ["agent_browser"],
"min_tier": "high",
"scope": { "collections": ["limited-drops"], "actions": ["add_to_cart", "checkout"] },
"schedule": { "start": "2026-10-01T14:00:00Z", "end": "2026-10-01T18:00:00Z" }
},
"action": { "type": "block", "status": 403, "message": "Automated checkout is not permitted on this item." }
}
match
| Field | Values | Meaning |
|---|---|---|
agent_ids |
registry ids, or a search engine id | the agent, from its user agent or its verified signature |
categories |
training_crawler, search_indexer, user_fetcher, browsing_agent (and the reserved personal_agent, below) |
that agent's category |
verification |
any, verified, unverified |
whether the request carried a valid Web Bot Auth signature from the agent's own signer (see Verified agents) |
min_tier |
uncertain, likely, high, verified |
minimum confidence tier (see below) |
traffic_class |
human, agent_browser, crawler, uncertain |
behavioural class; a restrictive rule may not target human or uncertain |
scope.paths |
globs (* within a segment, ** across) |
request path |
scope.products / scope.collections |
handles or slugs | resolved to /products/<h>, /product/<h>, /collections/<h>, /product-category/<h> |
scope.actions |
page_view, add_to_cart, checkout, api |
what the request is doing |
schedule.start / schedule.end |
ISO 8601 | a window in which the rule is live |
An empty match matches everything.
Reserved for upcoming protocols
Four more match fields are reserved for agents that sign in under an identity protocol, such as the Personal Agent Protocol: protocol (any, pap, web_bot_auth, trusted_agent, none), session_kind (any, guest, signed_in), access (any, read, write: the access the customer granted the agent) and route (any, web, api, business_agent). Each defaults to any. They have no effect until the matching verifier ships: a rule that sets any of them to something other than any is accepted, but held back from every enforcement point, so it applies to nothing. One rule holds already: an allow rule with access: "write" must name pap, web_bot_auth or trusted_agent, so writes are never pre-authorised for an agent that hasn't identified itself. The category personal_agent is reserved the same way and has no registry entries yet.
action
| Type | Effect | Needs |
|---|---|---|
allow |
pass | |
tag_only |
pass, log with a tag | |
throttle |
over rpm requests per minute → 429 with Retry-After |
rpm 1–100000 |
identify_required |
403 with a JSON body that says how to identify | |
challenge |
an interstitial with a continue link; a cookie remembers it for an hour | |
redirect |
302 to url |
min_tier high/verified, or verification: verified |
block |
status (default 403) and message |
min_tier high/verified, or verification: verified |
Tiers
| Tier | Meaning |
|---|---|
verified |
a registry agent whose Web Bot Auth signature verified |
high |
behavioural confidence ≥ 0.85 |
likely |
0.6 – 0.85, or a declared but unverified agent |
uncertain |
everything else |
block and redirect only ever apply at high or verified, whatever the rule says.
Guards
In order, and they only ever soften a decision:
- Kill switch — every rule becomes
tag_onlyuntil released. - Observe mode — every rule becomes
tag_only; the intended action is logged. - Human or uncertain — a visitor with no declared identity whose class is
humanoruncertainis never restricted. - Search engine — never restricted unless the rule names it and acknowledges the SEO impact.
- Tier —
blockandredirectneedhighorverified.
Templates
Four ship, in this order: Observe only; Drop protection (block add-to-cart and checkout on chosen collections in a window, for agent browsers at high confidence); Assistant etiquette, called Amazon-style before 27 September 2026 (verified agents pass; an agent browser that hasn't identified itself must do so before checkout); Crawler diet (throttle training crawlers; indexers and user-triggered fetchers pass).
Verified agents
verified means the request carried a valid Web Bot Auth signature (HTTP Message Signatures, RFC 9421) from a signer listed for that agent in Tactical's registry. The agent names its key directory in the Signature-Agent header; the Gate fetches the public keys from /.well-known/http-message-signatures-directory on that origin and checks the signature. A valid signature makes the visitor that agent at the verified tier, even when its user agent looks like ordinary Chrome, so a rule with verification: verified (the Declared and verified agents are welcome rule in Assistant etiquette and Drop protection) applies to it. A user agent on its own is never enough: a declared agent without a valid signature is likely.
Who signs today:
| Agent | Registry id | Signer | Notes |
|---|---|---|---|
| ChatGPT agent (OpenAI; formerly Operator) | openai-operator |
https://chatgpt.com |
signs every request; its user agent is a stock Chrome one |
| Google-Agent | google-agent |
https://agent.bot.goog |
Google calls it experimental; only some requests are signed |
Cloudflare Browser Run also signs every request, but it isn't treated as verified: it's a hosted browser anyone with a Cloudflare account can drive, so its signature proves the browser is Cloudflare's, not whose agent is driving it. Anthropic and Perplexity publish no key directory, so their agents can't be verified yet.
What the Gate checks: the signature is tagged web-bot-auth, covers @authority (or @target-uri) and the Signature-Agent entry it names, was created no more than 60 seconds in the future and has not expired (60 seconds of clock skew either way), and is valid for at most 24 hours. Ed25519 signatures only, which is what every signer uses today. Replayed signatures aren't detected: a signature is proof of who signed it, not that the request is new.
An invalid signature (tampered, expired, made for another site, or not matching the key) never counts as verified, and nothing is blocked because of it: the Gate decides from the user agent and the session, exactly as for an unsigned request. A signature Tactical can't check (the directory is down or slow, the key or algorithm is unknown, or the signer isn't in the registry) is treated the same way.
Only requests that carry the Signature, Signature-Input and Signature-Agent headers are checked, and only for registry signers, so unsigned traffic costs nothing. A signer's directory is fetched without following redirects, with a one-second timeout, and cached for five minutes to an hour; a failed refresh keeps the keys already fetched (for up to a day). Verification runs on the WooCommerce plugin from 1.4.0, on Cloudflare Workers deployed after verification shipped (disconnect and reconnect an older connection to update its Worker) and on the demo store; the @tactical-app/agent-analytics middleware doesn't verify. Whether Cloudflare in front of a WooCommerce store passes the signature headers through to the plugin hasn't been tested.
Session reputation
At add-to-cart and checkout, for a visitor that names no agent or search engine, the Gate asks Tactical whether that visitor's session (the same IP and user agent) was classified as an agent browser in the last 30 minutes. If it was, the rules see class agent_browser with its tier: likely (60–85% sure) or high (85% or more). That's how Assistant etiquette reaches an agent that never names itself; Drop protection blocks, so it acts only at high. Human and uncertain verdicts are never shared, and page views are never looked up.
The lookup has a hard timeout; if it's slow or fails, the Gate decides without it. The visitor's IP address never leaves your server: the WooCommerce plugin and the Cloudflare Worker send only the Gate's 8-character one-way hash. It runs on the WooCommerce plugin from 1.3.0 and on Cloudflare connections made from 27 September 2026 (disconnect and reconnect an older one to update its Worker). The classifier can be wrong: a person it misreads as an agent could be asked to identify at checkout in Enforce mode. That's why every policy starts in Observe mode and shows what it would have done first, and why Enforce is open to design partners only during the beta.
Decisions
Every enforcement point reports what it decided: who, whether they were verified, class and tier, the rule, the intended and effective action, the guard if one applied, the path and the policy version. Non-allow decisions are always kept; allows are sampled 1 in 100. The Gate page shows the last seven days and replays the current policy over recent traffic before enforcement is turned on.
Safety net
If a store in Enforce mode blocks or redirects more than 20% of its decided requests in the last hour (with at least 20 of them), enforcement reverts to Observe automatically and the store owner is emailed. The check runs every time an enforcement point reports a block or redirect, so it acts within about a minute of the ceiling being crossed. Allowed requests are sampled 1 in 100 in the log, and the check weights them accordingly. The kill switch is one click on the Gate page.