# Agora AI Agent Protocol (`agents.md`)

> **AGENT DIRECTIVE:** This file defines the authoritative DOM contracts, URL patterns, and REST API endpoints for interacting with SearchAgora (`https://www.searchagora.com`). Always use `/agent/*` routes and `#agent-*` / `data-agent-*` selectors instead of standard consumer UI pages to guarantee deterministic parsing and zero hydration flakiness.

Also see `llms.txt` for a high-level platform overview: https://www.searchagora.com/llms.txt

---

## 0. Choose Your Execution Mode

| Agent Type | Examples | Authentication Required? | Primary Workflow |
| :--- | :--- | :--- | :--- |
| **Browser / DOM Agent** | Perplexity, OpenAI Operator, Claude Computer Use, Browser-Use | **No** (Uses browser session/cookies, or user log-in at checkout) | Navigate `/agent/search?q=...` → `/agent/product/[slug]` → Click `#agent-add-to-cart` → `/agent/cart` → `/agent/checkout` |
| **Programmatic / API Agent** | Custom LLM tools, MCP servers, backend scripts | **Yes** (`Authorization: Bearer <API_KEY>` for v1 API & headless checkout) | Call `/api/search` → Read `#agent-product-raw-json` → Call `/api/agent/cart` & `/api/agent/checkout` |

---

## 1. Route Discovery & Manifest

Fetch the JSON manifest first to discover live routes, DOM selectors, and schema contracts programmatically:

- **Manifest URL:** `GET https://www.searchagora.com/api/agent-routes`
- **Response Format:** `application/json`
- **Agent Hub:** `https://www.searchagora.com/agent`

---

## 2. Search for Products

### Option A: Direct URL Navigation (Fastest for Browser Agents)
Skip form interaction by passing the search query directly in the URL:
- **URL Pattern:** `https://www.searchagora.com/agent/search?q={URL_ENCODED_QUERY}&page=1`
- **Example:** `https://www.searchagora.com/agent/search?q=quiet%20dishwasher&page=1`

### Option B: DOM Form Interaction (`/agent/search`)
If already on `https://www.searchagora.com/agent/search`, interact with these guaranteed stable selectors:

| Element Role | Selector | Action / Contract |
| :--- | :--- | :--- |
| Search Form | `form#agent-search-form` | Submit form to trigger search results. |
| Search Input | `input#agent-search-input` | Attribute `name="q"`. Set value to search query string. |
| Submit Button | `button#agent-search-submit` | Click to execute search. |
| Results Container | `#agent-product-list` | Parent container holding `.agent-product-item` cards. |
| Product Card | `.agent-product-item` | Contains `data-agent-*` attributes for instant extraction. |
| Product Link | `a.agent-product-link` | Also matches `[data-agent-role="product-detail-link"]` or `[data-agent-href]`. |
| Load More / Next | `button#agent-fetch-more` | Click to append the next page of results into `#agent-product-list`. |

**Product Card Data Attributes (on `.agent-product-item`):**
- `data-agent-product-slug`: Unique URL slug (use to navigate to `/agent/product/[slug]`).
- `data-agent-product-id`: MongoDB `_id` of the product (use for cart/checkout payloads).
- `data-agent-product-name`: Full product title.
- `data-agent-product-price`: Formatted price string (e.g., `$499.00`).

### Option C: Direct JSON Search API (No Auth Required)
- **Endpoint:** `GET https://www.searchagora.com/api/search?q={query}&page={page}&count={count}`
- **Response:**
```json
{
  "data": {
    "Products": [
      {
        "_id": "664f1a2b3c4d5e6f7a8b9c0d",
        "slug": "bosch-300-series-dishwasher-shem63w55n",
        "name": "Bosch 300 Series 24\" Recessed Handle Dishwasher",
        "price": 749.00,
        "brand": "Bosch",
        "inStock": true
      }
    ],
    "hasMore": true
  }
}
```

---

## 3. View Product Details & Extract Variant / Cart Data

Navigate to: `https://www.searchagora.com/agent/product/[slug]`

### A. Human/DOM Summary Fields (`#agent-product-meta`)
Structured key-value metadata is exposed inside `#agent-product-meta` via `[data-agent-field]` and `[data-agent-value]`:
- `[data-agent-field="name"]` — Product title
- `[data-agent-field="price"]` — Current price
- `[data-agent-field="brand"]` — Brand name
- `[data-agent-field="availability"]` — Stock status (`IN_STOCK` / `OUT_OF_STOCK`)
- `[data-agent-field="store"]` — Merchant / store name

### B. Full Machine-Readable JSON (`pre#agent-product-raw-json`)
The complete database object is embedded directly in the DOM.
- **Selector:** `pre#agent-product-raw-json`
- **Extraction Rule:** Read `.textContent` (DO NOT use `.innerHTML`, as HTML entity escaping like `&amp;` will corrupt `JSON.parse()`).
- **Key Fields Required for Cart & Checkout:**
```json
{
  "_id": "664f1a2b3c4d5e6f7a8b9c0d",
  "slug": "bosch-300-series-dishwasher-shem63w55n",
  "name": "Bosch 300 Series Dishwasher",
  "price": 749.00,
  "variants": [
    {
      "_id": "var_01",
      "variantId": "var_01",
      "title": "Stainless Steel",
      "price": 749.00,
      "available": true
    }
  ]
}
```
> **IMPORTANT:** Always use `_id` (the MongoDB ObjectId string) as the `product` identifier when adding to cart or checking out. v1 search also returns `id` with the same value as `_id` — either works. If `variants` is empty or omitted, you may omit `variantId` (or pass `null`) — the API defaults `variantId` to the product `_id`. Malformed product ids return `400`.

---

## 4. Add to Cart & Checkout

### Track A: Browser / DOM Agents (Perplexity, Operator, Playwright)
Browser agents can add items to the cart and complete checkout directly through the DOM without an API key:

1. **On `/agent/product/[slug]` (or standard `/product/[slug]`):**
   - **Select Variant (if present):** `select#agent-variant-select` (set value to target `variantId`) or click button `[data-agent-variant-id="<variant_id>"]`.
   - **Set Quantity:** `input#agent-quantity-input` (default `1`).
   - **Add to Cart:** Click `button#agent-add-to-cart` (inside `form#agent-add-to-cart-form`).
   - **Cart Confirmation:** Wait for `[data-agent-cart-status="added"]` (other values: `idle`, `adding`, `error`), then follow the `a#agent-view-cart` link to `/agent/cart`.

2. **On `/agent/cart` & `/agent/checkout`:**
   - **Cart Items List:** `#agent-cart-items` (each row has `data-agent-product-id`, `data-agent-variant-id`, `data-agent-quantity`).
   - **Change quantity:** `input#agent-cart-quantity-{index}` (set value, then click `button#agent-cart-update-quantity-{index}` or submit the line form).
   - **Remove line:** `button#agent-cart-remove-{index}`. Cart is account-scoped — remove leftover items from earlier sessions before checkout if needed.
   - **Proceed to Checkout Button:** Click `a#agent-proceed-to-checkout` (link text "Proceed to checkout"; navigates to `/agent/checkout`).
   - **Shipping Form (`form#agent-checkout-form`):**
     - `input#agent-first-name` (`name="firstName"`)
     - `input#agent-last-name` (`name="lastName"`)
     - `input#agent-email` (`name="email"`)
     - `input#agent-address-line1` (`name="addressFirst"`)
     - `input#agent-city` (`name="city"`)
     - `input#agent-state` (`name="state"`)
     - `input#agent-zip` (`name="zipCode"`)
     - `select#agent-country` (`name="country"`, ISO 2-letter code e.g. `US`)
   - **Place Order / Handoff to User for Payment:** Click `button#agent-submit-order` (button text "Place order"; progress is mirrored in `[data-agent-checkout-status]`: `idle`, `invalid`, `awaiting-payment`). *(Note: If the autonomous agent policy requires human confirmation for payment entry, stop after filling `#agent-checkout-form` and prompt the user to confirm payment.)*

> **Snapshot-based agents:** accessibility snapshots do not expose element `id`s. Every control above still carries its `id`; if you cannot see it, match by accessible name instead: "Add to cart" (`#agent-add-to-cart`), "View cart" (`#agent-view-cart`), "Proceed to checkout" (`#agent-proceed-to-checkout`), "Place order" (`#agent-submit-order`). To verify ids, query the DOM (e.g. `document.getElementById('agent-proceed-to-checkout')`).

---

### Track B: Programmatic API Checkout (Headless Agents)

*(Requires Bearer Authentication — see Section 6 below to generate an API key).*

**Optional — read the cart:** `GET https://www.searchagora.com/api/agent/cart` with `Authorization: Bearer <YOUR_API_KEY>`. Response: `{ "status": "success", "items": [...], "cart": {...} }`. Same on staging v1: `GET https://stagingServer.searchagora.com/api/v1/cart`.

**Read the cart:** `GET https://www.searchagora.com/api/agent/cart` with `Authorization: Bearer <YOUR_API_KEY>`. Response: `{ "status": "success", "items": [...], "cart": {...} }`. Also `GET https://stagingServer.searchagora.com/api/v1/cart`.

**Optional — set the cart on its own:** `POST https://www.searchagora.com/api/agent/cart` with `Authorization: Bearer <YOUR_API_KEY>` and body `{ "items": [{ "product": "<_id>", "quantity": 1, "variantId": "<variantId_if_applicable>" }] }`. Response: `{ "status": "success", "items": [...] }`. Omit/`null` `variantId` is fine for products without variants (server defaults to product `_id`). Invalid ids → `400`.

**Create a PaymentIntent for the cart:** `POST https://www.searchagora.com/api/agent/payment-intent` with `Authorization: Bearer <YOUR_API_KEY>` (optional body: `shippingState`, `shippingOptions`, `email`, `firstName`, `lastName`, `paymentMethod`). Response: `{ "status": "success", "clientSecret", "paymentIntentId", "stripeCustomerId", "publishableKey" }`. Use `publishableKey` + `clientSecret` with Stripe.js / Elements to confirm, then pass the resulting `pm_…` / `pi_…` into checkout. Also available as `POST https://stagingServer.searchagora.com/api/v1/payment-intent`.

`POST /api/agent/checkout` accepts an `items` array to populate the cart (`POST /api/v1/cart`) and then submit the order in a single call. `paymentMethodId` / `paymentIntent` come from confirming the PaymentIntent above (`pm_…` / `pi_…`). `offsetPerc` is the percent of merchandise to cover with Agora credits (`0` = full card charge). For headless checkout, `formData` wins over `shippingAddress` for name/email/address.

- **Endpoint:** `POST https://www.searchagora.com/api/agent/checkout`
- **Headers:**
  - `Content-Type: application/json`
  - `Authorization: Bearer <YOUR_API_KEY>`
- **Request Payload:**
```json
{
  "items": [
    {
      "product": "<_id_from_agent_product_raw_json>",
      "quantity": 1,
      "variantId": "<variantId_if_applicable>"
    }
  ],
  "paymentMethodId": "<stripe_payment_method_id>",
  "paymentIntent": "<stripe_payment_intent_id>",
  "offsetPerc": 0,
  "shippingAddress": {
    "firstName": "Jane",
    "lastName": "Doe",
    "addressFirst": "123 Market St",
    "city": "San Francisco",
    "state": "CA",
    "zipCode": "94105",
    "country": "US"
  },
  "formData": {
    "firstName": "Jane",
    "lastName": "Doe",
    "email": "jane@example.com",
    "addressFirst": "123 Market St",
    "city": "San Francisco",
    "state": "CA",
    "zipCode": "94105",
    "country": "US"
  }
}
```
- **Response (`200 OK`):** `{ "status": "success", "order": { "_id", "orderCode" } }` from Developer API `POST /api/v1/order` (API-key auth). Track with `GET /api/agent/orders/{orderId}` → `GET /api/v1/order-tracking/{orderId}`.

---

## 5. Order Tracking

Query real-time fulfillment and tracking details using the `orderId` returned at checkout:

- **Endpoint:** `GET https://www.searchagora.com/api/agent/orders/[orderId]`
- **Headers:** `Authorization: Bearer <YOUR_API_KEY>` (required)
- **Auth scope:** Only orders owned by the API-key user. Other users’ orders return `404`.
- **Response:**
```json
{
  "orderId": "12345",
  "status": "SHIPPED",
  "trackingUrl": "https://tools.usps.com/go/TrackConfirmAction?tLabels=...",
  "estimatedDelivery": "2026-10-24"
}
```
(`trackingUrl` / `estimatedDelivery` may be `null` until the order ships.)

---

## 6. Developer API & Authentication (`zues.searchagora.com`)

When integrating Agora directly into an external application, MCP server, or coding agent via REST:

### 1. Create an API Key
1. Sign in at https://www.searchagora.com (requires Premium / Developer Tools access — see https://www.searchagora.com/pricing).
2. Navigate to https://www.searchagora.com/developer-tools/api-keys
3. Generate a new key and store it securely (displayed only once).

### 2. Authenticate Requests
Include the bearer token in the `Authorization` header of all requests to the v1 API:
- **Base URL:** `https://zues.searchagora.com/api/v1`
- **Header:** `Authorization: Bearer YOUR_API_KEY`

### 3. Example: Authenticated v1 Search
```bash
curl -sS \
  -H "Authorization: Bearer YOUR_API_KEY" \
  "https://zues.searchagora.com/api/v1/search?q=quiet%20dishwasher&count=5"
```

```javascript
const res = await fetch(
  'https://zues.searchagora.com/api/v1/search?q=quiet%20dishwasher&count=5',
  { headers: { Authorization: `Bearer ${process.env.AGORA_API_KEY}` } }
);
const data = await res.json();
// data.Products[] — extract ._id and .slug for detail, cart, and checkout flows
console.log(data.Products?.[0]);
```

---

## 7. Quick Reference Links

- **Agent Hub:** https://www.searchagora.com/agent
- **Agent Search UI:** https://www.searchagora.com/agent/search
- **Agent Cart:** https://www.searchagora.com/agent/cart
- **Agent Checkout:** https://www.searchagora.com/agent/checkout
- **Agent Route Manifest (JSON):** https://www.searchagora.com/api/agent-routes
- **LLMs Overview (`llms.txt`):** https://www.searchagora.com/llms.txt
- **Agent Protocol (`agents.md`):** https://www.searchagora.com/agents.md
- **API Keys Dashboard:** https://www.searchagora.com/developer-tools/api-keys
- **Developer Docs:** https://docs.searchagora.com/introduction/quickstart
- **Auth Docs:** https://docs.searchagora.com/basics/authentication
