zepto
Order groceries from Zepto in 30 seconds. From chat to checkout.
Tell your AI what you need. It shops, generates a payment link, sends it to WhatsApp. You pay on your phone. Groceries arrive in 10 minutes.
💬 Examples
Quick orders:
CODEBLOCK0
Your usuals:
CODEBLOCK1
Full shopping list:
"Add milk, bread, eggs, coriander, ginger, and tea bags"
→ AI adds everything, shows total: ₹X
→ Sends payment link to WhatsApp
→ You pay, groceries arrive
🔒 Security & Privacy
What this skill does:
- - ✅ Browser automation on zepto.com (your local browser, your session)
- ✅ Stores order history locally in
~/.openclaw/skills/zepto/order-history.json (local file, not shared) - ✅ Sends payment links via WhatsApp (requires your consent for each order)
- ✅ All authentication happens through Zepto's official flow (Phone + OTP)
What this skill does NOT do:
- - ❌ No automatic payments (you must click the link and pay manually)
- ❌ No data sent to external servers (except Zepto.com and WhatsApp via your channels)
- ❌ No persistent background jobs (optional one-time order status check only if you approve)
- ❌ No storage of payment info or OTPs
- ❌ No access to your banking/UPI apps
Data Storage:
- - Order history:
~/.openclaw/skills/zepto/order-history.json (local only, helps with "usuals" feature) - Browser session: Managed by OpenClaw's browser (standard Chrome/Chromium profile)
User Control:
- - You control when to order
- You approve each payment link
- You can delete order history file anytime
- All browser actions happen in your profile with your visibility
🚨 CRITICAL WORKFLOW RULES
ALWAYS follow this order when building an order:
Rule 1: CHECK CART FIRST
CODEBLOCK3
Why: Cart may have items from previous sessions. Adding duplicates is wasteful.
Rule 2: Use smart-shop (RECOMMENDED)
CODEBLOCK4
What it does:
- 1. Checks current cart state
- Clears existing items (if any)
- For each item: checks if already in cart → skips if present → adds only if missing
- Returns: INLINECODE2
Rule 3: NEVER take screenshots unless snapshot data is insufficient
- - Snapshot shows all refs, buttons, text
- Screenshot is ONLY for visual debugging when snapshot is truncated or unclear
- In 99% of cases, snapshot is enough
Rule 4: Detect "already in cart" signals
When you see in snapshot:
CODEBLOCK5
DO NOT click "ADD" when you see these signals!
Complete Flow
- 1. Authentication - Phone + OTP verification
- Address Confirmation - Verify delivery location
- Shopping - Search & add items (with YOUR usuals prioritized!)
- Payment Link - Generate & send Juspay link via WhatsApp
Step 0: Order History & Usuals
Your order history is tracked in: INLINECODE3
(Where {SKILL_DIR} is your skill directory, typically ~/.openclaw/skills/zepto/)
Smart Selection Logic:
- 1. When user requests an item (e.g., "add milk")
- Check
order-history.json for that category - If ordered 2+ times → Auto-add your most-ordered variant
- If ordered 0-1 times → Show options and ask for selection
Automated Order History Scraper
When to run: User says "update my zepto history" or "refresh order history"
Process:
- 1. Navigate to account page
- Get all delivered order URLs
- Visit each order sequentially
- Extract items using DOM scraping
- Build frequency map
- Save to INLINECODE7
Implementation:
CODEBLOCK6
Automated scraper advantages:
- - ✅ No manual screenshot review
- ✅ Faster (visits all orders programmatically)
- ✅ Always up-to-date
- ✅ Can re-run anytime
Example:
User: "Update my Zepto order history"
Response:
"🔍 Scanning your Zepto orders...
📦 Found 6 delivered orders
🔄 Extracting items...
✅ Updated! Found:
- Coriander: 4 orders
- Milk: 3 orders
- Bread: 2 orders
- Potato: 2 orders
+ 15 other items
Your usuals are ready!"
Smart Selection Logic (Using History):
Example:
CODEBLOCK8
If only ordered once or never:
CODEBLOCK9
Update order history: After each successful order, update the JSON file with new items.
Step 1: Authentication (First Time Only)
Check if already logged in:
CODEBLOCK10
If NOT logged in, start auth flow:
1.1: Get Phone Number
Ask user: "What's your phone number for Zepto? (10 digits)"
1.2: Enter Phone & Request OTP
CODEBLOCK11
1.3: Get OTP from User
Ask user: "I've sent the OTP to {phone}. What's the OTP you received?"
1.4: Enter OTP
CODEBLOCK12
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:
- 1. 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:
CODEBLOCK13
ALWAYS ask user to confirm before shopping:
CODEBLOCK14
Programmatic Address Selection (NEW!)
Use the zepto-agent.js select-address command:
CODEBLOCK15
How it works:
- 1. Fuzzy matching - Case-insensitive, partial match supported
- "sanskar" → "Sanskar Blr" ✅
- "home" → "New Home" ✅
- "kundu" → "Kundu Blr" ✅
- 2. Already-selected detection - Skips if you're already at that address
- Verification - Confirms address change in header after click
Example:
CODEBLOCK16
When user says "change address to X" or "deliver to X":
CODEBLOCK17
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:
CODEBLOCK18
Select address using JavaScript:
CODEBLOCK19
After address confirmed by user:
CODEBLOCK20
⚠️ 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":
Common Discovery Patterns:
- - "Show me healthy snacks under ₹50"
- "What's good in dairy products?"
- "Find me something for breakfast"
- "Any deals on fruits?"
- "Discover protein bars"
Browse Categories:
CODEBLOCK21
Filter & Sort:
CODEBLOCK22
Discovery Response Format:
CODEBLOCK23
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:
- 1. 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"):
- 1. 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
- 2. 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:
CODEBLOCK24
Search Process:
CODEBLOCK25
Select Best Product
Rule: Pick product with highest review count (unless order history says otherwise).
Format: {rating} ({count}) where k=thousand, M=million.
Example: "4.8 (694.4k)" = 694,400 reviews = most popular.
Add to Cart
CODEBLOCK26
View Cart Summary (ALWAYS show after adding all items)
CODEBLOCK27
Cart Summary Format:
CODEBLOCK28
CRITICAL - Quantity Mapping:
When user provides a shopping list with quantities (e.g., "3x jeera, 2x saffola oats"):
- 1. 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:
CODEBLOCK29
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:
CODEBLOCK30
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
CODEBLOCK31
4.2: Extract Juspay Link
CODEBLOCK32
URL Format:
CODEBLOCK33
Example:
CODEBLOCK34
4.3: Send Link via WhatsApp
CODEBLOCK35
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
CODEBLOCK36
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):
CODEBLOCK37
Step 4: Confirm to user
If order confirmed:
CODEBLOCK38
If order NOT showing yet:
CODEBLOCK39
Then set up a background check to try again.
Step 1: Navigate back to Zepto homepage
CODEBLOCK40
Step 2: Check order status on homepage
CODEBLOCK41
Step 3: Open cart and check items
CODEBLOCK42
🚨 CRITICAL: Cart items may still be there because Zepto hasn't synced order confirmation yet!
Step 4: Ask user about clearing cart
CODEBLOCK43
Step 5: Clear cart if user approves (or by default)
CODEBLOCK44
Confirmation message:
CODEBLOCK45
If user says "keep it":
✅ Got it! Keeping {X} items in cart.
🛒 Ready to add more items or proceed with these?
- 2. 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)**
📍 Current address: {address}
Is this correct?
**2. Check Cart (if items exist)**
bash
Open cart
browser act profile=openclaw request='{"kind":"click","ref":"{cart
buttonref}"}'
browser snapshot --interactive profile=openclaw
**If items in cart from NORMAL browsing (not post-payment):**
⚠️ I see {X} items in your cart:
- 1. {item1} - ₹{price1}
- {item2} - ₹{price2}
Should I:
- 1. Clear the cart
- Keep these items
What would you like?
**Wait for user response before proceeding.**
---
### Post-Payment Behavior (After User Says "Done" or "Paid"):
**This is DIFFERENT from normal flow - auto-clear expected!**
**1. Navigate to zepto.com and check order status**
bash
browser navigate url=https://www.zepto.com profile=openclaw
browser snapshot --interactive profile=openclaw
**2. Look for "Your order is on the way" or "Arriving in X mins"**
**3. Open cart and AUTO-CLEAR without asking**
bash
Open cart
browser act profile=openclaw request='{"kind":"click","ref":"{cart
buttonref}"}'
Remove all items (they're from the order that just went through)
browser act profile=openclaw request='{"kind":"click","ref":"{remove
ref1}"}'
browser act profile=openclaw request='{"kind":"click","ref":"{remove
ref2}"}'
browser act profile=openclaw request='{"kind":"click","ref":"{remove
ref3}"}'
**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:**
bash
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
```
zepto
30秒内从Zepto订购杂货。从聊天到结账。
告诉你的AI你需要什么。它会购物,生成支付链接,发送到WhatsApp。你在手机上支付。杂货10分钟内送达。
💬 示例
快速下单:
从Zepto订购牛奶和面包
添加蔬菜 - 西红柿、洋葱、土豆
给我买Amul黄油和奶酪
你的常购品:
添加我常买的牛奶 → AI选择你常订购的品牌
订购常购杂货 → AI推荐你的频繁购买商品
完整购物清单:
添加牛奶、面包、鸡蛋、香菜、生姜和茶包
→ AI添加所有商品,显示总计:₹X
→ 通过WhatsApp发送支付链接
→ 你支付,杂货送达
🔒 安全与隐私
此技能的功能:
- - ✅ 在zepto.com上进行浏览器自动化(你的本地浏览器,你的会话)
- ✅ 在本地存储订单历史记录 ~/.openclaw/skills/zepto/order-history.json(本地文件,不共享)
- ✅ 通过WhatsApp发送支付链接(每次下单需征得你的同意)
- ✅ 所有身份验证均通过Zepto的官方流程(手机号+验证码)
此技能不执行的操作:
- - ❌ 无自动支付(你必须点击链接并手动支付)
- ❌ 无数据发送到外部服务器(除了通过你的渠道访问Zepto.com和WhatsApp)
- ❌ 无持久后台任务(仅在你批准的情况下进行一次性订单状态检查)
- ❌ 不存储支付信息或验证码
- ❌ 无法访问你的银行/UPI应用
数据存储:
- - 订单历史记录:~/.openclaw/skills/zepto/order-history.json(仅本地,有助于常购品功能)
- 浏览器会话:由OpenClaw的浏览器管理(标准Chrome/Chromium配置文件)
用户控制:
- - 你控制何时下单
- 你批准每个支付链接
- 你可以随时删除订单历史记录文件
- 所有浏览器操作都在你的配置文件中进行,你可见
🚨 关键工作流规则
构建订单时始终遵循此顺序:
规则1:先检查购物车
bash
在添加任何商品之前,始终检查购物车状态
node zepto-agent.js get-cart
原因: 购物车可能包含之前会话中的商品。重复添加是浪费的。
规则2:使用智能购物(推荐)
bash
这处理一切:清除不需要的,检查重复项,添加缺失项
node zepto-agent.js smart-shop 牛奶, 面包, 鸡蛋
功能:
- 1. 检查当前购物车状态
- 清除现有商品(如果有)
- 对于每个商品:检查是否已在购物车中 → 如果存在则跳过 → 仅在缺失时添加
- 返回:{ added: [], skipped: [], failed: [] }
规则3:除非快照数据不足,否则绝不截屏
- - 快照显示所有引用、按钮、文本
- 截屏仅用于快照被截断或不清晰时的视觉调试
- 在99%的情况下,快照就足够了
规则4:检测已在购物车中的信号
当你在快照中看到:
减少数量 1 增加数量 → 商品在购物车中
按钮 移除 [ref=eXX] → 商品在购物车中
不要在看到这些信号时点击添加!
完整流程
- 1. 身份验证 - 手机号+验证码验证
- 地址确认 - 验证配送位置
- 购物 - 搜索并添加商品(优先选择你的常购品!)
- 支付链接 - 生成并通过WhatsApp发送Juspay链接
步骤0:订单历史记录与常购品
你的订单历史记录保存在: {SKILL_DIR}/order-history.json
(其中 {SKILL_DIR} 是你的技能目录,通常是 ~/.openclaw/skills/zepto/)
智能选择逻辑:
- 1. 当用户请求某个商品时(例如,添加牛奶)
- 检查 order-history.json 中该类别
- 如果订购过2次以上 → 自动添加你最常订购的变体
- 如果订购过0-1次 → 显示选项并询问选择
自动订单历史记录抓取器
何时运行: 用户说更新我的zepto历史记录或刷新订单历史记录
流程:
- 1. 导航到账户页面
- 获取所有已配送的订单URL
- 依次访问每个订单
- 使用DOM抓取提取商品
- 构建频率映射
- 保存到 order-history.json
实现:
bash
步骤1:导航到账户页面
browser navigate url=https://www.zepto.com/account profile=openclaw
步骤2:提取订单URL
browser act profile=openclaw request={fn:() => { const orders = []; document.querySelectorAll(\a[href*=\\\/order/\\\]\).forEach(link => { if (link.href.includes(\isArchived=false\) && link.textContent.includes(\delivered\)) { orders.push(link.href); } }); return [...new Set(orders)]; }, kind:evaluate}
返回订单URL数组
步骤3:对于每个订单URL:
browser navigate url={order_url} profile=openclaw
步骤4:从订单页面提取商品
browser act profile=openclaw request={fn:() => { const items = []; document.querySelectorAll(\
\).forEach(el => { const text = el.textContent; if (text.match(/\\d+\\sunit/i)) { const parent = el.closest(\div\); if (parent) { const lines = parent.textContent.split(\\\n\).map(l => l.trim()).filter(l => l && l.length > 5 && l.length < 100); if (lines[0]) { const qtyMatch = text.match(/(\\d+)\\s*unit/i); items.push({ name: lines[0], quantity: qtyMatch ? parseInt(qtyMatch[1]) : 1 }); } } } }); const uniqueItems = {}; items.forEach(item => { if (!uniqueItems[item.name]) uniqueItems[item.name] = item; }); return Object.values(uniqueItems); }, kind:evaluate}
返回 {name, quantity} 数组
步骤5:将所有商品聚合到频率映射中
构建包含计数的JSON结构
步骤6:写入文件
write path={SKILL
DIR}/order-history.json content={jsondata}
自动抓取器的优势:
- - ✅ 无需手动查看截图
- ✅ 更快(以编程方式访问所有订单)
- ✅ 始终保持最新
- ✅ 可随时重新运行
示例:
用户:更新我的Zepto订单历史记录
响应:
🔍 正在扫描你的Zepto订单...
📦 找到6个已配送订单
🔄 正在提取商品...
✅ 已更新!找到:
- 香菜:4次订单
- 牛奶:3次订单
- 面包:2次订单
- 土豆:2次订单
+ 其他15个商品
你的常购品已就绪!
智能选择逻辑(使用历史记录):
示例:
用户:添加牛奶
[检查 order-history.json]
→ Amul Taaza Toned Fresh Milk | Pouch (500ml) 订购过3次
响应:
🥛 正在添加你的常购牛奶!
Amul Taaza Toned Fresh Milk (500ml) - ₹29
📊 你已订购此商品3次
✅ 已添加到购物车
如果只订购过一次或从未订购过:
用户:添加牛奶
[检查 order-history.json]
→ Amul Taaza 仅订购过1次
响应:
🥛 找到一些牛奶选项:
- 1. Amul Taaza Toned (500ml) - ₹29 ⭐ 4.8 (100k) - 你订购过此商品一次
- Amul Gold (1L) - ₹68 ⭐ 4.9 (80k) - 最受欢迎
- Mother Dairy (500ml) - ₹30 ⭐ 4.7 (60k)
选哪个?(或告诉我一个数字)
更新订单历史记录: 每次成功下单后,用新商品更新JSON文件。
步骤1:身份验证(仅首次)
检查是否已登录:
bash
browser open url=https://www.zepto.com profile=openclaw
b