Overview
This guide will walk you through using the Clawdot Gateway to build a complete local life Agent from scratch. By following best practices and handling edge cases, you will be able to create a robust, user-friendly application. The Gateway exposes its capabilities as MCP (Model Context Protocol) tools — once you connect, you see 24 tools and chain them, from binding/consent through finding shops and picking items, all the way to preview, order, and signing. Every example below is given as a tool name + JSON arguments (every business tool carriesconsent_grant_id, except the binding tools).
Architecture Design
A complete local life Agent consists of the following modules:The delivery gateway exposes 24 MCP tools over Streamable HTTP, covering the full local-life flow from binding/consent to ordering and payment. The connection, grouping, and ordering sequence of the tools are in the MCP Overview.
Step 1: Get API Key and Connect to MCP
1
Create an Agent in the console
Visit Clawdot Console, create an Agent and enable the delivery capability for it. Agents and API Keys are both managed in the console.
2
Copy API Key
System generates an API Key (starting with
clw_), displayed only once — immediately copy and save to a secure location. The server only stores a hash; if lost, you must regenerate it.3
Configure the API Key in your MCP client
The gateway serves MCP over Streamable HTTP (FastMCP), with the endpoint
https://eleme-gateway.hicaspian.com/mcp/v1. Put the API Key into your MCP client’s connection headers:The API Key identifies the Agent, passed at the connection layer via the
Authorization: Bearer clw_... header — required on every MCP request. To act on user resources, you also need the user consent grant obtained in the next step, which is passed as the consent_grant_id tool argument (not a header). See Authentication.Step 2: Get User Consent
Acting on user resources (search shops, place orders, query addresses, etc.) requires two-layer authentication: the connection-layer API Key identifies the Agent, and the user consent grant identifies the authorized delivery user. After a user completes a binding flow once, you get aconsent_grant_id (prefixed cg_) and pass it as an argument on every subsequent business tool call.
Binding supports two modes: sms (sends a verification code to the phone) and h5 (returns an authorization link the user logs in through). The binding tools request_user_bind / verify_user_bind are the entry point for obtaining consent — they only need the Agent identity (connection-layer API Key) and take no consent_grant_id. The example below uses sms.
Binding Flow
First, initiate binding; the gateway sends a verification code to the user’s phone:consent_grant_id:
consent_grant_id, keep it safe — its plaintext is returned only once and only a hash is stored. Pass it as an argument on every subsequent business tool call.
H5 mode is also supported:
request_user_bind(auth_type="h5") returns an h5_url (valid for ~300s); hand the link to the user to open and authorize. Then poll with verify_user_bind(auth_type="h5", request_id=...) — pending means not yet done, and bound=true returns the consent_grant_id. You may also pass callback_url to request_user_bind, and the gateway will POST a callback (event=user_bind) once authorization completes. Full fields in Initiate Binding and Confirm Binding.The
expires_at returned on success is the consent expiry (ISO 8601). Re-authorization rotates the grant: each successful binding for the same user mints a new consent_grant_id and immediately invalidates the old one. Consent can be revoked any time via revoke_user_bind, after which the old consent_grant_id is invalidated immediately.Step 3: Core Business Flow
Implement the complete chain from preparing the delivery address, finding shops and picking items, quoting, previewing, to placing the order. The whole chain is stateful: each step’s returned ID must be passed verbatim to the next — never fabricate one or mix IDs across chains. Prepare the delivery address first, then search deliverable shops by that address, so downstream tools all get the delivery coordinates.Password-free payment signing is an account-level, one-time prerequisite (see “Password-Free Payment Signing” below); it is not part of any single order’s chain and is not bound to a specific order — do not treat it as a step in the order chain.
consent_grant_id argument (from Step 2).
Phase 1: Prepare Delivery Address
First pin down “where to deliver”. The address flow = search POIs for a single-usetoken → register for an address_id. First search addresses:
saved_addresses[] are already-saved addresses whose address_id can be reused directly; for a new address, take a suggestions[].token and pass it as select_address’s suggestion_token to register it:
select_address directly with an existing address’s address_id. This address_id is used both to search shops next and for the later quote / preview. See Search Addresses and Select/Register Address; edit door number / label with update_address (the address_id stays the same).
Phase 2: Search Shops
address_id from the previous step to search deliverable shops. Without keyword it is browse mode (up to 20 shops near that address) with distance, rating, delivery fee, min-order and other decision fields; with keyword (shop name / category / item name) it is precise search (~5 shops). Browse mode accepts offset for paging: pass offset: 0 first, keep paging with the returned next_offset until shops is empty.
Each result carries a shop_id and a cart_id: the cart_id already encapsulates that shop plus the delivery coordinates, and is the entry point for the later get_shop_menu / quote_cart / preview_order — pass it verbatim, so downstream tools need not pass coordinates. Full fields in Search Shops.
Phase 3: View Menu Details
keyword or limit / offset for progressive disclosure and check has_more for more. To order, you MUST use the item_id / sku_id returned by get_shop_menu (plus ingredient_option_ids for specs / add-ons). Full fields in Shop Menu; the spec / attribute / add-on system is in Item Specs.
Phase 4: Quote Cart
items is an array (NOT a JSON string); each item’s item_id / sku_id comes from get_shop_menu. can_checkout indicates whether min-order and other ordering conditions are met, and payable_price is the estimated payable (in cents). Full fields in Quote Cart.
Phase 5: Preview Order (Pre-Order Confirmation)
Always validate and show the final price with
preview_order before creating the order to avoid mistakes. The preview_id + confirmation_token it produces are the credentials required to actually place the order.preview_id + confirmation_token must be used as a pair, are produced by the same preview, and are valid for about 10 minutes.
Coupons take effect at the preview stage, and the coupons actually usable for the current order are whatever is in the returned available_coupons (coupon_ids tri-state: omitted = auto-pick best; [] = no coupon; ["<coupon_id>"] = specific coupon). To switch coupons, pick a available_coupons[].coupon_id and re-call preview_order with coupon_ids=[...] to re-price:
list_coupons, but what’s actually usable for the current order is the available_coupons from preview_order. Full fields and the coupon_ids tri-state are in Preview Order.
Phase 6: Create Order
Place the order with thepreview_id + confirmation_token from the same preview:
confirmation_token as the idempotency key: a token can place only one order; re-ordering requires a fresh preview for a new token. Returns order_id, status, and (when payment is needed) payment_action. You may pass callback_url; every status change on the order POSTs a callback (body carries order_id, seq, status; the payment-outcome one adds event=order_payment and ispay, status, etc.) — otherwise poll get_order_status yourself. Full fields in Create Order.
Step 4: Password-Free Payment Signing (Account-Level, One-Time)
Password-free signing lets the user authorize password-free payment: sign once, and later password-free orders are charged automatically. It is an account-level, one-time prerequisite that is not bound to any single order and is not done per order — so it stands apart from the order chain above. Before you need password-free payment, check withget_sign_status whether already signed, and only initiate when not:
action_type=open_h5, direct the user to action_url (the H5 sign page) to sign; once done the browser returns to return_url. none means already signed. Then poll the signing result with get_sign_status:
Step 5: Handle Edge Cases
Robust Agents gracefully handle edge cases and provide friendly error messages. Gateway errors return a uniform{"error": {"code", "message"}} structure (every MCP tool returns this shape on failure).
Error Handling
Branch onerror.code to show friendly messages:
User Consent Expiration Handling
Any business tool returningCONSENT_GRANT_INVALID / CONSENT_GRANT_EXPIRED means re-authorization is needed (or proactively compare the recorded expires_at). Just run the binding flow again — re-authorization rotates the grant, so you get a new consent_grant_id; replace the stale value in local storage with it.
Shop Closed Handling
Theavailable / unavailable_reason in search_shops browse results let you pre-check whether a shop is open. If the order chain hits a closed shop mid-way, prompt the user to choose another shop and go back to search_shops to re-select.
Order Query with Retry
get_order_status is a read-only query and is safe to retry on timeout:
get_order_status, but do not blindly retry order-creation tools — rely on the confirmation_token idempotency key to avoid duplicate orders.
Best Practices
Reuse Saved Addresses
search_addresses returns saved_addresses[]; prefer reusing their address_id instead of re-registering a new address.Progressive Menu Disclosure
Menus can have 100+ items. Use
keyword or limit / offset on get_shop_menu to page, following has_more / next_offset until done.Logging and Monitoring
Record critical tool calls (argument summaries, returned
order_id / error codes, etc.) for debugging and monitoring. Be sure to redact sensitive fields like consent_grant_id.Rate Limit Handling
Respect rate limits (create order 10/min, others 60/min, per Agent). On limit a tool returns
RATE_LIMITED; use exponential backoff.Amounts Are in Cents
All amount fields are cents (integer). Divide by 100 when showing to users — never treat cents as yuan.
payable_price: 1500 is ¥15.00.Graceful Degradation
When upstream is unavailable (
ELEME_ERROR), provide alternatives (show cached results or ask the user to retry later).The Full Chain at a Glance
Chaining the tool calls from each step above gives one complete order:address_id / shop_id / cart_id / preview_id / confirmation_token …) are issued by the gateway and must be passed verbatim — never fabricate them or mix across chains. confirmation_token is the order idempotency key, and the consent_grant_id minted during binding is the user-consent argument carried by every subsequent business tool call. Password-free payment signing (get_sign_action) is an account-level, one-time prerequisite, independent of this order chain (see Step 4).
Next Steps
- See the MCP Overview for the 24 tools’ connection, grouping, and complete inputs / outputs
- Read Order Flow to master the full stateful order chain and payment sequence
- Read Security Model to learn data protection best practices
- Explore Supported Platforms to integrate with your Agent app

