Products, keeps one active basket per customer with Baskets, places the order, and reports its status with Orders. It needs no external API and no keys. It is six files, and every file compiles against lua-cli 3.33.0; run it with the steps on Running any example.
Verified against lua-cli 3.33.0.
The conversation
- The customer describes what they want. The model calls
search_products, which runs a catalog search and applies an optional price cap. - The customer picks a product.
add_to_cartreuses their active basket or creates one, then adds the item; no basket id passes through the model, because baskets belong to the end user in the conversation. - The model reads the items and total back and asks for a shipping address.
checkoutplaces the order from the active basket. - Later,
track_orderreports the status of an order the customer names.
Primitives and channels
- Skill and tools:
shopping, withsearch_products,add_to_cart,checkout, andtrack_order. - Runtime objects:
Products.search,Products.getById,Baskets.get,Baskets.create,Baskets.addItem,basket.placeOrder,Orders.getById, and theBasketStatusenum. - Channels: any. Baskets and orders are scoped to the end user, so a cart started on the web widget is the same cart on WhatsApp.
The code
Products.search returns at most five matches in its products array; each product’s fields are on data.
src/skills/tools/SearchProductsTool.ts
Baskets.get(BasketStatus.ACTIVE) lists the customer’s open baskets; a BasketInstance exposes itemCount, totalAmount, and status directly and its id through toJSON().
src/skills/tools/AddToCartTool.ts
basket.placeOrder converts the active basket into an order; the order’s id is orderId on the serialized order.
src/skills/tools/CheckoutTool.ts
Orders.getById only sees the end user’s own orders.
src/skills/tools/TrackOrderTool.ts
context makes the model confirm before it calls checkout.
src/skills/shopping.skill.ts
src/index.ts
First run
No variables are needed. Run the search tool; with an empty catalog it returns no products.Output
lua chat --ci -e sandbox -m "Find me a desk lamp under $50" -t, then reuse the printed thread id with -t <thread-id> to add the lamp to the cart and check out in the same conversation. Then release it with lua push all --ci --force, lua version create --ci -m "<message>", and lua version promote <n>; Release an agent to production explains what each command changes.
Ways to make it yours
- Load the catalog in the admin dashboard, with
Products.createfrom a one-off tool, or by connecting Shopify or WooCommerce and letting the store own the cart. checkoutrecords the order; to take payment, send a payment link fromcheckoutor use the payment component.- Add
Baskets.removeItemandBaskets.clearas tools when customers need to change their mind; both take the basket id fromtoJSON(). - Send an order-shipped message from a webhook your fulfillment system calls; see Send proactive messages.
Next steps
Products reference
Search, filters, pagination, and the product shape.
Baskets reference
Statuses, items, metadata, and
placeOrder.Web widget quickstart
Put the agent on the store’s site.

