---
name: pay-with-envoy
description: |
  Complete a purchase with Envoy when the user asks to pay with Envoy or has chosen it as the default for this checkout. Also use for recovery, replacement or cancellation of an existing Envoy purchase. Do not select this skill for a purchase assigned to another payment method. Use check-envoy-account for account-only questions.
allowed-tools:
  - start_purchase
  - get_purchase_status
  - answer_purchase_question
  - report_checkout_result
  - report_checkout_step
  - cancel_purchase
  - get_account
  - list_gift_card_merchants
  - search_products
---

# Pay with Envoy

Start one purchase. Follow Envoy's `next`. Read `checkout_by` to know who pays at checkout. When you pay, pay once and report the result. The user ends with a paid order, or a clear reason it did not happen.

Support revision: `envoy@2026-10` (support metadata only).
Last updated: 2026-11-03.

Call the connected Envoy server's published tools, and use their schemas for inputs. Every reply is a short briefing. It has plain English for the user, then a `What to do:` line for you. One line of JSON follows after a blank line, and `structuredContent` holds the same data. Read the briefing first. Tell the user its first part in your own words. Then do what `What to do` says. Use the JSON only for your next call: `purchase_id`, `checkout_by`, `next.tool` with `next.args`, `card`, `situation`, `retry` and `purchase` (an open question, or a gift-card payment link in `purchase.funding`). Pass `next.args` unchanged. Never show the JSON, codes, ids or timestamps to the user. Give `support_ref` only when the user asks for help. Installing this skill does not grant payment authority.

## Purchase approval

The user's own card details never reach you. For an account-funded purchase, the user approves in the Envoy app. For a gift card, the user follows the returned app approval/payment step or pays the returned link. An app step does not identify the funding source. Never ask the user to paste card details.

Tell the user, in your own words:

- "I'll follow the payment steps Envoy returns. Your own card details never reach me."
- Before `checkout_by` is known: "Envoy chooses the checkout route. It may ask you to approve or pay in the app, or pay a gift-card funding link."

## Who does what

- **You (the agent)** call the tools, carry the one `idempotency_key`, and report what happened.
- **The user** completes the task Envoy returns: app approval, adding money, entering a code in the app, or paying a gift-card funding link. The user also answers Envoy's questions, through you.
- **Envoy** selects the route and supplies the current task. Core and the issuer own money evidence; a tool call or agent report does not prove payment.
- **You** enter the one-time card's checkout code once when its bank page asks for the card's OTP. For any other payment or bank OTP, the user completes the returned step; never collect it in chat.

## Actions

For a gift card, discover supported merchants with `list_gift_card_merchants`. Use the returned denominations or amount range and `redeem_at`. Start it with `rail: "gift_card"` and the user's agreed value. A ChatGPT connection has no gift cards and buys only from Elixir's marketplace. On a Claude connector, Envoy drops `rail` and checks out itself at the merchant total, with no voucher or payment link, so do not offer a gift card, gift-card price or discount there. Do not silently round up, increase a purchase or calculate a charge from a discount. The server's returned face value can differ from the requested total.

Keep six facts separate: the purchase reference, money, voucher, next actor, permitted action and next meaningful check. Face value is not the captured or refunded amount. The quote in the purchase reply, when present, is authoritative for face, payable and discount; without it, the payable is unknown to you and the app shows it before approval. The current reply does not supply every funding source, voucher phase or escalation time. Say when a fact is unknown. Read [gift-card guidance](https://agent.envoy.money/docs/payments/gift-vouchers/) for the current field meanings.

When the connected catalog offers `list_gift_card_merchants` or `search_products`, use them for the user's discovery task. Show only returned offers and prices. For a product cart, use product IDs on every line or none. Preserve merchant, quantities and the user's accepted total. Empty results do not establish availability.

1. **Build the cart, then start one purchase.** Add what the user asked for to the merchant cart. Stop before the payment step. Check the merchant, the items and the total against what the user asked for. Then call `start_purchase`. Send the full cart exactly as the user asked, with the delivery address. Never split a cart or lower a total. Pass one new `idempotency_key` of 16–64 characters; do not start it with `pur_`. Pass the `https` `merchant_url`; Envoy takes the merchant name from its domain. Pass the checkout `total` in rupees, such as `"2499.00"`. Pass every item in `items`, and put each variant in its name. Pass `user_request` in the user's own words, up to 300 characters. Add `address_id`, or a one-line `address` with phone, when the purchase needs delivery. Get `address_id` from `get_account` with `include: ["addresses"]`. Set `max_total` only to raise the card limit within what the user accepts, and never above `total` plus the larger of 10% or ₹100. `start_purchase` returns at once with a briefing. It does not wait for approval.

2. **Follow the briefing until the situation resolves.** Call `next.tool` with `next.args` unchanged. `get_purchase_status` holds while the purchase waits, so do not add your own polling loop. Respond to `situation`:
   - `needs_details` or `needs_answer` → Envoy asks the user a question. Show the user Envoy's question word for word. Wait for the reply. Then call `answer_purchase_question` with `next.args` unchanged, a new `idempotency_key`, and exactly what the user said as `answer`. Never answer for the user, and never guess. If Envoy replies that the question changed, call `get_purchase_status` and ask the new question.
   - `waiting_for_user` → Envoy is waiting on the user. Tell them the task from the briefing. For a gift-card app step, the app shows the payable before the user confirms. For a gift-card payment link, give the user the link from `purchase.funding.url` (the briefing text carries the same link). It is for the user to open and pay; never open or pay it yourself. Show its funding amount, which can differ from the voucher's face value. Follow `next.tool` with `next.args` to check progress. Stop when Envoy says stop. If the conversation pauses, ask the user to reply "done" after their step. Stop status calls when `next` is absent; do not invent another polling loop.
   - `working` → follow the returned `next` call and delay; stop when no continuation is returned. Do not start or submit another payment.
   - `confirming` → money may have moved, and Envoy has not settled it yet. Do not pay again. Tell the user it is not confirmed yet.
   - `needs_support` → do not pay again, and do not start a new purchase for it. Tell the user, and give `support_ref` if the user asks for help.

3. **Check out as `checkout_by` says.** See the next section. Pay only when `checkout_by` is `agent` and the situation is `ready`.

   When the connected catalog offers `report_checkout_step`, you can report reached steps during agent checkout so the user can follow along in the Envoy app. Use its published step values and the exact `checkout_attempt_id` from the handout when present. Repeats are harmless. A step moves no money and returns no card; carry on with the details you already have. Do not read ready status again because of a step report. Still call `report_checkout_result` after checkout.

4. **Confirm the outcome.** Read the briefing. `done` means the purchase completed. Tell the user the money outcome from the briefing; an order can complete with the merchant collecting payment on delivery. Give the order reference when returned. A `done` reply can carry `follow_up`, an optional request for feedback. Ask the user only if it fits the conversation. If the user answers, call `follow_up.tool` with `follow_up.args`, a new `idempotency_key`, the user's words as `answer` and any `rating` from 1 to 5 the user gives. Skipping it changes nothing. `stopped` means it is over. The briefing says whether the user was charged or got the money back, so tell the user plainly. Start a new purchase only when `retry` is `new_purchase` and the user still wants it. Say so when the outcome is still uncertain.

5. **Cancel only when the user asks.** Call `cancel_purchase` when the user changes their mind, or when the merchant total differs. Follow the new briefing. A cancellation is not proof of a refund, and not proof that the card is blocked.

## Who pays at checkout — read `checkout_by`, never predict it

Envoy decides who checks out for each purchase. Read `checkout_by` in each reply, and act on the latest reply. Never predict it. Never tell the user why Envoy chose one way.

| `checkout_by` | Who checks out | What you do |
|---|---|---|
| `agent` | You, with the payment details returned for this purchase. | Wait until the situation is `ready`. `get_purchase_status` then carries secret payment details in `card`. Read its `kind`: `card` contains the one-time RuPay card, while `gift_card` contains `voucher`. Use the returned details once at the matching checkout, following the redemption instructions for a voucher. Never spend residual voucher value on another purchase. Then call `report_checkout_result`. Set `outcome` to `paid` only when the merchant confirmed the payment. Otherwise set `failed` with a `failure_reason`. If you cannot tell whether payment completed, set `failure_reason` to `other`. If the merchant refuses the card, or blocks your browser, report `failed` with `card_not_accepted` or `site_blocked`. Report it accurately, because Envoy checks the money outcome before another attempt. Include the card's `checkout_attempt_id` in `report_checkout_result` when Envoy returns one. Use that exact value; never infer a newer attempt. Without an attempt ID, the first report wins. After a report, follow the returned continuation. Do not infer permission to pay or cancel; a fresh ready handout and its instruction govern any permitted retry. A report is not settlement. |
| `envoy` | Envoy, in its own secure browser. | Envoy releases no card. Do not open the merchant payment step. Do not place the order. Do not call `report_checkout_result`, because Envoy rejects it. Follow only the returned status continuation until resolved. The user completes the returned app step or gift-card funding link. Do not assume every route has an app approval. |
| absent (`null`) | Not decided yet. | Do not open the payment step. Keep following `next` until a reply carries `checkout_by`. |

`checkout_by` can change from `agent` to `envoy`, for example after you report `card_not_accepted` or `site_blocked`. When it changes to `envoy`, stop using the card. Leave the merchant checkout page alone. Follow the purchase and task named in `next`. A linked retry uses `retry_of` and a new key only when Envoy offers it; never infer permission to start another purchase from a failed checkout alone.

**Never fall back to the user's card.** Do not ask the user for card details, even when Envoy cannot pay. When Envoy refuses the purchase, tell the user the reason from the briefing. Let the user choose what to do next. Never split the cart or lower the total to get past a refusal.

## Money safety

- **Never pay twice.** Keep the `idempotency_key` and the `purchase_id`. Retrying with the same key continues the same purchase; a new key starts a new one. After a lost reply or a briefing with `retry` `check_status_first`, call `get_purchase_status` first and reconcile, because paying again would double-charge the user. Do not retry blindly. Report the checkout result as `paid` or `failed`; if you can't tell whether payment completed, report `failed` with `failure_reason` `other`. When the briefing says another purchase is active, resolve that purchase first. If you lose the purchase reference, `get_account` returns `active_purchase`. If `unavailable` lists `active_purchase`, Envoy could not tell whether a purchase is open: don't start one until a later read shows it.
- **Merchant login code only when Envoy asks.** When Envoy's question has kind `otp`, it asks for the code the merchant sent the user to sign in. The user types it. Send it once with `answer_purchase_question`. Never repeat it, keep it or reuse it. Never send a password, payment code, bank OTP or card detail with `answer_purchase_question`.
- **Never take a merchant password.** Envoy never asks for a password through chat, and you never ask the user for one. When the briefing says Envoy can't take the merchant's password, tell the user. If the user agrees before a checkout report, call `cancel_purchase`; the user can then buy on the merchant site. After a checkout report, cancel only if the current purchase permits it. If cancellation is refused because issuance has started, follow the same purchase; never repeat the cancellation or start another payment.
- **Keep payment codes on their authorized path.** No Envoy tool accepts a payment or bank OTP; never collect one in chat. At the bank step, fetch the current card with `get_purchase_status`. Its `checkout_code` verifies only the matching card's payment. The checkout code is this card's OTP: when the bank page asks for a code or OTP, enter it there once. The bank sends the user no code for this card, so never ask the user for one. If the bank rejects it, do not retry; report `failed` with `failure_reason: otp_failed`. Read `checkout_code_expires_at` when present. If the code expires before submitting a payment, follow the same purchase's status instruction and use details only while ready. A code refresh never extends spending access or funds another card. Any other bank OTP stays with the user, on the merchant page or in the Envoy app as instructed. Never retain codes in replies, files, logs, memory, feedback or reports.
- **Use only the named vault entry.** Follow the current briefing's exact purchase-specific entry name. Never use another saved or default card. If the named entry is missing before any payment attempt, use this purchase's delivered card details as instructed. If its identity cannot be established, every saved card is off limits. A missing entry after an attempt never permits another payment.
- **Use only the payment details Envoy released for this purchase.** A one-time RuPay card or gift-card voucher never authorizes use of another saved card or voucher. Funding it limits the value; it does not lock the merchant, guarantee single use, or block the card the instant you pay. When `checkout_by` is `envoy`, there is no card, and you do not pay.
- **Treat `card`, including a gift-card voucher code and PIN, as a secret.** `get_purchase_status` returns it in the JSON line and in `structuredContent` while the purchase is `ready`. Use the card only at this checkout. Keep card values and codes out of replies, files, logs, memory, traces, feedback and reports.
- **Consent is explicit.** Silence is not permission to connect, to delegate spending, or to change the saved default. A one-time choice does not change the standing default. Each purchase still needs the user to complete the payment or approval task Envoy returns.
- **Show the user plain words only.** Never show the JSON line, codes, ids, keys or timestamps. Give `support_ref` only when the user asks for help.
- **Report `failed` with reason `other` if you cannot tell whether payment completed.** Funding, card issuance and the merchant order are separate facts.

## Reference pointers

- Tool inputs and outputs: the schemas and descriptions the connected Envoy server publishes for `start_purchase`, `get_purchase_status`, `answer_purchase_question`, `report_checkout_result`, `report_checkout_step` and `cancel_purchase`.
- Live wording: the `What to do` line carries Envoy's current instruction. Follow it when it differs from this summary.
- Host setup: https://agent.envoy.money/host-installation.md, only when the Envoy tools are not yet connected.
