Before you start
- An iMessage agent that receives a text and replies in the same thread. The first guide builds one on Linq, Vercel, and Redis.
- Agentcard sandbox credentials, from Commerce SDK, Start implementing in the dashboard. Quickstart shows where.
- Node 18 or later.
The sandbox stops before payment. A confirm there ends
declined, with no approval link and no order. Checking the approval and the placed order needs live credentials, as Go live describes.How it works
The user’s phone number is theirexternalUserId. Agentcard connects them to your company the first time they ask, with one Vault link, and never needs a code or an account.
1. Install the SDK
AgentcardClient and keep one buy tool for each phone number, as Quickstart shows. Set ack: 'text' on each tool, because iMessage shows no reactions to the agent:
agentcard.ts
2. Send texts, photos, and links through Linq
Linq sends a message from your number with a list of parts. Atext part holds words, and a media part holds the web address of an image, which Linq fetches and delivers as a photo.
linq.ts
3. Answer each text in its own turn
Open a turn for each text and hand the app the turn in order withonItem. The turn sends the instant reply, then the product cards, then your model’s words about them, and it holds each step link until the message that asks for it went out. Answering each shopper message in its own turn explains each option.
chat.ts
loadHistory and saveHistory stand for your own code. Save the history after every turn, because the model reads from it that the user saved a card or got an order.
Use the user’s phone number in the same form every time, such as +14155550100, so the same person always maps to the same tool.
4. Hear from Agentcard at a webhook endpoint
A Vercel function ends each request after a few seconds, so take Agentcard’s events at a webhook endpoint instead oflisten. Mount agentcardWebhook on the route where the first guide points Agentcard, and run the next step for the user when a message advances the purchase. Taking the next step once the shopper finishes outside the chat explains the turn.
app/agentcard/webhooks/route.ts
runNextStep is onText for a turn that nextStep opened: it runs the model on step and sends the answer in place of message.text. saveAssistantMessage appends an assistant message to the user’s history.
A Vercel function keeps a user’s tool only while its own instance lives, and the chat route and this route can run in different instances. The next step reads where the purchase stands from Agentcard, so the card link, the cart, and the ask for the yes still arrive. A yes the user already gave in the chat, and the first ask of a user who was not connected yet, stay in the instance that took them, so the next step asks for the yes again, or asks the user to carry on from what they last asked for. To take both with nothing typed, run the chat and agentcard.listen together in one long-running process.
Create the webhook endpoint, subscribed by name to the three events that carry a message for a user. A catch-all * alone does not turn purchase.message on. Exchange your client ID and secret for an organization token first, as step 6 of the first guide shows.
AGENTCARD_WEBHOOK_SECRET on Vercel and deploy again. The handler answers 400 to a delivery whose signature does not match, so until the secret is set, no message arrives.
5. Text it
From the phone you activated the Linq sandbox with, text the Linq number:111111, and save any of Stripe’s published test cards. The sandbox sends no card-saved message, so text the agent again, and it texts the products for your ask. Send “the second one”, and the agent adds that product and texts the cart. Send “yes”, and the confirm ends declined, because the sandbox stops before payment.
Go live
Going live makes the approval link, the passkey tap, and the placed order real. The code does not change.- Switch to Live credentials and choose how to pay the fee, as Quickstart describes.
- Replace
AGENTCARD_CLIENT_IDandAGENTCARD_CLIENT_SECRETon Vercel with the production values. - Create a live webhook endpoint with the live credentials, because an endpoint belongs to a mode, and replace
AGENTCARD_WEBHOOK_SECRETwith its secret. - Deploy, then buy one inexpensive item with your own card. Check that the approval link arrives alone, and that “order placed” arrives after the tap with nothing typed.
If nothing comes back
- The Vault link opens a sign-in page instead of the card form. Something was glued onto the URL. Send every link as its own message.
- The agent asks “did you save your card?” after the user did. The model never read the card message. Check that
saveAssistantMessageruns, and thatloadHistoryreturns whatsaveHistorystored. - The card is saved and nothing happens. Check the endpoint’s deliveries under Settings, Developers, Webhooks in the dashboard. A
400meansAGENTCARD_WEBHOOK_SECRETdoes not match the endpoint. A500meansonMessagethrew, and Agentcard delivers the event again. - Messages arrive in the wrong order. Hand the turn to your app with
onItemand write the model’s text throughturn.messageStream(). - A product has no photo. The store sent none, so
imageUrlis null. Send the name and price alone.
Where to go next
- Showing products and carting the one the shopper picks for the product cards and the pick.
- Approving a purchase for the approval, the refusals, and the order messages.
- Commerce SDK reference for every option used here.