# Verifiable Intent
Source: https://docs.treeship.dev/integrations/verifiable-intent

> Treeship as one agent_attestation scheme inside Verifiable Intent credentials, shipped as treeship vi

[Verifiable Intent](https://verifiableintent.dev/) is an open credential standard for agent commerce, maintained by Mastercard and co-developed with Google (draft v0.1, February 2026). It defines a three-layer credential chain that proves an agent was authorized to act on a user's behalf. Treeship implements the agent's side of that chain, `treeship vi`, and supplies one `agent_attestation` type for the Layer 3 credential: the signed evidence of what the agent actually did between receiving the mandate and handing the cart to checkout.

This is an independent implementation against the published draft and its reference SDK, tested against that SDK in both directions in CI. Treeship interoperates with Verifiable Intent; it is not endorsed by, and does not speak for, the standard's maintainers.

> **Note**
>
> Shipped in 0.31 against the published **v0.1 draft**, and included in the current release, 0.31.14. The implementation follows the credential format and constraints pages on [verifiableintent.dev](https://verifiableintent.dev/) and is tested against the reference SDK in CI. The draft is not final, so the CLI names it as a draft. The command reference is [`treeship vi`](/cli/vi). Since 0.31.6, `vi verify --local --require-attestation` checks the attestation signature under a trusted key. Before 0.31 this page described a design; the April 2026 `packages/vi` types it referred to were written against a pre-v0.1 draft and never wired, and are retired.

## The published draft, as it stands

[verifiableintent.dev](https://verifiableintent.dev/) still labels the specification **Draft v0.1**. The credential format page keeps the date 2026-02-18 and, together with the constraints page and the homepage, is the text `treeship vi` implements:

* **Eight registered constraint types.** Amount bounds, merchant and payee allowlists, line items, a payment reference, a budget cap, and two recurrence forms. A stateless verifier checks the ones that can be checked from a single purchase. Budget totals, recurrence, and occurrence counts need the network's ledger. `treeship vi check` evaluates one purchase. It does not keep that ledger.
* **Versioned mandate types and a nested agent key.** Open mandates are `mandate.checkout.open.1` and `mandate.payment.open.1`. Final mandates are `mandate.checkout.1` and `mandate.payment.1`. The wallet binds the agent's P-256 key at `cnf.jwk`, and every Layer 3 header `kid` must match `cnf.jwk.kid`.
* **Selective disclosure.** Each recipient sees the disclosures the spec routes to it. That privacy is the SD-JWT. Receipt field privacy is a separate surface, [`treeship present`](/cli/present).
* **Protocol mappings, outside the core spec.** The homepage points at AP2, ACP, and UCP. The [protocol landscape](https://verifiableintent.dev/protocol-landscape/) bounds those mappings to UCP as of 23 January 2026, AP2 as of 16 September 2025, and ACP as of 30 January 2026. AP2 leaves the verifiable-digital-credential format open; the landscape presents Verifiable Intent as one concrete format for that slot, and says the credentials can be carried in UCP's AP2 mandate extension and in ACP's extension. Treeship signs and verifies the credential. It does not implement those checkout transports, and it does not implement Visa's Trusted Agent Protocol.

The site's changelog page still records 0.1.0 (2026-02-19) and five constraint types, and says there are no unreleased changes. The credential format, the constraints registry, and the homepage are ahead of that changelog. This implementation follows those three, not the changelog page.

The [security model](https://verifiableintent.dev/spec/security-model/) states the boundary this integration is for. Verifiable Intent checks that an agent stayed inside the mandate. It does not check how the agent behaved on the way there. `agent_attestation` (§9.2 of the overview) is the optional claim reserved for that record. A verifier that does not recognize the type ignores the claim. Treeship registers `treeship.receipt-chain.v1` and puts the signed receipt chain in `value`.

One mandate pair per L2. The overview allows several pairs in one Layer 2 credential, and `mandate.payment.agent_recurrence` allows several Layer 3 fulfillments of one pair, counted by the network. `treeship vi` refuses an L2 that carries more than one checkout mandate or more than one payment mandate.

## The credential chain

```
L1: Issuer credential
    The payment network or credential provider issues an SD-JWT that
    identifies the user and binds their device key.

    |
    v

L2: User mandate
    The user delegates bounded authority to a specific agent: checkout
    constraints, payment constraints, a time window, and the agent's key
    bound under `cnf`.

    |
    v

L3: Agent execution (autonomous mode)
    The agent signs two key-bound SD-JWTs, L3a for the payment network and
    L3b for the merchant, each bound to the L2 mandate. This is where the
    `agent_attestation` claim lives, and where Treeship plugs in.
```

`treeship vi keygen` mints the agent's key and prints the JWK the wallet binds at L2. `treeship vi attest` signs L3a and L3b, after checking the purchase against the mandate. `treeship vi verify` checks a pair the way the reference verifier does, then the attestation.

## What Treeship puts in the claim

The v0.1 draft shapes the claim as `{ "type": "<scheme>", "value": <payload> }` and requires verifiers to ignore types they do not recognize rather than reject the credential. Treeship did not invent the field; it registers the scheme `treeship.receipt-chain.v1` and fills `value` with a signed statement, every field of which already exists in a Treeship session:

| Field            | What it contains                                                                                                            | Where it comes from               |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
| `session`        | The Treeship session id, which names the exported `.treeship` package a verifier receives                                   | `treeship session`                |
| `chain_head`     | The id of the last receipt in the session's chain at the moment the L3 pair was signed                                      | The receipt chain                 |
| `checkpoint`     | The Merkle root over every receipt from the session root to that head, so a verifier can check inclusion of any single step | `treeship merkle` / session close |
| `approval_use`   | The digest of the approval-use record that spent the human approval the action ran under, when one exists                   | The Approval Use Journal          |
| `mandate_digest` | SHA-256 of the L2 base JWT, so the attestation names the mandate it was issued against                                      | The L2                            |
| `transaction_id` | The `checkout_hash` both L3 halves carry                                                                                    | The checkout JWT                  |

The statement is signed with the ship's Ed25519 key as an ordinary action receipt (`vi.l3.attested`, DSSE envelope, `parentId` = `chain_head` inside the signature), stored on the chain, and `value` carries the envelope, its artifact id and the signing public key. Any Ed25519 library confirms the signature with no Treeship code. `treeship verify <artifact-id>` walks the chain it sits on. The L3 credential itself is signed with the agent's P-256 key as the spec requires; Treeship does not replace that signature, it adds evidence underneath it.

A verifier that does not know the scheme ignores the claim and checks the rest of the chain as usual. The reference SDK does exactly that, and the interop suite asserts it. A verifier that does know it takes the `.treeship` package, runs `treeship package verify` and `treeship verify` offline, and checks that the package's chain head and Merkle root equal the two digests in the claim. That confirms the credential was minted at the end of exactly this sequence of signed steps, and that the human approval it cites was spent once and never replayed.

What is deliberately not in the payload: zero-knowledge proofs. Nothing in the shipped Treeship stack produces such a proof, and the design does not claim one. Field-level privacy for the receipts themselves is a separate, shipped surface: [`treeship present`](/cli/present).

## What crosses the issuer boundary

An L3 credential travels to a payment network and, in a dispute, to an issuer's evidence process. That is a different audience from the merchant's operators, so the identifiers in the claim are chosen deliberately rather than inherited:

* **The Treeship session id crosses.** It is a random identifier that names the evidence package. It is not a bearer credential and unlocks nothing on its own; the verifier still has to be handed the package.
* **The host's own session identifier does not cross.** In the [commerce-agents integration](/integrations/commerce-agents) the reference host's session id is a request credential, and receipts carry only the short tag the host logs. The VI claim carries neither.
* **No cart contents, prices, URLs, or order references cross in the claim.** Those are already digests in the receipts, and the claim carries only the chain head and root over them. (The L3 halves themselves carry what the spec says they carry: the amount and payee to the network, the checkout JWT to the merchant.)

## With Anthropic's commerce blueprint

Anthropic's [commerce-agents](/integrations/commerce-agents) reference stops at checkout hand-off: the shopping agent assembles a cart, and a hosted checkout owned by the merchant takes over. Verifiable Intent starts from the other end: the network wants a chain from the user's mandate to the transaction. Treeship's commerce package already signs the steps in between, so the mapping is direct:

| Verifiable Intent                                                       | Treeship commerce receipt                                                                             | Note                                                                                                                                                                                                   |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| L2 mandate constraints (`amount_range`, `allowed_payees`, `line_items`) | `commerce.checkout.handoff` carries `subtotal`, `currency`, `item_count`, and a per-hand-off `seller` | `treeship vi attest` is run at hand-off with the cart's values; the chain the attestation names runs through the hand-off receipt, so the claim binds the cart that went to checkout to the credential |
| L3b `checkout_hash` (SHA-256 of the merchant's checkout JWT)            | `cart_digest` (SHA-256 over the canonical cart)                                                       | Different preimages by design: the spec hashes the merchant's token, Treeship hashes the cart the agent built. The claim's `transaction_id` is the former; the chain it names covers the latter        |
| L3a payment leg                                                         | `commerce.order.placed`, on the chain after the hand-off, naming it                                   | Treeship records that an order was placed and for how much, digesting the order reference. It does not touch the payment instrument; that stays on the network                                         |
| Provenance-gate refusals                                                | `commerce.tool.*` receipts with status `blocked`                                                      | Not part of VI at all, and the part an issuer is most likely to ask about: the planted cart add that the gate refused is in the same chain the credential cites                                        |

Merchant-side approvals (the signed, single-use grants in the merchant vertical) are outside Verifiable Intent, which is the buyer's chain. They stay in the merchant's own session package.

## Key management

Verifiable Intent requires ES256 (P-256) for every layer's signature, alongside Treeship's default Ed25519 receipt keys. `treeship vi keygen` generates the P-256 keypair, seals the private scalar at rest with the ship keystore's machine key (the same AES-256-GCM construction that protects the Ed25519 keys), and prints the public half as the JWK the L2 mandate binds under `cnf`. `treeship vi keys import` takes a private JWK a wallet or HSM issued instead.

## Status

| Stage           | Capability                                                                                                                                                                                                          |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| spec (external) | `agent_attestation` claim on L3, `{ type, value }`, unknown types ignored: defined by Verifiable Intent v0.1, not by Treeship                                                                                       |
| shipped · 0.31  | `treeship vi keygen` / `keys` / `check` / `attest` / `verify`; key-bound SD-JWT L3a/L3b with `sd_hash`, `transaction_id` / `checkout_hash`; the eight constraint types; the `treeship.receipt-chain.v1` attestation |
| shipped · 0.31  | Two-way interop with the reference SDK, in CI                                                                                                                                                                       |
| shipped         | Every field of the attestation value: session ids, receipt chains, Merkle checkpoints, approval-use records, `treeship verify` over an exported package                                                             |
| shipped         | The commerce receipts the claim binds: `commerce.checkout.handoff` and `commerce.order.placed` in [treeship-commerce](/integrations/commerce-agents)                                                                |
| not in scope    | A second mandate pair in one L2; network-side cumulative budget and occurrence counting; immediate mode (no L3 exists); UCP, ACP, and Visa Trusted Agent Protocol transports                                        |

## Compatible with Lobster Cash

Verifiable Intent credentials and Lobster Cash payments work together. The flow is:

1. L2 mandate delegates payment authority to the agent
2. Treeship attests each step (intent, approval, execution)
3. Lobster Cash executes the payment
4. Treeship produces the `agent_attestation` for the L3 credential
5. The L3 credential, the Treeship receipt chain, and the Lobster Cash settlement form a complete proof

See the [Lobster Cash integration](/integrations/lobster-cash) for the payment-specific workflow.

> **Warning**
>
> Mastercard-specific integration details (network rules, merchant onboarding, credential exchange protocols) are separate from this technical implementation. This page covers the open Verifiable Intent standard only.