> ## Content Index
> Fetch the complete content index at: https://newsroom.botshield.ai/llms.txt
> Use this file to discover other available public pages before exploring further.

# Technical Series, Part 1: An agent buys the ticket — with a verified human's permission
- URL: https://newsroom.botshield.ai/technical-series-part-1-claude-ticketz-agents-ask/
- Published: 2026-09-17T16:34:05.000Z
- Updated: 2026-10-05T21:15:59.000Z
- Description: Part 1 of the BotShield Technical Series: how the Ticketz demo wires Claude, an MCP connector, Link an Agent and Agents Ask so a purchase cannot complete until a verified human confirms it on their phone. No password, email or name crosses to the agent.
- Author: Paul Payne
- Tags: Technical Series

**Technical Series, part 1.** Each post in this series takes one integration surface and shows exactly what happens on the wire. Part 1 is Claude via an MCP connector. Salesforce Agentforce and others follow.

*Here is the magic: the bot does the buying, but every ticket is purchased by — and belongs to — a verified, real human. The agent acts; a proven person stands behind the purchase, and it cannot complete until they confirm it on their phone. No password, no email, no name crosses to the agent.*

*This is a walkthrough of the Ticketz demo, wired end to end. The open beta opens the day the app lands on the App Store and Google Play — because we hold no data about you, there is no shadow dataset to test against, so the only honest way to harden a personhood layer is to run it live.*

## What the demo does

The stakes here are small on purpose — a ticket. Watch the guarantee, not the purchase: the same rule holds whether an agent is buying a seat or moving money. Ticketz is a fictional ticket seller with an MCP server. Add it to Claude as a connector, ask for what is on sale, and ask it to buy a seat. The listing comes back instantly. The purchase does not: Claude tells you it has sent the request to your BotShield app, a card appears on your phone with the event and the total, you confirm it with your passkey, and only then does the order complete with a confirmation number. This is demonstrating gating a MCP tool (e.g. checkout) with human presence verification using BotShield.

**One line on the lane:** BotShield never touches the payment. The card, the charge, and the checkout stay exactly where they are — with the seller and the payment network. BotShield adds one thing: proof that a verified human stood behind the action. By design that reduces fraud — an action no verified human approved cannot complete, so unauthorized purchases, and the disputes they cause, have far less room to happen. It completes the rails; it does not replace them.

The neutrality is the whole point. The layer that proves the human works only because it holds nothing and has no stake in the outcome — a notary, not a party. That is what lets a seller, an agent, and the network that moves the money all build on the same attestation and trust it.

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image-8.png)

*The Ticketz MCP Server Has Been Added to Claude Desktop*

---

## Step one: Link with Agents Ask

When you connect the Ticketz connector, Claude runs a standard OAuth flow against the Ticketz authorization server. Instead of a login form, the page shows one button: **Get my link code**. It produces a six-character code that has a 10 minute TTL.

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image.png)

In the BotShield app you open **Link an Agent**, type the code, and confirm with your passkey. That single ceremony does two things:

- It proves to BotShield that a real, verified human is behind the link, because the passkey is bound to the device and the person, not to the agent.
- It mints a **pairwise opaque ID** for this agent only. Ticketz receives an identifier that works for Ticketz and for nothing else. Another agent asking about the same person gets a different one. There is no email, no name, and no account to correlate.

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/app_link_an_agent.png)

The authorization server then issues Claude a token whose subject is that opaque ID. From here on, every tool call Claude makes to Ticketz carries it.

## Standards on the wire

Connecting Ticketz follows the Model Context Protocol’s authorization spec. Claude discovers the authorization server (RFC 9728, RFC 8414), registers itself (RFC 7591), and runs a standard **OAuth 2.1 authorization-code flow with PKCE (S256)** and an exact redirect URI; the code it gets back is single-use and short-lived. The only unusual part is the sign-in page: instead of a password, you link with BotShield and confirm with your passkey.

The access token is an ES256-signed JWT whose subject is your pairwise ID, and the gateway verifies it against published keys. The per-purchase approval today is the BotShield Agents Ask API. We are moving it onto OpenID’s **CIBA** standard (Client-Initiated Backchannel Authentication), so any OpenID library can call it. That is the subject of a later part in this series.

![Sequence diagram: Claude connects to Ticketz with OAuth 2.1 (discovery, registration, code flow with PKCE, link code confirmed with a passkey, ES256 token), then each checkout passes the agent gateway and is approved by the person with a passkey before BotShield returns a signed resolution.](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/10/technical-series-1-oauth-flow.png)

Connect once with standard OAuth 2.1; every purchase then asks the person.

## Step two: the purchase becomes a question

The Ticketz `checkout` tool does not charge anything on the first call. It proposes the action to the linked human through the BotShield API:

```
POST /operations/agentlink/inquire
Authorization: Bearer bs_agent_TicketzAgent__…

{
  "request_id": "4d0ce1dd-…",
  "opaque_id": "OP_WUCX4YttUJpb",
  "action": {
    "summary_title": "Ticketz · 1× Coral Bay Music Festival",
    "category": "commerce.purchase",
    "summary_detail": { "label": "TOTAL", "value": "$89.50" }
  },
  "ttl_seconds": 600
}
```

BotShield checks three things before anything reaches a phone. The agent key must belong to a registered agent. The opaque ID must have an active link to *this* agent, so an ID minted for someone else resolves to nothing. And the action category must be one the agent was registered to ask for. Ticketz is allowed the BotShield defined scope `commerce.purchase`; it could not, for example, ask to change an address.

If all three pass, a card is created and pushed to the human's device. The tool tells Claude the request is pending and when it expires, and Claude tells you it is waiting.

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image-4.png)

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image-2.png)

## Step three: the human decides

The card shows what the agent is asking, who is asking, and the amount. Approving it is a passkey ceremony on the phone, unlocked the same way you unlock the device. The result is not a boolean stored somewhere. BotShield signs a **resolution**, a JWT that names the request, the verdict, the opaque ID and the ceremony, using keys published at a public JWKS endpoint. Anyone holding that token can verify, without calling BotShield, that a verified human approved that specific request.

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image-3.png)

## Step four: completing the order

Claude calls `checkout` again with the request ID. The tool long-polls BotShield for the resolution, holding the call for about seventy-five seconds at a time so the model is not bouncing through retries while you reach for your phone. When the resolution arrives, Ticketz completes the order and returns a receipt that carries the confirmation number and the attestation: which opaque ID approved it and which ceremony produced the signature.

If the card expires or you decline, the tool says so and nothing is charged. There is no fallback path that completes without the human.

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image-2.png)

## Where the enforcement actually lives

Two layers enforce this, and they enforce different things. The per-purchase approval you just saw is application code inside the Ticketz MCP server: it proposes the action, waits for the resolution, and completes the order only on an approve verdict. That is a fine way to integrate, and for most sellers it is the whole story.

In the demo there is a second layer that does not depend on the seller writing anything. The traffic between Claude and Ticketz passes through an **agent gateway** running a BotShield policy. The gateway verifies the bearer token against the Link server's published keys and exposes the `checkout` tool only to a caller carrying a linked opaque ID. An agent that never linked a human does not get a denied call; it does not see the tool at all. Ask the gateway for its tool list with no token and you get `list_events` and nothing else. The Ticketz server is never reached.

So the gateway guarantees that only a verified, linked human's agent can reach the tools you name, and the seller's server guarantees that each action was approved. The first needs no code on the seller's side; the second is a few calls to the BotShield API. That policy layer is the part developers ask about most, and it is what the console hands you: a registered agent key, the gateway policy pack, and the Link server that runs the Link ceremony as the connector's OAuth step. Point it at an existing MCP endpoint, name the tools that require a person, and the same experience applies to your agent. A purchase today; a transfer, a new payee, or a data-sharing consent tomorrow — the same gate fits any consequential action a person should stand behind.

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image-6.png)

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image-7.png)

## What crossed the wire, and what did not

| Party     | Learns                                   | Never sees                                      |
| --------- | ---------------------------------------- | ----------------------------------------------- |
| Claude    | an opaque ID, the resolution token       | your email, name, passkey, device               |
| Ticketz   | the same opaque ID, one approved request | who you are, your other agents                  |
| BotShield | that a verified human approved request X | what you bought beyond the summary you approved |

## Try it — open beta

![](https://storage.ghost.io/c/7e/c0/7ec03f3f-948f-443a-b8e5-6828d0924234/content/images/2026/09/image-10.png)

[](https://console.botshield.ai/?utm%5Fsource=newsroom&utm%5Fmedium=blog&utm%5Fcampaign=claude-ticketz-demo) in the BotShield Console, register an agent, and download the gateway policy pack from your dashboard. The Ticketz server is open for you to point a connector at. The open beta opens the day the BotShield app lands on the App Store and Google Play. That is by design: because we hold no data about you, there is no shadow dataset to test against, so the only honest way to harden a personhood layer is to run it live. Build against it now, so you are ready the day it opens.