Order groceries from Zepto in seconds. Just say what you need, get a payment link on WhatsApp, pay on your phone, done. Remembers your usual items. Works across India where Zepto delivers.
Order groceries from Zepto in seconds. Just say what you need, get a payment link on WhatsApp, pay on your phone, done. Remembers your usual items. Works across India where Zepto delivers.
Ask user: "I've sent the OTP to {phone}. What's the OTP you received?"
1.4: Enter OTP
browser snapshot --interactive profile=openclaw # Get OTP input refs
browser act profile=openclaw request='{"kind":"type","ref":"{otp_input_ref}","text":"{otp}"}'# OTP auto-submits after 6 digits
Result: User is now logged in! Session persists across browser restarts.
Step 2: Address Confirmation
🚨 CRITICAL: ALWAYS CHECK ADDRESS BEFORE PROCEEDING WITH ANY SHOPPING!
Address Selection Rules
Default behavior:
Most users have multiple saved addresses (Home, Office, etc.)
ALWAYS show current address and ASK for confirmation - never assume
Check what was used in the last order (if order history exists)
Wait for explicit user confirmation before proceeding
On homepage, address is visible in the header:
browser snapshot --interactive profile=openclaw
# Look for button with heading level=3 containing the address# Example ref: e16 with text like "Home - [Address Details]..."# Delivery time shown nearby (e.g., "10 minutes")
ALWAYS ask user to confirm before shopping:
📍 I see your delivery address is set to:
{Address Name} - {Full Address}
⏱️ Delivery in ~{X} minutes
Is this correct? Should I proceed with this address?
When user says "change address to X" or "deliver to X":
# Just call the command with their address name/query
node zepto-agent.js select-address "{user_query}"
No manual modal navigation needed! The script handles:
Opening the address modal
Finding the address (fuzzy match)
Clicking it
Verifying the change
Closing the modal
Manual Selection (Fallback):
If the programmatic method fails or address isn't found:
# Click the address button (ref e16 or similar)
browser act profile=openclaw request='{"kind":"click","ref":"e16"}'# This opens address selection modal with all saved addresses
Select address using JavaScript:
# Replace {USER_ADDRESS_NAME} with the actual address name user selected
browser act profile=openclaw request='{"fn":"() => { const input = document.querySelector('input[placeholder*=\"address\"]'); if (!input) return { error: 'Modal not found' }; let modal = input; for (let i = 0; i < 15; i++) { if (!modal.parentElement) break; modal = modal.parentElement; if (window.getComputedStyle(modal).position === 'fixed') break; } const divs = Array.from(modal.querySelectorAll('div')); const match = divs.find(d => d.textContent && d.textContent.trim().startsWith('{USER_ADDRESS_NAME}')); if (!match) return { error: 'Address not found' }; let p = match; for (let i = 0; i < 10; i++) { if (!p) break; const s = window.getComputedStyle(p); if (p.onclick || p.getAttribute('onClick') || s.cursor === 'pointer') { p.scrollIntoView({ block: 'center' }); setTimeout(() => {}, 300); p.click(); return { clicked: true, text: match.textContent.substring(0, 100) }; } p = p.parentElement; } return { error: 'No clickable parent' }; }()","kind":"evaluate"}'
After address confirmed by user:
✅ Delivery address confirmed: {address_name}
📍 {full_address}
⏱️ ETA: {eta} mins
Ready to shop! What would you like to add to cart?
⚠️ Address is CRITICAL - never skip this step!
Step 3: Shopping
3A: Discovery Mode (Browse & Explore)
When user asks to "explore", "show me", "what's good", "find something", or "discover":
# Example: Browse "Munchies" category
browser navigate url=https://www.zepto.com/pn/munchies profile=openclaw
browser snapshot --interactive profile=openclaw
# Take screenshot to show user the options
browser screenshot profile=openclaw
Discovery Response Format:
🔍 Found some great options in {category}:
1. **{Product Name}** - ₹{price} ({discount}% OFF)
⭐ {rating} ({review_count} reviews)
📦 {size/quantity}
2. **{Product Name}** - ₹{price}
⭐ {rating} ({review_count} reviews)
3. **{Product Name}** - ₹{price} ({discount}% OFF)
⭐ {rating} ({review_count} reviews)
Want me to add any of these? Just tell me the number(s)!
Smart Filtering Tips:
Price range: Extract from query ("under ₹50", "below 100")
Discount focus: Look for items with ₹X OFF tags
High ratings: Prioritize 4.5+ star products
Popular items: Sort by review count (k = thousands)
Health focus: Keywords like "protein", "sugar-free", "organic", "millet"
Interactive Discovery:
After showing options, user can:
Add by number: "Add 1 and 3"
Ask for more: "Show me more"
Refine: "Show cheaper options" or "What about chocolate flavors?"
Browse different category: "Now show me dairy products"
3B: Direct Search (Specific Items)
MANDATORY PRE-FLIGHT CHECK:
Before adding ANY items:
Click cart button
Read current cart contents
If cart has items: Ask user "Keep existing items or clear cart first?"
If empty: Proceed to shopping
Multi-Item Shopping Flow:
When user gives a list (e.g., "add milk, butter, bread"):
Add items ONE AT A TIME with verification:
Search for item
Click ADD button
Wait 0.5s for page update
VERIFY item shows quantity controls (means it's in cart)
If verification fails: Retry up to 3 times
Then show final cart summary with all items and total
CRITICAL: Never batch-add without verification! Page refs change after each add.
Item Selection Logic:
Check order-history.json first
If item ordered 2+ times → auto-select that variant
If item ordered 0-1 times or multiple unclear variants → show options and ASK
Pick closest match to user's request (e.g., "Yakult Light" when they said "light")
Use highest review count as tiebreaker
When UNCLEAR about variant:
🥛 Found multiple milk options:
1. Amul Taaza (500ml) - ₹29 ⭐ 4.8 (100k)
2. Amul Gold (1L) - ₹68 ⭐ 4.9 (80k)
3. Mother Dairy (500ml) - ₹30 ⭐ 4.7 (60k)
Which one? (or tell me a number)
🛒 Added to cart:
1. Item 1 - ₹XX
2. Item 2 - ₹YY
3. Item 3 - ₹ZZ
💰 Total: ₹{total}
Ready to checkout? (say "yes" or "checkout" or "lessgo")
CRITICAL - Quantity Mapping:
When user provides a shopping list with quantities (e.g., "3x jeera, 2x saffola oats"):
ALWAYS create a mapping file FIRST before any cart operations
Map each item name to its requested quantity
Before removing/modifying items, verify against this mapping
Never assume which item has which quantity - CHECK THE MAPPING
Example mapping:
{"jeera":3,"saffola_oats":2,"milk":1}
Before removing duplicates or adjusting quantities:
Take a cart snapshot
Match cart items to your mapping by name similarity
Verify quantities match the original request
If unsure, ASK the user before making changes
Error Handling - Out of Stock
If item not found or out of stock:
❌ {item} is currently unavailable.
🔍 Suggestions:
- {similar_item_1}
- {similar_item_2}
What would you like instead?
Don't auto-add alternatives - wait for user's next item or choice.
Step 4: Generate Payment Link
After all items added to cart and user confirms checkout:
4.1: Open Cart and Proceed to Payment
# Open cart modal
browser act profile=openclaw request='{"kind":"click","ref":"{cart_button_ref}"}'# Example ref from homepage: e44# Wait for cart to open, take snapshot
browser snapshot --interactive profile=openclaw
# Click "Click to Pay ₹{amount}" button
browser act profile=openclaw request='{"kind":"click","ref":"{click_to_pay_button_ref}"}'# Example ref: e3579
4.2: Extract Juspay Link
# Wait 2 seconds for navigation to complete
browser act profile=openclaw request='{"fn":"async () => { await new Promise(r => setTimeout(r, 2000)); return window.location.href; }","kind":"evaluate"}'
message action=send channel=whatsapp target={user_phone} message="🛒 *Your Zepto order is ready!*
*Cart Summary ({item_count} items):*
1. {item1} - ₹{price1}
2. {item2} - ₹{price2}
3. {item3} - ₹{price3}
*💰 Total: ₹{total}*
📍 Delivering to: {address_name} - {address}
⏱️ ETA: {eta} minutes
*🔗 Click here to pay:*
{juspay_payment_link}
⚠️ *IMPORTANT: After payment, message me \"DONE\" to confirm your order!*
(Don't rely on the payment page - just tell me when you've paid and I'll verify it) 🚀"
4.4: Wait for User "Done" Message & Verify Order
After user says "done" or "paid":
Step 1: Navigate to Zepto homepage to check order status
Step 2: Look for order confirmation
Check for text like:
"Your order is on the way"
"Order confirmed"
"Preparing your order"
"Arriving in X mins"
Track order button/link
Step 3: Auto-clear cart (Post-Payment Behavior)
🚨 CRITICAL: After payment, cart items persist because Zepto hasn't synced yet!
Automatically clear cart without asking (user expects cart to be empty after payment):
# Open cart
browser act profile=openclaw request='{"kind":"click","ref":"{cart_button_ref}"}'
browser snapshot --interactive profile=openclaw
# Click Remove button for each item
browser act profile=openclaw request='{"kind":"click","ref":"{remove_button_ref_1}"}'
browser act profile=openclaw request='{"kind":"click","ref":"{remove_button_ref_2}"}'
browser act profile=openclaw request='{"kind":"click","ref":"{remove_button_ref_3}"}'# ... repeat for all items
Step 4: Confirm to user
If order confirmed:
✅ *Payment confirmed!*
🚚 Your order is on the way! Arriving in ~{X} mins.
Order details:
- {item_count} items, ₹{total}
- Delivery to: {address}
✅ Cart cleared ({item_count} items removed from previous order)
🛒 Ready for your next order! 🐺
If order NOT showing yet:
⏳ Payment processed, but order confirmation is still loading on Zepto's end.
Let me check again in 30 seconds...
🚨 CRITICAL: Cart items may still be there because Zepto hasn't synced order confirmation yet!
Step 4: Ask user about clearing cart
✅ Payment confirmed! Your order is on the way.
⚠️ I can see {X} items still in the cart (from the previous order that just went through).
Should I:
1. Clear the cart (recommended for fresh start)
2. Keep the items (if you want to reorder them)
*Default: I'll clear the cart unless you say "keep it"*
Step 5: Clear cart if user approves (or by default)
# For each item in cart, click Remove button
browser act profile=openclaw request='{"kind":"click","ref":"{remove_button_ref_1}"}'
browser act profile=openclaw request='{"kind":"click","ref":"{remove_button_ref_2}"}'# ... repeat for all items# Or use JavaScript to clear all at once:
browser act profile=openclaw request='{"fn":"() => { const removeButtons = document.querySelectorAll(\"button\"); let count = 0; for (let btn of removeButtons) { if (btn.textContent.trim() === \"Remove\") { btn.click(); count++; } } return `Removed ${count} items`; }","kind":"evaluate"}'
Confirmation message:
✅ Cart cleared! ({X} items removed)
🛒 Ready for your next order!
Your current order ({item_count} items, ₹{total}) will arrive in ~{eta} mins.
If user says "keep it":
✅ Got it! Keeping {X} items in cart.
🛒 Ready to add more items or proceed with these?
Going to cart manually and clicking "Pay"
Let me know if you need me to try again
**If delivery address becomes unserviceable:**
⚠️ Your delivery address is currently unserviceable.
Should I order it to a different address?
(I can show you all your saved addresses)
---
## 🎯 Complete Order Flow Summary
### Before Starting ANY New Order (Normal Flow - No Recent Payment):
**1. Check Address (ALWAYS)**
2. Look for "Your order is on the way" or "Arriving in X mins"
3. Open cart and AUTO-CLEAR without asking
# Open cart
browser act profile=openclaw request='{"kind":"click","ref":"{cart_button_ref}"}'# Remove all items (they're from the order that just went through)
browser act profile=openclaw request='{"kind":"click","ref":"{remove_ref_1}"}'
browser act profile=openclaw request='{"kind":"click","ref":"{remove_ref_2}"}'
browser act profile=openclaw request='{"kind":"click","ref":"{remove_ref_3}"}'
4. Confirm to user
✅ Payment confirmed! Your order is on the way! Arriving in ~{X} mins.
✅ Cart cleared ({item_count} items removed from previous order)
🛒 Ready for your next order!
Why auto-clear in post-payment?
User expects cart to be empty after successful order
Cart items are from the order they just paid for
Zepto hasn't synced yet, so items persist temporarily
Clearing prevents confusion and duplicate orders
Start Fresh Shopping (After Cart Cleared)
✅ Cart cleared!
✅ Address confirmed: {address}
What would you like to order? 🛒
Key Difference:
Normal flow: ASK before clearing cart (user might want those items)
Post-payment flow: AUTO-CLEAR cart (user knows those items are ordered)
Safety & Best Practices
✅ DO:
Check auth status before every order
Confirm address with user
Extract payment link accurately
Send link via WhatsApp
Let user complete payment
❌ DON'T:
Never click "Pay" button
Never store OTP
Never auto-submit payment
Never change address without user confirmation
Error Handling
Phone number invalid:
"Phone number should be 10 digits. Please try again."
OTP verification failed:
"OTP verification failed. Let me resend the OTP.
Check your phone for the new code."
Location not serviceable:
"⚠️ Your location is currently not serviceable by Zepto.
Store might be temporarily closed or location outside delivery zone.
Want to try a different address?"
Item not found:
"Couldn't find {item} on Zepto. Try a different search term?"
Session Persistence
After successful authentication:
Browser cookies persist login
No need to re-authenticate for future orders
Address selection persists
Can directly proceed to shopping
To check if authenticated:
browser navigate url=https://www.zepto.com profile=openclaw
browser snapshot --interactive profile=openclaw
# If "profile" link exists → logged in# If "login" button exists → need to auth