> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentvault.io/llms.txt
> Use this file to discover all available pages before exploring further.

# How it works

> Follow a checkout from your agent to the merchant, and see exactly where the real card number appears and what is checked first.

Follow one checkout from your agent to the merchant, and see the one point where
a token becomes your real card number.

## The pieces

| Piece | What it is | Where it runs |
| - | - | - |
| Your agent | A script, an MCP host or an agent framework | Your machine or server |
| Client | `@agentvault/mcp` (MCP server) or `@agentvault/playwright` (SDK) | The same process as your agent |
| Proxy | A Playwright browser plus the engine that checks rules and swaps tokens | Agent Vault infrastructure |
| Backend | Accounts, cards, logins, agent cards, sessions and the activity log | Agent Vault infrastructure |
| Vault | The card number store. Cards are tokenized in your browser | The card vault provider |
| Dashboard | Where you set rules and approve purchases | Agent Vault web app |

## A checkout, step by step

<Steps>
  <Step title="The agent reads its token catalog">
    With its API key, the agent asks the backend which tokens it may use. It gets
    mock tokens plus the card brand and last four digits.
  </Step>

  <Step title="The agent opens a proxy session">
    It connects to the proxy over a WebSocket with the same key. The proxy starts
    a browser for this session.
  </Step>

  <Step title="The agent shops">
    It opens the product page, adds to cart and goes to checkout. For name and
    address fields it sends tokens, and the proxy types the real values on a site
    you have authorized as a [destination](/dashboard/destinations).
  </Step>

  <Step title="The agent fills the card number with a token">
    The proxy reads the order total from the page and asks the backend to check
    the key's scope, your merchant rules, whether the site is an authorized
    destination, your limits and your approval threshold. If the purchase needs
    your approval, the checkout waits for you.
  </Step>

  <Step title="The backend records the transaction and allows the fill">
    Recording first keeps your limits accurate even if something fails later.
  </Step>

  <Step title="The proxy types the real card number">
    It fetches the number from the vault, holds it in memory while it types it
    into the merchant's field, and stores it nowhere. Until the session closes,
    it keeps the number's spellings in memory, only to scrub them from what the
    agent is later shown. The Agent Vault backend
    never receives it.
  </Step>

  <Step title="The agent submits and reports the outcome">
    The agent clicks pay. The proxy tries to record the session's events and
    outcome for the **Activity** page. Recording is best effort and never holds
    up the agent, so an event that fails to save is missing rather than retried.
  </Step>
</Steps>

The same path as a sequence diagram:

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant A as Agent
    participant P as Proxy (Playwright)
    participant B as Backend
    participant V as Vault
    participant M as Merchant

    A->>B: GET /v1/tokens (Bearer api key)
    B-->>A: Token catalog (mock tokens + metadata)
    A->>P: launch() over WebSocket, authenticate with the key
    P-->>A: Session open
    A->>P: goto(product url), click, fill address tokens
    P->>M: Real address values typed into the page
    A->>P: fill(#cardNumber, av_card_1_number_u7x2k)
    P->>P: Read the order total off the page
    P->>B: Check scope, merchant rules, destination, spending limits, approval threshold
    B-->>P: Allowed, and record the transaction
    P->>V: Reveal the card number for this vault token
    V-->>P: Real PAN
    P->>M: Real PAN typed into the field
    A->>P: click(#pay)
    M-->>P: Confirmation page
    A->>P: get_session_outcome / recordOutcome
    P-->>B: Session events and outcome (best effort, may be dropped)
```

The card number appears in cleartext only at steps 12 and 13: in the proxy's
memory, then on the merchant's page. The proxy uses it for that one fill, and
keeps its spellings in memory until the session closes only to scrub agent-facing
output. The agent and the backend never
receive it.

## What is checked at the moment of a fill

Every fill goes through the same decision. A refusal at one of these checks
returns an error code the agent can act on, and nothing is typed. A failure
after typing has started is different: with `fill_rejected`, a page that goes
away mid-fill, or typing that fails partway, some or all of the value may already
be on the page, and a card transaction can stay counted. Each code's entry in
[Error codes](/sdk/error-codes) says how to recover.

```mermaid theme={null}
flowchart TD
    Start[Agent calls fill with a token] --> Parse{Does the string parse<br/>as a token?}
    Parse -- No --> Literal[Type it literally.<br/>Nothing sensitive involved]
    Parse -- Yes --> Owner{Does the token belong to<br/>this session's account?}
    Owner -- No --> Cross[cross_user_denied.<br/>Three strikes revokes the key]
    Owner -- Yes --> Scope{Is this key scoped<br/>to this resource?}
    Scope -- No --> Denied[scope_denied]
    Scope -- Yes --> Kind{Token kind}
    Kind -- Login or TOTP --> Host{Is this host the login's<br/>website or an extraWebsite?}
    Host -- No --> Blocked[login_blocked]
    Host -- Yes --> Resolve[Resolve and type]
    Kind -- Identity or address --> Dest{Is this host an<br/>authorized destination?}
    Dest -- No --> DU[Ask the owner.<br/>destination_unauthorized until approved]
    Dest -- Yes --> Resolve
    Kind -- Card number --> Gate{Active agent card<br/>permits this merchant?}
    Gate -- No --> MB[merchant_blocked or card_paused]
    Gate -- Yes --> CDest{Is this host an<br/>authorized destination?}
    CDest -- No --> DU
    CDest -- Yes --> Total{Order total readable?}
    Total -- No --> Capped{Enforced cap or<br/>approval threshold?}
    Capped -- Yes --> Unknown[checkout_total_unknown,<br/>or a hold if a threshold is set]
    Capped -- No --> RecordUnknown[Accepted under the plan quota.<br/>Recorded as unknown]
    RecordUnknown --> Reveal
    Total -- Yes --> Limits{Under the plan's payment quota<br/>and every agent card limit?}
    Limits -- No --> Limit[plan_quota_reached for the quota.<br/>limit_reached for a card limit]
    Limits -- Yes --> Approve{At or above confirmAbove?}
    Approve -- Yes --> Hold[Pause and ask the owner]
    Approve -- No --> Record[Record the transaction]
    Hold --> Record
    Record --> Reveal[Reveal from the vault and type]
```

Two consequences for anyone writing fill steps:

* **The transaction is recorded before the number is revealed.** A failure after
  that point can leave a recorded spend with no charge.
  [Error codes](/sdk/error-codes) say which failures do.
* **The card number authorizes exactly one security code fill.** The next page
  action uses it up, so fill the security code immediately after the number. See
  [The card fill order](/guides/first-checkout#the-card-fill-order).

## Where each secret lives

| Secret | Stored where | Reaches the proxy | Reaches the agent |
| - | - | - | - |
| Card number | Card vault provider. Never stored by Agent Vault | In memory. Used for one fill, then kept until the session closes only for scrubbing | Never |
| CVV | Never stored. Only in the proxy's memory, for the session that needs it | Only when you type it live. Used for one fill, then kept until the session closes only for scrubbing | Never |
| Card expiry | Backend | Yes, as non-secret metadata the agent supplies. The agent reads `expiryMonth` and `expiryYear` from the catalog and passes the literal values in its fill, which runs through the proxy | Yes, it is not a secret |
| Login password | Backend, encrypted | At fill time. Used for one fill, then kept until the session closes only for scrubbing | Never directly. If a site renders a filled password as text, its non-digit characters can be probed like any echoed value. See [the digit-free echo exception](/security/agent-context#the-guarantee) |
| TOTP secret | Backend, encrypted | Never from the backend. Only the current code, derived by the backend, used for one fill and then kept until the session closes only for scrubbing. During [enrolment](/security/totp#enrolment-by-an-agent) the proxy reads a new secret off the site's page and passes it to the backend | Never |
| Name, address, contact | Backend | At fill time. Used for one fill, then kept until the session closes only for scrubbing | Only as tokens. A page that echoes one as text can have its non-digit characters probed, never its digits. See [the digit-free echo exception](/security/agent-context#the-guarantee) |

Details: [Card storage](/security/card-storage), [CVV policy](/security/cvv-policy)
and [TOTP handling](/security/totp).

## What the agent can see and where its traffic goes

* **Reading the page.** After the first token fill, screenshots go black and the
  page snapshot is refused for the rest of the session. Have the agent look at
  the page before it fills anything. Full table:
  [Agent context](/security/agent-context).
* **Network address.** By default the SDK tunnels the browser's traffic out
  through your machine, because many sites block datacenter addresses. See
  [Egress and tunnelling](/sdk/tunnel).

**Next:** [Choose an integration](/get-started/choose-an-integration) to pick how your agent connects.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.