Trusted Agent Protocol · Cloudflare Workers

Tell a real agent
from a scraper.

AI agents like ChatGPT and Perplexity are starting to browse and buy on real merchant sites on behalf of real users. Before you can let them, you need to tell a legitimate agent apart from a scraper — cryptographically, at the edge, on every request.

That's the merchant's one job in the Trusted Agent Protocol. TAPKit makes it one import.

TAP was co-developed by Cloudflare and Visa. TAPKit is the canonical Cloudflare-native implementation.

worker.ts
import { verifyTap } from "@mconroy-cf/tapkit-workers";

export default {
  async fetch(request, env) {
    const result = await verifyTap(request, {
      tag: "agent-payer-auth",
      nonceStore: env.NONCE_STORE,
    });
    if (!result.ok) return result.toResponse();

    // Signature verified. Body is in result.rawBody.
    const order = JSON.parse(result.rawBody);
    return Response.json({ status: "approved", order });
  }
};

What a merchant actually has to do.

Agentic commerce has a lot of moving parts — agent platforms, user passkeys, payment tokenisation, network controls. Almost none of them are the merchant's problem.

You don't build the agent.

That's Visa, OpenAI, Perplexity and others. You don't handle user passkeys, tokenisation, or network controls. Those are all upstream of you.

You don't enrol the user.

Card-on-file, payment tokens, consumer identity — all handled before the agent ever hits your site.

You do verify the signature.

Every agent request to your Worker carries an RFC 9421 HTTP Message Signature. You verify it against the scheme's agent registry and check the intent tag. Valid → let it through. Invalid → reject like any other bad bot.

That's it. Really.

One verification call, two variants (browsing and payer), correct failure handling. Everything else in agentic commerce is somebody else's problem.

The work TAPKit is doing for you.

That one verification step sounds small. Here's what it actually contains — and what you'd otherwise have to build yourself.

  • RFC 9421 + structured-fields parsing

    Signature-Input and Signature headers, covered-field inner lists, structured-field parameters like "query-param";name="agent-id". Get the parser wrong and you open a cross-merchant signature replay.

  • Both signing algorithms

    Ed25519 and RSA-PSS-SHA256. The spec leaves PSS salt length ambiguous — JOSE says 32, Visa's reference implementation uses MAX_LENGTH. TAPKit tries both. Catching that ambiguity cost us half a day.

  • Byte-exact signature-base reconstruction

    @authority, @path (which confusingly includes the query string despite strict RFC 9421 saying otherwise), query-param components resolved from the URL. One character off and the crypto fails with no useful hint.

  • Nonce replay protection at Cloudflare scale

    KV-backed, cross-colo, with the right check-early/write-late timing so a malformed request can't race and consume a legitimate request's nonce.

  • Tag enforcement

    agent-browser-auth on browsing routes, agent-payer-auth on checkout — the spec splits them for a reason, and mixing them is a subtle auth bypass.

  • Bidirectional interop with Visa

    We run Visa's own tap-agent against TAPKit and TAPKit's signer against Visa's reference verifier. If your signatures don't round-trip against their reference, merchants won't accept real agent traffic. Full test matrix in the repo.

  • Everything a first implementation gets wrong

    Covered-field uniqueness, duplicate-param smuggling, whitespace preservation in signature bases, wrong-tag routing, nonce timing races. TAPKit has tests for each.

Three things, one repo.

TAPKit ships the three pieces a merchant actually needs to go from "I've read the TAP spec" to "we're accepting agent traffic in production."

01

@mconroy-cf/tapkit-workers

Drop-in middleware

One import, one function call. Verifies the TAP v1 Agent Recognition Signature on incoming requests: RFC 9421 parsing, freshness window, nonce replay protection, JWKS discovery, Ed25519 and RSA-PSS verification. Returns a discriminated result with a toResponse() helper.

02

@mconroy-cf/tapkit-cli

Signing test agent + conformance runner

npx @mconroy-cf/tapkit-cli sign <merchant-url> generates a TAP-compliant signed request against your staging site. npx @mconroy-cf/tapkit-cli check <merchant-url> runs a 13-scenario conformance suite — valid, replay, expired, window-too-large, wrong-tag, missing-signature, unknown-keyid, CRO and APC variants — and reports pass/fail per scenario.

03

Reference merchant

Live, deployable, cloneable

A minimal Cloudflare Worker showing exactly what correct TAP verification looks like, running against real Ed25519 keys and real JWKS discovery (including Visa's production endpoint). Use it as a verified baseline when integrating into your own stack — it's the same verifier the middleware ships.

See it run.

Run the TAPKit conformance suite live against our reference merchant — or point it at your own staging URL to see how close you are to spec.

tapkit check
Click "Run check" above to stream live results.

Quick start

Two steps, about five minutes. Assumes a Cloudflare Worker you already have shipping on wrangler deploy.

1. Install the middleware

shell
npm install @mconroy-cf/tapkit-workers

2. Bind a KV namespace for replay protection

Create the KV namespace and bind it as NONCE_STORE:

wrangler.jsonc
{
  "kv_namespaces": [
    { "binding": "NONCE_STORE", "id": "<your-kv-id>" }
  ]
}

3. Verify incoming requests

worker.ts
import { verifyTap, TAP_TAGS } from "@mconroy-cf/tapkit-workers";

export default {
  async fetch(request, env) {
    if (new URL(request.url).pathname === "/checkout") {
      const result = await verifyTap(request, {
        tag: TAP_TAGS.PAYER,
        nonceStore: env.NONCE_STORE,
      });
      if (!result.ok) return result.toResponse();

      const order = JSON.parse(result.rawBody);
      // ...process the verified order...
      return Response.json({ status: "approved", order });
    }
    return new Response("Not found", { status: 404 });
  }
};

4. Confirm with the conformance suite

Deploy, then run the suite against your URL. You want 13 / 13:

shell
npx @mconroy-cf/tapkit-cli check https://your-merchant.example.com

Frequently asked

Is this a Cloudflare product?

Not yet. TAPKit is open-source and MIT-licensed, built as part of Cloudflare's agentic commerce work. The @mconroy-cf/tapkit-workers package is designed to run on any Cloudflare Worker but doesn't require a Cloudflare account or paid plan to use. The current scope is a partner-feedback release; an official @cloudflare/-scoped package will follow.

What is the Trusted Agent Protocol?

TAP is an open, Visa-led standard for AI agents to cryptographically prove their identity and intent to merchants. It's built on HTTP Message Signatures (RFC 9421), Ed25519, JWKS for key discovery, and nonce + timestamp freshness. TAPKit implements all three TAP v1 layers: Agent Recognition Signature, Consumer Recognition Object, and Agentic Payment Container. Read the spec ↗

What about AP2 or Mastercard Agent Pay?

TAPKit's architecture is protocol-pluggable — adapters live in packages/cli/src/protocols/<name>. We'll land AP2 and Mastercard Agent Pay adapters when those specs are merchant-ready. Until then, TAP is the one with a published spec and live pilot deployments.

Do I need Visa-issued keys to get started?

No. TAPKit ships with a test keypair so you can verify your integration end-to-end without any external dependency. For production you'd trust Visa's JWKS (the default) or your issuer's equivalent.

How do I get real TAP credentials?

Through Visa's payment scheme onboarding. TAPKit exists precisely so you can do everything else in parallel — build and verify your integration before credentials land so the critical path isn't waiting on NDA.

Is the package on npm?

Yes — @mconroy-cf/tapkit-workers and @mconroy-cf/tapkit-cli are both live on npm as partner-feedback releases. Once the official @cloudflare/ scope ships, both packages will deprecate and point at the canonical names.

Ship TAP support this week.

Clone the repo. Run the conformance suite against your staging site. Open an issue if you hit something weird.