Skip to content
Browse documentation

Storefront AI agent

How the storefront AI assistant works, how to connect your own agent, and what your agent can do.

Overview

The storefront AI assistant is a chat widget injected on your store. When a shopper sends a message, it streams to your configured provider through our endpoint POST /api/store/modules/ai-assistant/stream, and the widget renders the reply. Replies support Markdown and optional tappable choices (see Interactive messages).

You configure it per store under Modules → AI Assistant: enable it, pick a provider, and (optionally) let the agent read your catalog.

Providers

Two ways to power the assistant:

Provider What it is Use when
Claude / DeepSeek (BYOK) We run the agent loop with your own model API key; our built-in store tools are available. You want a shopping assistant over your catalog with minimal setup.
External agent (bring your own agent) We proxy the conversation to your own agent API and stream its reply back. Your agent stays authoritative. You already have an agent (e.g. a specialized assistant) and want it hosted in the store UI.

External agent API

With the External agent provider, we forward each turn to your endpoint and re-stream the reply. Request body:

POST <your endpoint>?<optional query params>
Content-Type: application/json

{
  "messages": [ { "role": "user", "content": "..." }, ... ],
  "session_id": "<conversation id>",
  "mcp": { "url": "...", "headers": { ... } }   // present only if "expose store products" is on
}

You may set one auth header (name + value) and extra query params / body fields in the config. Respond with a streamed body in one of these formats:

Stream format Meaning Notes
text (recommended) Plain UTF-8 text; we re-wrap it into the widget stream. Library-agnostic — your backend/AI-SDK version never has to match ours.
sse-text SSE frames carrying plain text. Also library-agnostic (transport convention only).
ai-sdk-ui Verbatim Vercel AI SDK UI-message stream. Reserved / not enabled. Requires the AI SDK at a protocol compatible with ours (ai@7).

Prefer text: because we only read raw bytes, there is no coupling between your AI-SDK version and ours. Only ai-sdk-ui would impose a version contract.

Per-page endpoints

Different pages can talk to different agents, for example one agent per landing page. Under Per-page endpoints, map a page path to its own endpoint URL:

Path Matches
/summer-sale Exactly that page (a trailing slash, query string, or hash is ignored).
/lp/* /lp and every page under it (/lp/shoes, /lp/vip/gold), but not /lpx.

The most specific match wins: an exact path beats any /* rule, and a longer prefix beats a shorter one. Pages with no match use the default endpoint URL. A rule only changes the URL; the auth header, query params, body fields, and stream format are shared. The request body is the same for every endpoint, and the shopper's conversation carries over as they move between pages.

Store products via MCP

Your store exposes a read-only MCP endpoint so an agent can look up your catalog. It lives on your store's own domain:

https://<your-store-domain>/api/store/mcp

It's scoped to your store by domain — no key needed when connecting via your store's URL. It's a standard Streamable-HTTP MCP server exposing:

Tool Does
searchProducts Search published products by text / collection.
getProduct Full details for one product by slug.
listCollections List product collections.
getStoreInfo Public store info (name, branding, currencies).

When "expose store products" is on for an external agent, we include the binding in each request so your agent can connect:

"mcp": {
  "url": "https://<your-store-domain>/api/store/mcp",
  "headers": { "x-publishable-key": "pk_live_…" }
}

Fail-open: the store tools are optional enrichment. Your agent should connect the MCP client with a short timeout and continue normally if it's unreachable — the MCP endpoint being down must never break the conversation.

Interactive messages

Markdown: assistant messages render as sanitized Markdown — headings, bold, lists, rules, tables, links, inline code (inline HTML is sanitized to a safe subset). Just emit normal Markdown.

Tappable choices: to let the shopper pick from a fixed set, emit a fenced select block. The widget renders it as chips and hides the raw block:

```select multi min=1 max=3
1. ⚡ Energy & Performance
2. 🌿 Gut & Digestion
3. 😴 Sleep & Relaxation
```
  • Info string: single (default) or multi; optional min=N / max=N.
  • Items: N. label (or - label, auto-numbered). Emojis allowed.
  • On tap, the shopper's reply arrives as the chosen numbers (e.g. 1 3) — a normal user message. Parse it as their selection.
  • An agent that doesn't emit the block still works: it renders as a numbered list and the shopper types.

Action buttons (call-to-action): emit a fenced action block — one button per line. Don't emit raw HTML buttons/cards; they're stripped.

```action
View my formula
Shop the range | https://store.example.com/shop
```
  • A plain line is a button whose tap sends that text back as the shopper's message.
  • label | <url> (https://…, /path, mailto:, tel:) opens a link in a new tab.
  • Buttons are themed with the store's accent automatically.

Redirect: end a reply with a fenced navigate block holding one store path, and the widget takes the shopper there in the same tab once the reply finishes. Only pages on your own store are allowed.

```navigate
/products/energy-formula
```

Our built-in models emit select, action and navigate automatically. An external agent enables them by adding the blocks to its own system prompt — no code change.