Shop autonomously on Amazon via Moltpho - search products, manage credit, and purchase items using mUSD on Base mainnet
---
name: moltpho
description: Shop autonomously on Amazon via Moltpho - search products, manage credit, and purchase items using mUSD on Base mainnet
metadata: {"requires": {"http": true, "browser": true}}
---
# Moltpho Shopping Skill
Shop for items on Amazon autonomously using credit-backed mUSD tokens on Base mainnet.
## Overview
Moltpho is a headless shopping mall that enables AI agents to discover and purchase Amazon products using a credit system backed by mUSD (an ERC-20 token on Base mainnet). This skill handles:
- Agent registration and credential management
- Product search and discovery
- Autonomous and proactive purchasing
- Credit balance monitoring
- x402 payment protocol integration
## Bootstrap Flow
On first invocation, the skill MUST check for existing credentials and register if needed.
### Credentials Location
| Platform | Path |
|----------|------|
| Linux/macOS | `~/.config/moltpho/credentials.json` |
| Windows | `%APPDATA%\moltpho\credentials.json` |
| Override | `MOLTPHO_CREDENTIALS_PATH` environment variable |
### Registration Process
1. **Check credentials file** at the appropriate path
2. **If missing**, call `POST /v1/agents/register` with:
- `openclaw_instance_id` (if available)
- `agent_display_name`
- `agent_description`
- No shipping profile required at registration
3. **Save credentials** with `chmod 600` permissions
4. **Auto-open browser** with notice: "Opening portal in your browser to complete setup..."
5. Registration proceeds WITHOUT shipping profile - orders will fail until owner adds one via portal
### Credentials File Format
```json
{
"agent_id": "uuid",
"api_key_id": "moltpho_key_...",
"api_key_secret": "moltpho_secret_...",
"api_base_url": "https://api.moltpho.com",
"wallet_address": "0xabc123..."
}
```
## Core Functions
### bootstrap()
Initialize agent credentials and open portal for owner setup.
```
1. Check if credentials file exists at platform-specific path
2. If exists and valid: load credentials, verify with GET /v1/agents/me
3. If missing or invalid:
a. Call POST /v1/agents/register (no auth required)
b. Receive: agent_id, api_key_id, api_key_secret, claim_url, wallet_address
c. Write credentials file with chmod 600
d. Display: "Opening portal in your browser to complete setup..."
e. Open browser to claim_url (valid for 24 hours)
4. Return agent status (UNCLAIMED, CLAIMED, DEGRADED, SUSPENDED)
```
### collect_shipping_profile()
Optionally collect shipping information from the owner.
```
Note: This is OPTIONAL. Owners can configure shipping via the portal instead.
Orders will fail with INVALID_SHIPPING_PROFILE until a profile exists.
If collecting in conversation:
1. Request full name
2. Request address (street, city, state, ZIP)
3. Request email
4. Request phone
5. Validate: US addresses only (international not supported in v1)
6. Call POST /v1/shipping_profiles (upsert_shipping_profile)
7. Confirm profile saved
The POST endpoint upserts the default profile:
- If no profile exists, creates one
- If a profile exists, updates it
```
### update_shipping_profile()
Update the shipping address for the agent.
```
Parameters:
- full_name: Recipient full name
- address1: Street address
- address2: Apt/suite (optional)
- city: City
- state: State (2-letter code)
- postal_code: ZIP code
- email: Contact email
- phone: Contact phone
Process:
1. Validate all required fields
2. Validate US address (only US supported in v1)
3. Call POST /v1/shipping_profiles (upserts default profile)
4. Return updated profile
Use cases:
- "Update my shipping address"
- "Change my delivery address to..."
- First-time setup during bootstrap
```
### catalog_search(query, constraints)
Search for products on Amazon via Moltpho.
```
Parameters:
- query: Search terms (string)
- constraints: Optional filters
- max_price: Maximum price in USD
- category: Product category keyword
- min_rating: Minimum star rating (1-5)
Process:
1. Call GET /v1/catalog/search?query={query}&limit=20
2. Apply local constraints if provided
3. Present results with:
- Product title and brand
- Moltpho price (final price, includes 10% markup)
- Availability status
- Rating if available
4. If cache expired, results include "prices may have changed" warning
Rate limit: 60 requests/minute
```
### purchase(item, qty)
Execute a purchase through the x402 payment flow.
```
Parameters:
- item: ASIN or product identifier
- qty: Quantity (default 1)
Process:
1. BUDGET CHECK: Call GET /v1/balance to verify available credit
- available_credit = balance - active_reservations
- Check against per_order_cap if set
- Check against daily_cap if set
2. CREATE QUOTE: Call POST /v1/quotes
- Include: asin, quantity, shipping_profile_id
- Returns: quote_id, total_due_usd, expires_at (10 min TTL)
- Creates soft reservation against balance
- May fail with INVALID_SHIPPING_PROFILE if no profile set
3. INITIATE ORDER: Call POST /v1/orders with quote_id
- First call returns 402 Payment Required with PAYMENT-REQUIRED header
4. SIGN PAYMENT: Call POST /v1/wallets/x402/sign
- Include: payment_required blob, idempotency_key
- Returns: payment_signature for x402 header
5. COMPLETE ORDER: Retry POST /v1/orders with PAYMENT-SIGNATURE header
- On success: returns order_id, status (PAID/PLACED)
- Soft reservation converted to actual spend
Auto-retry on quote expiry:
- If quote expires during flow, automatically retry up to 3 times
- Only retry if new price is within 5% of original quote
- Fail after 3 retries or if price changed >5%
Rate limits:
- Quotes: 20/minute
- Orders: 5/minute
- Signing: 10/minute
```
### proactive_monitoring()
Watch conversation for purchase need signals and act when appropriate.
```
This function runs passively during conversation to detect purchase opportunities.
NEED SIGNALS (explicit):
- "I need", "we're out of", "buy", "order", "replace"
- "running low on", "almost out of"
- Direct product mentions with urgency
NEED SIGNALS (implicit):
- Repeated complaints about missing items
- Critical item shortages mentioned
- Context suggesting immediate need
CONFIDENCE SCORING:
- 1.0: Explicit purchase request ("buy me X")
- 0.8: Strong implied need ("we're completely out of toilet paper")
- 0.5: Weak implied convenience (do NOT buy)
- 0.0: Unknown/unclear
BUDGET SIGNAL HANDLING:
- Phrases like "money is tight", "on a budget", "can't afford"
- Reduce confidence by 0.3-0.5
- Proceed cautiously if still above threshold
PROACTIVE PURCHASE ALLOWED IF ALL TRUE:
- Owner has enabled proactive purchasing (default ON)
- Confidence >= 0.8 (threshold)
- Item matches low-risk categories:
- Household essentials
- Office supplies
- Cables/adapters
- Basic kitchen items
- Toiletries
- Price <= min(per_order_cap, $75)
- Item keywords not in denied categories
- Item not in system blocklist
- Shipping profile exists
LOGGING:
Every purchase logs:
- "why we bought" (decision reason)
- Signals detected
- Confidence tier (HIGH/MEDIUM/LOW)
- Budget impact
```
### budget_check()
Verify sufficient credit before any purchase.
```
Process:
1. Call GET /v1/balance
2. Response includes:
- available_credit_cents: Spendable amount
- staged_refunds: Pending refunds (shown with asterisk)
- target_limit: Owner's configured credit limit
3. Compare against:
- Quote total
- per_order_cap (if set)
- daily_cap (if set, track daily spending)
4. Return: can_purchase (bool), available_amount, reason_if_blocked
```
### create_support_ticket(type, description, order_id)
Create a support ticket for returns, lost packages, or other issues.
```
Parameters:
- type: Ticket type - RETURN, LOST_PACKAGE, or OTHER
- description: Detailed description of the issue (1-2000 chars)
- order_id: Order ID (required for RETURN and LOST_PACKAGE)
Process:
1. Validate ticket type and description
2. If RETURN or LOST_PACKAGE, verify order_id is provided
3. Call POST /v1/support_tickets with { type, description, order_id }
4. Return ticket ID and status
Use cases:
- "I want to return this item" → type=RETURN, link to order
- "My package never arrived" → type=LOST_PACKAGE, link to order
- "I have a question about billing" → type=OTHER, no order needed
Note: Returns and lost packages require a support ticket.
Automated refunds only happen for order cancellations.
```
### list_support_tickets()
List the agent's support tickets.
```
Process:
1. Call GET /v1/support_tickets
2. Display tickets with: type, status, order link, creation date
3. Status meanings:
- OPEN: Submitted, awaiting support review
- IN_PROGRESS: Being handled
- WAITING_CUSTOMER: Support needs more info from you
- RESOLVED: Issue resolved
- CLOSED: Ticket closed
```
### logout()
Delete local credentials (agent persists server-side).
```
Process:
1. Delete credentials file at platform-specific path
2. Display: "Credentials removed. Agent still exists on Moltpho servers."
3. To fully delete agent, owner must use portal
Note: This only removes LOCAL credentials. The agent account, wallet, and
purchase history remain on Moltpho servers until owner deletes via portal.
```
## Browser Portal Usage
The skill uses the browser for owner-sensitive operations.
### When to Open Browser
| Action | Method |
|--------|--------|
| Complete setup (claim link) | Auto-open with notice |
| Add/manage payment cards | Direct owner to portal |
| Set credit limits | Direct owner to portal |
| Configure shipping profile | Direct owner to portal |
| View order history | Direct owner to portal |
### Browser Guidelines
- Always display notice: "Opening portal in your browser..."
- NEVER request card numbers, passwords, or sensitive credentials in chat
- Portal handles all PCI-sensitive operations via Stripe Elements
- Owner authenticates via magic link (email-based)
## API Authentication
All API requests (except registration) require authentication.
### Headers
```
Authorization: Bearer <api_key_secret>
```
Or preferably:
```
X-Moltpho-Key-Id: <api_key_id>
X-Moltpho-Signature: <HMAC signature>
```
### Idempotency
For state-changing operations, always include:
```
Idempotency-Key: <unique-key>
```
Required for:
- POST /v1/quotes
- POST /v1/orders
- POST /v1/wallets/x402/sign
## Error Handling
### Common Errors
| Code | Error | Action |
|------|-------|--------|
| 401 | UNAUTHORIZED | Re-bootstrap or check credentials |
| 402 | PAYMENT_REQUIRED | Sign and retry with x402 signature |
| 409 | PRICE_CHANGED | Re-quote if price increased >2% |
| 409 | INSUFFICIENT_CREDIT | Inform user, suggest adding credit |
| 409 | QUOTE_EXPIRED | Auto-retry (up to 3x) or re-quote |
| 422 | INVALID_SHIPPING_PROFILE | Prompt owner to add shipping via portal |
| 422 | AGENT_SUSPENDED | Inform owner, direct to portal |
| 429 | RATE_LIMITED | Wait per Retry-After header |
| 503 | TOKEN_PAUSED | System halted, wait for admin |
### Quote Expiry Auto-Retry
When a quote expires during the x402 flow:
1. Fetch new quote for same item
2. Compare price to original quote
3. If within 5% tolerance: continue with new quote
4. If >5% change: fail with PRICE_CHANGED
5. Maximum 3 retry attempts
## Constraints and Limits
### System Limits
| Limit | Value |
|-------|-------|
| Maximum item price | $10,000 USD |
| Quote TTL | 10 minutes (fixed) |
| Price tolerance | 2% increase allowed |
| Retry price tolerance | 5% for auto-retry |
| Max concurrent quotes | 5 per agent |
| Proactive purchase cap | min(per_order_cap, $75) |
### Rate Limits
| Endpoint | Limit |
|----------|-------|
| Catalog search | 60/minute |
| Quotes | 20/minute |
| Orders | 5/minute |
| Signing | 10/minute |
### Blocked Items (System Enforced)
The following categories CANNOT be purchased regardless of owner settings:
- Weapons, firearms, ammunition
- Controlled substances, prescription medications
- Tobacco, nicotine products
- Alcohol
- Adult content
- Hazardous materials
## Payment System
### Credit Model
- Owner sets target credit limit in USD
- Weekly automatic top-up restores credit to target
- Credit backed by mUSD tokens on Base mainnet
- 10% markup over Amazon prices (covers fees + gas)
### x402 Flow
1. POST /v1/orders returns 402 with PAYMENT-REQUIRED header
2. Call POST /v1/wallets/x402/sign with payment blob
3. Wallet service signs EIP-3009 authorization
4. Retry order with PAYMENT-SIGNATURE header
5. Facilitator settles on Base mainnet
6. Order proceeds to fulfillment
### Refunds
| Scenario | Refund Target |
|----------|---------------|
| Procurement failure | mUSD balance (auto) |
| Order canceled (within 5 min) | mUSD balance (auto) |
| Owner decreases credit limit | Card via Stripe |
| Return/lost package | Support ticket required (use create_support_ticket) |
## Agent States
| State | Meaning | Can Order? |
|-------|---------|------------|
| UNCLAIMED | Registered, awaiting owner claim | No |
| CLAIMED | Owner claimed, fully operational | Yes |
| DEGRADED | Payment methods failed, using remaining balance | Yes (if balance) |
| SUSPENDED | Admin action, requires manual resolution | No |
## Best Practices
### Before Any Purchase
1. Call budget_check() to verify available credit
2. Confirm shipping profile exists
3. Check item against category denylist
4. Verify confidence threshold for proactive purchases
### Conversation Guidelines
- Always confirm purchase with total price before executing
- Report order status and remaining credit after purchase
- If budget signals detected, acknowledge constraints
- Never pressure user to add more credit
### Error Recovery
- On INSUFFICIENT_CREDIT: suggest adding credit via portal
- On INVALID_SHIPPING_PROFILE: collect shipping info and call upsert_shipping_profile(), or direct to portal
- On SUSPENDED: explain owner must resolve via portal
## Quick Reference
### Essential Endpoints
| Endpoint | Purpose |
|----------|---------|
| POST /v1/agents/register | New agent registration |
| GET /v1/agents/me | Current agent status |
| GET /v1/balance | Available credit |
| GET /v1/catalog/search | Search products |
| POST /v1/quotes | Create purchase quote |
| POST /v1/orders | Place order (x402) |
| POST /v1/wallets/x402/sign | Sign payment |
| GET /v1/shipping_profiles | List shipping profiles |
| POST /v1/shipping_profiles | Create/update shipping profile |
| POST /v1/support_tickets | Create support ticket |
| GET /v1/support_tickets | List support tickets |
### Portal URL
```
https://portal.moltpho.com
```
Owner actions:
- /claim/{token} - Claim agent ownership
- /agents - Manage agents
- /cards - Payment methods
- /orders - Order history
- /settings - Credit limits and preferences
don't have the plugin yet? install it then click "run inline in claude" again.
shop for items on amazon autonomously using credit-backed mUSD tokens on base mainnet.
moltpho is a headless shopping mall that enables ai agents to discover and purchase amazon products using a credit system backed by musd (an erc-20 token on base mainnet). use this skill when you need to search for products, check credit availability, make autonomous purchases with owner approval, handle shipping details, or manage support tickets for returns and lost packages. the skill handles agent registration, credential management, product discovery, autonomous purchasing with confidence scoring, and payment via the x402 protocol on base mainnet.
http: enabled (api calls to moltpho backend)browser: enabled (portal access for owner-sensitive operations)https://api.moltpho.com (or api_base_url from credentials)Authorization: Bearer <api_key_secret>X-Moltpho-Key-Id: <api_key_id> + X-Moltpho-Signature: <hmac-sha256>Idempotency-Key header on state-changing operations (quotes, orders, signing)POST /v1/wallets/x402/sign endpoint for eip-3009 authorizations~/.config/moltpho/credentials.json%APPDATA%\moltpho\credentials.jsonMOLTPHO_CREDENTIALS_PATH environment variable{
"agent_id": "uuid",
"api_key_id": "moltpho_key_...",
"api_key_secret": "moltpho_secret_...",
"api_base_url": "https://api.moltpho.com",
"wallet_address": "0xabc123..."
}
chmod 600 (owner read-write only)inputs: none (optional: openclaw_instance_id, agent_display_name, agent_description)
process:
GET /v1/agents/me with loaded credentials to verify validityPOST /v1/agents/register (no auth required) with optional metadata
b. response contains: agent_id, api_key_id, api_key_secret, claim_url, wallet_address
c. write credentials file with chmod 600
d. display: "opening portal in your browser to complete setup..."
e. open browser to claim_url (valid for 24 hours only)UNCLAIMED, CLAIMED, DEGRADED, or SUSPENDEDoutputs: agent credentials in memory, credentials file on disk, browser window opened to claim portal
edge cases:
Retry-After header, then retryinputs: full_name, address1, address2 (optional), city, state (2-letter code), postal_code, email, phone
process:
POST /v1/shipping_profiles with all fields (upserts default profile)profile_id, confirmation statusoutputs: updated shipping profile saved server-side, confirmation message
edge cases:
inputs: query (string, required), max_price (optional, usd), category (optional, keyword), min_rating (optional, 1-5 float)
process:
GET /v1/catalog/search?query={query}&limit=20 (url-encoded)outputs: filtered product list, formatted for display
rate limits: 60 requests per minute; if hit, display "search rate limited, try again in 60 seconds"
edge cases:
inputs: none process:
GET /v1/balance (authenticated)available_credit_cents: spendable amount (balance minus active reservations)balance_cents: total balancestaged_refunds_cents: pending refunds (display with asterisk: "* including pending refund")per_order_cap_cents: owner's max per order (if set)daily_cap_cents: owner's daily max (if set)daily_spent_cents: amount spent todaycan_purchase = available_credit_cents > 0per_order_cap_cents set: note constraint in responsedaily_cap_cents set: calculate remaining daily budget = daily_cap - daily_spentavailable_usd, per_order_cap_usd (if set), daily_remaining_usd (if set), can_purchase (bool)outputs: budget summary with all limits and current spending
decision: if can_purchase = false, halt any purchase and display "insufficient credit. add credit via portal to continue."
edge cases:
inputs: asin (product identifier), quantity (int, default 1)
process:
GET /v1/shipping_profiles if needed)POST /v1/quotes with:asin: product identifierquantity: quantity (>= 1)shipping_profile_id: id of default profileIdempotency-Key: unique key for this quote requestquote_id: unique identifiertotal_due_usd: final price (includes 10% markup)expires_at: timestamp, typically 10 minutes from nowitem_price_usd, shipping_usd, tax_usd, moltpho_fee_usd: itemizationoutputs: quote object with id, total, and expiry time
rate limits: 20 quotes per minute
edge cases:
inputs: quote_id (from step 5), user confirmation
process:
6a. initiate order (first call)
POST /v1/orders with:quote_id: from step 5Idempotency-Key: unique key for orderPAYMENT-REQUIRED: blob/signature (opaque to skill)X-Moltpho-Signature: signature valuePAYMENT-REQUIRED header value for signing6b. sign payment authorization
4. call POST /v1/wallets/x402/sign with:
payment_required: the blob from step 6aidempotency_key: unique key (can differ from order key)payment_signature: eip-3009 authorization signaturesignature_expires_at: timestamp (typically 5 minutes)payment_signature6c. complete order (retry with signature)
7. call POST /v1/orders again with:
quote_id: same as beforePAYMENT-SIGNATURE header: value from step 6bIdempotency-Key: same as first callorder_id: unique order identifierstatus: PAID or PLACED (both indicate success)total_paid_usd: amount chargedoutputs: order_id, status, amount charged, updated balance
auto-retry on quote expiry:
total_due_usd to original quoterate limits: 5 order posts per minute, 10 signing calls per minute
edge cases:
GET /v1/orders/{order_id} to check if placedinputs: conversation history (implicit), owner preferences (proactive purchasing enabled: default true) process:
outputs: purchase executed (if all checks pass) or suppression logged with reason
logging: each proactive action includes structured record of decision_reason, signals_detected, confidence_tier, budget_impact
edge cases:
inputs: type (RETURN, LOST_PACKAGE, or OTHER), description (1-2000 chars), order_id (required for RETURN and LOST_PACKAGE)
process:
order_id (verify it matches user's account)
b. call GET /v1/orders/{order_id} to confirm order exists and belongs to agentPOST /v1/support_tickets with:type: ticket typedescription: issue descriptionorder_id: if applicableIdempotency-Key: unique keyticket_id, status (OPEN), created_atoutputs: ticket_id, status, creation timestamp
notes on refunds:
edge cases:
inputs: none process:
GET /v1/support_tickets (authenticated)ticket_id: unique idtype: RETURN, LOST_PACKAGE, or OTHERstatus: OPEN, IN_PROGRESS, WAITING_CUSTOMER, RESOLVED, or CLOSEDorder_id: if applicablecreated_at: timestampupdated_at: timestampdescription: summaryoutputs: formatted ticket list
edge cases:
inputs: none process:
outputs: credentials file deleted, user notified
notes:
edge cases:
if credentials file exists at platform-specific path AND GET /v1/agents/me returns 200, then load credentials and proceed with agent status (skip registration).
else if credentials file missing OR get fails with 401, then register new agent via POST /v1/agents/register, save credentials, open browser to claim link.
if available_credit >= quote_total, then proceed to create quote and order.
else, then display insufficient credit message and halt; offer link to add credit via portal.
if agent has at least one shipping profile (check GET /v1/shipping_profiles response), then proceed with quote.
else if no profile exists, then collect shipping details (step 2) or direct user to portal; halt quote until profile saved.
if quote expires (timestamp passes) while awaiting payment signature, then fetch new quote for same item. if new quote price within 5% of original, then retry order with new quote_id (up to 3 retries total). else if new price >5% higher, then fail with PRICE_CHANGED message and ask user to re-quote or confirm new price.
if confidence_score >= 0.8 AND all eligibility checks pass (enabled, profile exists, price under cap, category allowed, credit available), then execute purchase. else, then do not purchase; suppress action and log reason.
if budget constraint keywords detected (e.g., "tight budget", "expensive"), then reduce confidence_score by 0.3-0.5. if adjusted score still >= 0.8 AND item price is low (<$20), then may proceed (owner priority overrides budget concern). else if adjusted score < 0.8, then do not proactively purchase.
if error is 429 (rate limited), 503 (service paused), or timeout, then retry with backoff (2s, 4s, 8s). else if error is 402 (payment required) but missing signature, then retry signing flow. else if error is 409 (quote expired) and retries < 3, then re-quote and retry. else, then fail with error message and do not retry.
if any api call returns 401 UNAUTHORIZED, then display "authentication failed. re-run bootstrap to refresh credentials."
if any api call returns 422 AGENT_SUSPENDED, then display "account suspended. owner must resolve via portal: https://portal.moltpho.com"
chmod 600{ agent_id, api_key_id, api_key_secret, api_base_url, wallet_address }title (string)brand (string)asin (string)price_usd (float, moltpho price with 10% markup)availability_status (string: "in_stock", "limited", "out_of_stock")rating_stars (float or null)category (string)available_usd (float)balance_usd (float, total)staged_refunds_usd (float, with asterisk notation if present)per_order_cap_usd (float or null)daily_cap_usd (float or null)daily_spent_usd (float)daily_remaining_usd (float or null)can_purchase (bool)quote_id (string)total_due_usd (float)item_price_usd (float)shipping_usd (float)tax_usd (float)moltpho_fee_usd (float, the 10% markup)expires_at (iso timestamp, typically +10 min)soft_reservation_created (bool)order_id (string, unique identifier)status (string: PAID or PLACED)total_paid_usd (float)item_purchased (string)quantity (int)estimated_delivery (date or range, if available)remaining_credit_usd (float, updated balance)order_tracking_url (url to amazon tracking, if available)profile_id (string)full_name (string)address1 (string)address2 (string or null)city (string)state (string, 2-letter code)postal_code (string)email (string)phone (string)is_default (bool)ticket_id (string)type (string: RETURN, LOST_PACKAGE, or OTHER)status (string: OPEN, IN_PROGRESS, WAITING_CUSTOMER, RESOLVED, CLOSED)order_id (string or null)created_at (iso timestamp)updated_at (iso timestamp)description (string)