> ## Documentation Index
> Fetch the complete documentation index at: https://docs.maximem.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Amazon: Shopping Assistant

> Catalog-grounded shopping concierge with order history, preference recall, and return handling.

<Check>
  **Status:** Live in Playground · **Try it:** [synap.maximem.ai/playground](https://synap.maximem.ai/playground)
  Open the playground and pick **Amazon: Shopping Assistant** to see the reference implementation running before you build.
</Check>

A shopping concierge that knows the buyer's order history, dietary and material preferences, brand affinities, and recent searches. It grounds product suggestions in the live catalog via tools and handles tracking, returns, and re-orders, all while learning preferences across sessions.

## What you'll build

A chat agent that:

* **Searches the catalog** with the buyer's preferences applied as filters by default
* **Recalls preferences**: dietary restrictions, allergies, sizes, materials, brand likes/dislikes
* **Grounds in order history**: "find me another of those running shoes I bought in March"
* **Handles post-purchase**: tracking, returns, replacement orders

**Est. build time:** 30 to 45 minutes (assuming you already have catalog and orders APIs).

## When to use this recipe

Build this if your product:

* Has a sizeable catalog where suggestion quality matters
* Tracks per-buyer order history you want the agent to reference
* Wants the agent to *remember preferences* across visits without making the buyer re-state them
* Needs the agent to take post-purchase actions (track, return, replace)

## Architecture at a glance

<Frame>
  <img src="https://mintcdn.com/maximemai/hC0v5SwR4z4on8p2/images/cookbook-amazon.png?fit=max&auto=format&n=hC0v5SwR4z4on8p2&q=85&s=198a6a2d3445a2985e8042e2dd9d2bab" alt="Amazon shopping assistant architecture diagram showing chat, backend, Synap memory fetch, LLM with catalog and order tools, and turn ingestion" width="1774" height="887" data-path="images/cookbook-amazon.png" />
</Frame>

Preferences and order context auto-organize into a [MACA](/concepts/memory-architecture); you don't define the fields; the SDK does.

## Stack

| Layer              | Choice                                                                                                                |
| ------------------ | --------------------------------------------------------------------------------------------------------------------- |
| **Synap SDK**      | `maximem-synap` (Python) / `@maximem/synap-js-sdk` (TypeScript)                                                       |
| **Framework**      | [OpenAI Agents SDK](/integrations/openai-agents) (Python) / [Vercel AI SDK](/integrations/vercel-ai-sdk) (TypeScript) |
| **Memory adapter** | `maximem-synap-openai-agents` / `@maximem/synap-vercel-adk`                                                           |
| **LLM**            | OpenAI `gpt-4o`                                                                                                       |
| **Channel**        | Your existing chat surface (web widget, in-app, etc.)                                                                 |

## Prerequisites

* A Synap API key, see [Authentication](/setup/authentication)
* Internal APIs for catalog search, product details, orders, and returns
* **Python recipe:** Python 3.11+
* **TypeScript recipe:** Node 18+ **and** Python 3.11+ on the host

<Warning>
  TypeScript recipe runs on Node only. Pin Next.js route handlers to `export const runtime = "nodejs"`. See [Installation → JavaScript / TypeScript SDK](/setup/installation#javascript-typescript-sdk).
</Warning>

### Install

<CodeGroup>
  ```bash Python theme={null}
  pip install maximem-synap maximem-synap-openai-agents openai-agents
  ```

  ```bash uv theme={null}
  uv add maximem-synap maximem-synap-openai-agents openai-agents
  # pip-compatible (existing venv): uv pip install maximem-synap maximem-synap-openai-agents openai-agents
  ```

  ```bash TypeScript theme={null}
  npm install @maximem/synap-js-sdk @maximem/synap-vercel-adk ai @ai-sdk/openai zod
  ```
</CodeGroup>

### Configure

<CodeGroup>
  ```bash Python theme={null}
  # .env
  SYNAP_API_KEY=...
  OPENAI_API_KEY=...
  ```

  ```bash TypeScript theme={null}
  # .env.local
  SYNAP_API_KEY=...
  OPENAI_API_KEY=...
  ```
</CodeGroup>

## Build it

### 1. Identity & scoping

* `customer_id = "amazon"`: single tenant
* `user_id = <stable buyer ID>`: from authenticated session
* `conversation_id = <session UUID>`: per chat session

<Note>
  `conversation_id`, `user_id`, and `customer_id` must be valid UUIDs. Generate session ids with `crypto.randomUUID()` (JS) or `str(uuid.uuid4())` (Python), as shown below.
</Note>

<CodeGroup>
  ```python Python theme={null}
  SESSIONS: dict[str, str] = {}

  def conv_for(session_id: str) -> str:
      return SESSIONS.setdefault(session_id, str(uuid.uuid4()))
  ```

  ```typescript TypeScript theme={null}
  const SESSIONS = new Map<string, string>();

  function convFor(sessionId: string): string {
    if (!SESSIONS.has(sessionId)) SESSIONS.set(sessionId, crypto.randomUUID());
    return SESSIONS.get(sessionId)!;
  }
  ```
</CodeGroup>

### 2. Business tools

<CodeGroup>
  ```python Python theme={null}
  from agents import function_tool

  @function_tool
  async def search_catalog(query: str, filters: dict = None, limit: int = 10) -> list[dict]:
      """Search the catalog. Filters: {category, price_max, brand, dietary, material}."""
      return await catalog_api.search(query, filters or {}, limit)

  @function_tool
  async def get_product_details(asin: str) -> dict:
      """Return full product detail: title, price, specs, reviews_summary, in_stock."""
      return await catalog_api.detail(asin)

  @function_tool
  async def get_order_history(buyer_id: str, limit: int = 10) -> list[dict]:
      """Return the buyer's recent orders, newest first."""
      return await orders_api.history(buyer_id, limit)

  @function_tool
  async def add_to_cart(buyer_id: str, asin: str, qty: int = 1) -> dict:
      return await cart_api.add(buyer_id, asin, qty)

  @function_tool
  async def track_order(order_id: str) -> dict:
      return await orders_api.track(order_id)

  @function_tool
  async def request_return(order_id: str, reason: str, items: list[str]) -> dict:
      return await returns_api.create(order_id, reason, items)
  ```

  ```typescript TypeScript theme={null}
  import { tool } from "ai";
  import { z } from "zod";

  const businessTools = {
    search_catalog: tool({
      description: "Search the catalog with optional filters.",
      parameters: z.object({
        query: z.string(),
        filters: z.object({
          category: z.string().optional(),
          priceMax: z.number().optional(),
          brand: z.string().optional(),
          dietary: z.string().optional(),
          material: z.string().optional(),
        }).optional(),
        limit: z.number().default(10),
      }),
      execute: async ({ query, filters, limit }) =>
        catalogApi.search(query, filters ?? {}, limit),
    }),
    get_product_details: tool({
      description: "Return full product detail.",
      parameters: z.object({ asin: z.string() }),
      execute: async ({ asin }) => catalogApi.detail(asin),
    }),
    get_order_history: tool({
      description: "Return the buyer's recent orders, newest first.",
      parameters: z.object({ buyerId: z.string(), limit: z.number().default(10) }),
      execute: async ({ buyerId, limit }) => ordersApi.history(buyerId, limit),
    }),
    add_to_cart: tool({
      description: "Add an item to the buyer's cart.",
      parameters: z.object({ buyerId: z.string(), asin: z.string(), qty: z.number().default(1) }),
      execute: async ({ buyerId, asin, qty }) => cartApi.add(buyerId, asin, qty),
    }),
    track_order: tool({
      description: "Return tracking info for an order.",
      parameters: z.object({ orderId: z.string() }),
      execute: async ({ orderId }) => ordersApi.track(orderId),
    }),
    request_return: tool({
      description: "Open a return for one or more items in an order.",
      parameters: z.object({
        orderId: z.string(),
        reason: z.string(),
        items: z.array(z.string()),
      }),
      execute: async ({ orderId, reason, items }) =>
        returnsApi.create(orderId, reason, items),
    }),
  };
  ```
</CodeGroup>

### 3. System prompt

```text System prompt theme={null}
You are an Amazon shopping concierge.

- Apply known buyer preferences (dietary, allergies, sizes, materials, brand likes/dislikes) as filters by default. Surface them in your reasoning so the buyer can override.
- Never recommend items that violate a known allergy or dietary restriction.
- Cite product title + ASIN when you suggest something. Don't oversell; one or two options is better than five.
- For "find me another of those X I bought", search order history first, then catalog.
- Keep replies under 5 sentences unless listing options. Be helpful, not pushy.
```

### 4. Wire memory + LLM + tools

<CodeGroup>
  ```python Python theme={null}
  import os, uuid, asyncio
  from agents import Agent, FunctionTool, Runner
  from maximem_synap import MaximemSynapSDK
  from synap_openai_agents import create_search_tool, create_store_tool

  sdk = MaximemSynapSDK()
  await sdk.initialize()

  async def handle_message(buyer_id: str, session_id: str, text: str) -> str:
      conv_id = conv_for(session_id)

      synap_search = create_search_tool(sdk=sdk, user_id=buyer_id, customer_id="amazon")
      synap_store  = create_store_tool(sdk=sdk, user_id=buyer_id, customer_id="amazon")

      agent = Agent(
          name="amazon_shopping",
          instructions=SYSTEM,
          tools=[
              FunctionTool(synap_search, name_override="synap_search"),
              FunctionTool(synap_store,  name_override="synap_store"),
              search_catalog,
              get_product_details,
              get_order_history,
              add_to_cart,
              track_order,
              request_return,
          ],
      )

      result = await Runner.run(agent, input=text)
      reply = result.final_output

      asyncio.create_task(sdk.memories.create(
          document=f"Buyer: {text}\nAssistant: {reply}",
          document_type="ai-chat-conversation",
          user_id=buyer_id,
          customer_id="amazon",
          metadata={"conversation_id": conv_id, "channel": "web-chat"},
      ))
      return reply
  ```

  ```typescript TypeScript theme={null}
  import { generateText } from "ai";
  import { openai } from "@ai-sdk/openai";
  import { createSynap } from "@maximem/synap-vercel-adk";

  const synap = await createSynap({ apiKey: process.env.SYNAP_API_KEY! });

  export async function handleMessage(
    buyerId: string,
    sessionId: string,
    text: string,
  ): Promise<string> {
    const conversationId = convFor(sessionId);

    const model = synap.wrap(openai("gpt-4o"), {
      userId: buyerId,
      customerId: "amazon",
      conversationId,
    });

    const { text: reply } = await generateText({
      model,
      system: SYSTEM,
      prompt: text,
      tools: businessTools,
    });

    return reply;
  }
  ```
</CodeGroup>

## Run & verify

```text Session 1 theme={null}
Buyer:     Looking for vegan protein powder, ideally chocolate flavored, under $40.
Assistant: Two solid picks under $40:
           - Orgain Organic Plant Protein (ASIN B07J2N4Q1H), $32, 21g protein, chocolate fudge.
           - Vega Sport Premium (ASIN B00MUK2KQM), $39, 30g protein, mocha. Want either added to cart?

Buyer:     Add the Orgain. I'm allergic to soy by the way.
Assistant: Added Orgain to cart. Noted: I'll keep your suggestions soy-free from here on.
```

```text Session 2 (a week later, new conversation_id) theme={null}
Buyer:     I need a new protein, ran out.
Assistant: Re-ordering Orgain Organic Plant Protein (chocolate fudge), same one as last time.
           It's soy-free, which matches your allergy. Add to cart?
```

The second session is a fresh conversation. Synap surfaces the prior order and the soy allergy without you wiring them by hand.

### Inspect what got stored

<CodeGroup>
  ```python Python theme={null}
  docs = await sdk.memories.list(user_id="buyer_42", customer_id="amazon", limit=20)
  for d in docs:
      print(d.document_type, ":", d.content[:120])
  ```

  ```typescript TypeScript theme={null}
  const docs = await synap.sdk.memories.list({ userId: "buyer_42", customerId: "amazon", limit: 20 });
  for (const d of docs) console.log(d.documentType, ":", d.content.slice(0, 120));
  ```
</CodeGroup>

## Customize / extend

* **Voice channel** → swap the chat handler for [Voice Concierge](/cookbook/voice-concierge). The shopping tools transfer untouched.
* **Multi-tenant marketplaces** → set `customer_id` per seller storefront. See [Patterns → Multi-Tenant SaaS](/patterns/multi-tenant-saas).
* **Replay historical orders into memory** on launch so the agent is useful from day one. See [Patterns → Replay History](/patterns/replay-history).
* **Different framework** → see [AI Integrations](/integrations/overview) for LangChain, LlamaIndex, CrewAI, etc.
* **Support flavor** → adapt this shape with `request_refund` instead of `request_return`; see [Uber: Customer Support](/cookbook/consumer-uber).

## Troubleshooting

**Assistant ignores known allergies / dietary prefs**

* Confirm `synap_search` is being called (Python); inspect the agent trace. If the model isn't calling it, sharpen the system prompt: "Before recommending food, beauty, or supplements, call `synap_search` for the buyer's restrictions."
* For the TS path with `synap.wrap`, increase `maxResults` so the dietary memory makes it into the injected context.

**Same product suggested over and over**

* The agent has the buyer's affinity but no negative feedback. Capture explicit rejections ("I didn't like that one") with `synap_store`, or post-purchase ratings via your own pipeline → `sdk.memories.create`.

**Order history out of sync**

* Order data should be tool-fetched live, never cached in memory. If you see stale orders in suggestions, your tool is returning cached data, not Synap.

## Related

* **Integrations:** [OpenAI Agents SDK](/integrations/openai-agents) · [Vercel AI SDK](/integrations/vercel-ai-sdk)
* **Concepts:** [Customized Memory Architectures](/concepts/memory-architecture) · [Memory Scopes](/concepts/memory-scopes)
* **Patterns:** [Replay History](/patterns/replay-history) · [Multi-Tenant SaaS](/patterns/multi-tenant-saas)
* **Other recipes:** [Uber: Customer Support](/cookbook/consumer-uber) · [Salesforce: Enterprise Sales Assistant](/cookbook/b2b-salesforce)
