--- name: resy-booking description: >- Book restaurant reservations on Resy. Use when the user asks to book a table, make a reservation, find a restaurant, or check availability. homepage: https://agentres.dev metadata: version: 2 --- # Resy Booking Read fully before acting. Every rule is load-bearing. **Base URL:** `https://agentres.dev` · **Full schemas:** [openapi.json](https://agentres.dev/openapi.json) **Execute step-by-step.** Don't preview the flow or batch questions — ask only for what the current step needs, then continue. ## Step 0 — Pick auth path (do this FIRST) Exactly one path. Never mix auth mechanisms mid-conversation. - `AGENTRES_API_KEY` in memory, **or** user says "API key" → **Path A**. - User says "tempo" / "agentcash" / "wallet" / "x402" → **Path B**. - Otherwise → recommend Path A (no wallet setup, fastest). ## Path A — API key Plain `fetch` with header `x-agent-key: `. **Never** call AgentCash / mppx / x402 / tempo tools on this path. 1. Key in memory? → go to **Common workflow**. 2. User pastes an `agentres_...` key? → save to memory as `AGENTRES_API_KEY` → **Common workflow**. 3. No key? → the user must paste one or buy one. Share: **https://buy.stripe.com/14A6oGbGr3XI723f2Ib7y00** **STOP.** Wait for an `agentres_...` key. Do not call any endpoint. The Stripe purchase auto-links the purchase email as the agentres account. **Do not ask the user for an email on Path A.** The only email you may request is their Resy.com email (during Link Resy). ## Path B — Wallet (tempo / agentcash / x402) Use the appropriate wallet tool to handle 402 challenges. Bookings cost **0.01 USDC**; every other endpoint is **$0** (wallet signs for identity only, no charge). Proceed directly to **Common workflow**. ## Common workflow Every POST must include `"content-type": "application/json"`. On Path A add `x-agent-key: ` to every request. ### Step 1 — `GET /api/me` ``` → { user_id: string, email: string, resy_linked: boolean } ``` Branch on the response — do not skip: - **200 + `resy_linked: true`** → jump to **Search**. - **200 + `resy_linked: false`** → jump to **Link Resy**. - **401 on Path A** → the API key is invalid or revoked. Ask the user for a valid key or share the Stripe link. Do not proceed. - **401 on Path B** → no agentres account for this wallet. Jump to **Create account**. ### Create account *(Path B, first-time wallet only — skip otherwise)* Ask once: *"What email should I register your agentres account under?"* ``` POST /api/account body: { "email": "user@example.com" } ``` Then continue to **Link Resy**. ### Link Resy *(skip if `resy_linked: true`)* The user's **Resy.com account** must be linked to their agentres account. One-time setup per user. Ask once: *"What email is your **Resy.com** account under?"* (Their existing Resy.com login — not a new email.) ``` POST /api/link-resy body: { "em_address": "user@example.com" } ``` Tell the user to check their email for a 6-digit code from Resy. Then: ``` POST /api/link-resy body: { "em_address": "user@example.com", "code": "123456" } ``` Field is **`em_address`** (not `email`). Code is a string. ### Search ``` GET /api/search?query=sushi&city=nyc → [{ venue_id, name, neighborhood, cuisine, rating }] ``` `query` required. `city` optional (default `nyc`; full list in openapi.json). ### Availability ``` GET /api/availability?venue_id=59237&party_size=2&day=2026-04-25 → { venue_name, slots: [{ config_id, time, type }] } ``` All three params required. `day` is exactly `YYYY-MM-DD`. Present slots, ask which to book, remember the `config_id`. **"Anything open in X at 8pm"** queries: search the area, call availability for every venue **in parallel**, filter ±30min, present as a table. ### Book *(explicit confirmation required)* Show a summary and wait for "yes": > **Please confirm:** Book **Venue** on **Date** at **Time** for **N** people? Reply "yes" to confirm. > *(Path B: also state "this will charge **0.01 USDC** (non-refundable).")* Only "yes" / "confirm" / "book it" / "go ahead" count. Anything ambiguous → clarify, do not book. ``` POST /api/book body: { "venue_id": "59237", "config_id": "", "party_size": 2, // JSON number, NOT a string "day": "2026-04-25" } ``` ### List reservations ``` GET /api/reservations?type=upcoming&limit=10 → [{ venue, resy_token, ... }] ``` `type`: `upcoming` (default) | `past`. `limit` 1–50. `offset` ≥ 0. ### Cancel 1. `GET /api/reservations?type=upcoming` → find `resy_token`. 2. Match the user's description; clarify if ambiguous. 3. Confirm with a summary + explicit "yes". 4. `POST /api/cancel body: { "resy_token": "" }` Never guess or reuse `resy_token` across conversations. ## Rules 1. **Pick one auth path and stay on it.** Never mix `x-agent-key` with wallet tools. 2. **No API key and no wallet → stop.** Share the Stripe link; wait for a key. Do not call endpoints. 3. **Path A never asks for an email** — the Stripe purchase already linked the agentres account. The only email you may request is the user's Resy.com email during Link Resy. 4. **Path B creates an agentres account only when `/api/me` returns 401.** If 200, the account already exists — skip Create account. 5. Always start with `/api/me` once credentials are set. 6. Always use `/api/search` to get `venue_id` — never guess. 7. Always fetch fresh `/api/availability` immediately before `/api/book` — `config_id` expires. 8. Dates are `YYYY-MM-DD`. `party_size` is a JSON number. 9. Booking and cancelling require a summary + explicit "yes". 10. Booking fees are non-refundable — disclose at booking confirmation, not at cancel. 11. Errors return `{ error: { code, message, retryable, next_step } }` — follow `next_step`. 12. One step, one ask. Don't announce future steps or request info you won't use this turn.