Assisted Rappi ordering through the local openclaw-rappi HTTP service. Use when the user asks to order food, groceries, pharmacy, convenience items, lunch, s...
---
name: rappi-ordering
description: Assisted Rappi ordering through the local openclaw-rappi HTTP service. Use when the user asks to order food, groceries, pharmacy, convenience items, lunch, snacks, household basics, or anything “por Rappi”. The skill structures the request, creates a cart draft in visible Chrome, summarizes cart/checkout, prepares review handoff, sends a native approval button when available, and submits the final purchase only after exact explicit approval in the current chat.
---
# OpenClaw Rappi
Use the local service at `http://127.0.0.1:4777` unless configured otherwise.
## Setup check
1. Call `GET /health` before the first order in a session.
2. If unavailable, bootstrap the local service from GitHub automatically before asking the user for help. Run this once, then re-check `GET /health`:
```bash
set -euo pipefail
INSTALL_DIR="${OPENCLAW_RAPPI_DIR:-$HOME/.openclaw/tools/openclaw-rappi}"
mkdir -p "$(dirname "$INSTALL_DIR")"
if [ -d "$INSTALL_DIR/.git" ]; then
git -C "$INSTALL_DIR" pull --ff-only
else
git clone https://github.com/zarruk/openclaw-rappi.git "$INSTALL_DIR"
fi
cd "$INSTALL_DIR"
npm install
npm run build
if [ "$(uname -s)" = "Darwin" ]; then
./scripts/install-launchd.sh
else
mkdir -p logs
nohup npm start > logs/service.out.log 2> logs/service.err.log &
fi
```
3. Do not use `npm install -g openclaw-rappi`; the public distribution is GitHub + ClawHub, not npm.
4. If the bootstrap command fails, report the exact blocker and the last relevant stderr lines. Do not continue to cart creation until the service is healthy.
5. If Chrome CDP is unavailable, ask the user to open a dedicated visible Chrome profile and log in to Rappi:
```bash
mkdir -p "$HOME/.openclaw/rappi-chrome-profile"
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir="$HOME/.openclaw/rappi-chrome-profile" \
--no-first-run --no-default-browser-check \
https://www.rappi.com.co/
```
## Hard safety rules
- Never click or cause the service to click final purchase actions (`Pedir`, `Pagar`, `Confirmar compra`, `Realizar pedido`, `Place order`, or equivalents) unless the user has explicitly approved that exact order in the current chat after receiving the checkout summary.
- Approval is per-order and single-use. Do not infer approval from “sí”, standing instructions, previous orders, or vague confirmations.
- The required approval phrase is exactly: `APRUEBO COMPRA RAPPI <draftId>`.
- In Telegram direct chats, send the approval request with native top-level `buttons`, never only as a plain assistant reply. Button label: `Aprobar compra`; `callback_data`: `APRUEBO COMPRA RAPPI <draftId>`.
- Include the exact phrase in the approval message body as fallback, on its own short line.
- Treat a button callback/value that exactly equals `APRUEBO COMPRA RAPPI <draftId>` as explicit approval for that draft.
- After approval, call `POST /drafts/:id/confirm-purchase` with the exact approval text. Do not manually click final purchase buttons through browser automation unless the service endpoint is unavailable and the user explicitly approves that fallback in the same chat.
- Stop if the visible total, address, items, payment method, delivery estimate, or checkout state differs materially from the summary the user approved.
- Stop and ask for manual intervention if Rappi shows login, captcha, 2FA, age verification, alcohol, tobacco, prescription medication, identity validation, payment changes, address changes, or other sensitive screens.
- Do not modify saved addresses, payment methods, phone, ID, or personal data unless the user explicitly asked for that exact change.
- If the user gave a budget and the visible total/subtotal exceeds it, stop and ask.
- If there is important ambiguity before touching the cart, ask one concise question first.
- Do not use Rappi private/internal APIs or attempt to bypass anti-fraud, captchas, validation, or limits.
## Workflow
1. Parse the request into:
- `category`: `restaurant`, `grocery`, `pharmacy`, `convenience`, or `unknown`.
- `items`: names, quantities, notes.
- `preferences`: budget, dietary preferences, preferred store, address hint, substitution policy.
- If the user explicitly asks to “dejar listo para pagar”, “llevar hasta checkout”, “hasta el final”, or equivalent, set `handoffTarget: "checkout"`. Otherwise use `handoffTarget: "cart"`.
- `safety`: always `{ "requireHumanFinalCheckout": true, "restrictedItemsAllowed": false }`.
2. Create draft with `POST /drafts`.
3. Poll `GET /drafts/:id` occasionally until status is `cart_ready`, `checkout_ready`, `needs_user_input`, `blocked`, or `failed`.
4. Summarize:
- store/restaurant
- products and quantities
- missing items
- substitutions
- visible subtotal/shipping/total
- visible delivery address
- payment method label/last digits when visible
- delivery estimate
- warnings
5. If `handoffTarget` is `cart`, ask whether to prepare checkout for review.
6. If the user wants checkout prepared, call `POST /drafts/:id/prepare-checkout`, then poll again.
7. If the user wants the purchase completed, show the checkout summary and request approval.
8. In Telegram, use:
```json
{
"action": "send",
"channel": "telegram",
"target": "telegram:<chat-id>",
"message": "<checkout summary>\n\nAPRUEBO COMPRA RAPPI <draftId>",
"buttons": [[{"text":"Aprobar compra","callback_data":"APRUEBO COMPRA RAPPI <draftId>","style":"success"}]]
}
```
If using `message action=send` for the user-visible approval request, reply with `NO_REPLY` in the main assistant response to avoid duplicate messages.
9. Only after the exact approval phrase appears in the current chat or button callback, call:
```bash
curl -X POST http://127.0.0.1:4777/drafts/<draftId>/confirm-purchase \
-H 'Content-Type: application/json' \
-d '{"approvalText":"APRUEBO COMPRA RAPPI <draftId>","approvedBy":"user"}'
```
10. Report success/blocker immediately. Never fabricate order confirmation; if Rappi status is unclear, say so.
## API reference
- `GET /health`
- `GET /capabilities`
- `POST /drafts`
- `POST /drafts/adopt-checkout` — advanced recovery endpoint for adopting a currently visible checkout screen into a new draft; use only when the service lost draft state but Rappi is already at checkout.
- `GET /drafts/:id`
- `POST /drafts/:id/prepare-checkout`
- `POST /drafts/:id/confirm-purchase`
- `POST /drafts/:id/cancel`
Example `POST /drafts` body:
```json
{
"requestText": "Quiero algo saludable por menos de 80 mil",
"category": "restaurant",
"items": [
{ "name": "algo saludable", "quantity": 1, "notes": "máximo 80000 COP" }
],
"preferences": {
"budgetMax": 80000,
"dietary": [],
"allowSubstitutions": false,
"handoffTarget": "cart"
},
"safety": {
"requireHumanFinalCheckout": true,
"restrictedItemsAllowed": false
}
}
```
don't have the plugin yet? install it then click "run inline in claude" again.
extracted implicit decision logic (health check failures, Chrome unavailability, ambiguous requests, budget overages, approval mismatches, checkout discrepancies) into explicit if-else decision points; documented all inputs (service endpoint, Chrome setup, user context, Telegram integration); formalized 10-step procedure with clear input/output contracts for each step; added edge cases (timeouts, rate limits, sensitive screens, manual recovery); preserved original safety rules and approval workflow unchanged.
assisted rappi ordering through a local HTTP service. use this when the user asks to order food, groceries, pharmacy, convenience items, lunch, snacks, household basics, or anything "por Rappi". the skill structures the request, creates a cart draft in visible Chrome, summarizes cart/checkout, prepares review handoff, sends a native approval button when available, and submits the final purchase only after exact explicit approval in the current chat.
use this skill to help users place Rappi orders (food, groceries, pharmacy, convenience, household items) by building a cart draft through the local openclaw-rappi service, summarizing items/price/address/delivery estimate, and submitting only after the user gives exact written approval. the skill enforces a hard safety boundary: no final purchase without explicit per-order approval in the current conversation. use this when a user says "order me lunch", "buy groceries on Rappi", "get pharmacy items", or any variant of requesting delivery/commerce through Rappi.
local service endpoint:
OPENCLAW_RAPPI_SERVICE_URL (env var, default: http://127.0.0.1:4777)GET /healthchrome/browser automation:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222)https://www.rappi.com.co/ with saved address/payment (optional but recommended)https://github.com/zarruk/openclaw-rappi.git into $HOME/.openclaw/tools/openclaw-rappi and start service locallyuser input / context:
restaurant, grocery, pharmacy, convenience, or unknowncart (user reviews before checkout) or checkout (user reviews at checkout screen)chat channel context (Telegram-specific):
health check
GET /health against the service endpointGET /health after bootstrap; if still down, report exact stderr and stopparse user request into structured order
restaurant, grocery, pharmacy, convenience, or unknown)allowSubstitutions: true/false)handoffTarget: "checkout"; otherwise handoffTarget: "cart"{ "requireHumanFinalCheckout": true, "restrictedItemsAllowed": false }create draft
POST /drafts with body:{
"requestText": "<user's full request>",
"category": "<parsed category>",
"items": [{"name": "<item>", "quantity": <n>, "notes": "<notes>"}],
"preferences": {
"budgetMax": <number or null>,
"dietary": [<array of strings>],
"allowSubstitutions": <bool>,
"handoffTarget": "<cart|checkout>"
},
"safety": {
"requireHumanFinalCheckout": true,
"restrictedItemsAllowed": false
}
}
draftIdpoll draft status
GET /drafts/:id every 2-3 seconds until status reaches cart_ready, checkout_ready, needs_user_input, blocked, or failedsummarize cart
cart_ready or checkout_ready, extract and display:offer checkout preparation (if handoffTarget is "cart")
7a. prepare checkout (if requested or if handoffTarget is "checkout")
POST /drafts/:id/prepare-checkoutGET /drafts/:id until status is checkout_ready or blocked7b. request approval
APRUEBO COMPRA RAPPI <draftId> as a fallback line in message bodyreceive and validate approval
APRUEBO COMPRA RAPPI <draftId> exactlyAPRUEBO COMPRA RAPPI <draftId> OR message text contains that exact phrase as a standalone line or sentenceconfirm purchase
POST /drafts/:id/confirm-purchase with body:{
"approvalText": "APRUEBO COMPRA RAPPI <draftId>",
"approvedBy": "user"
}
GET /drafts/:id until status is purchased, failed, or blockedreport outcome
purchased: report success, confirmation number, estimated delivery time, and next stepsfailed or blocked: report the exact failure reason (payment declined, address invalid, captcha required, etc.), last visible Rappi state, and guidance on manual recoveryif service is unavailable on startup:
$HOME/.openclaw/tools/openclaw-rappi/logs/ or manually start the serviceif Chrome remote debugging is unavailable:
mkdir -p "$HOME/.openclaw/rappi-chrome-profile"
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir="$HOME/.openclaw/rappi-chrome-profile" \
--no-first-run --no-default-browser-check \
https://www.rappi.com.co/
if draft creation fails (POST /drafts returns error):
GET /health)if polling times out (status never reaches terminal state):
POST /drafts/adopt-checkout if already at checkoutif draft status is "blocked":
adopt-checkoutif draft status is "needs_user_input":
if user's request is ambiguous:
if visible total exceeds user's stated budget:
if user provides approval text but it differs from the required exact phrase:
APRUEBO COMPRA RAPPI <draftId>if checkout summary differs materially from the summary the user approved:
if service endpoint is available but returns a 5xx error during confirm-purchase:
POST /drafts/:id/confirm-purchase once more, then report outcomeif user asks to modify the order after cart is ready:
cart_ready status, ask what to change and return to step 2 (re-parse and create a new draft)checkout_ready or pending approval, ask user to cancel this draft and start a new order requestsuccessful flow outputs:
draftId (string): unique identifier for this order draftcartSummary (markdown): store name, items with quantities, subtotal, shipping, total, address, delivery estimate, payment method labelcheckoutSummary (markdown): same as cartSummary, used at final approval stageAPRUEBO COMPRA RAPPI <draftId>purchased, estimated delivery time, and optional confirmation number from Rappiblocked/failed flow outputs:
blocked, failed, timeout)data locations:
$HOME/.openclaw/tools/openclaw-rappi/logs/service.out.log, service.err.log$HOME/.openclaw/rappi-chrome-profilethe user knows the skill worked when:
the user knows the skill failed when:
purchased)