Skip to content

Marqo Conversational Agent API

Overview

The Conversational Agent API provides intelligent, conversational product discovery with query expansion, contextual recommendations, and real-time streaming responses. The system understands user intent, asks clarifying questions when needed, and organizes results into meaningful categories with natural language explanations.

Features

  • Conversational Search: Natural language queries with intelligent query expansion
  • Context-Aware Suggestions: Product-specific query suggestions on PDP pages
  • Streaming Responses: Real-time streaming via Server-Sent Events (SSE)
  • Categorized Results: Products organized into logical categories with descriptions
  • Clarifying Questions: System asks questions when queries are ambiguous
  • Context Continuity: Maintains conversation context across interactions
  • Automatic Filtering: When automatic filtering is enabled, the agent automatically applies filters based on user intent (see Automatic Filtering)

Prerequisites

  • A Marqo Cloud account
  • Your x-marqo-index-id value (copy it from the Quick Start code snippets for your index in the Marqo Console)
  • An existing ecommerce index with products (add products guide)
  • Access to the Conversational Agent API (contact Marqo for access)

Endpoints

PDP Query Suggestions

Generate contextual search query suggestions based on a specific product. This endpoint helps users discover related products or learn more about a product they're viewing.

Endpoint: POST /indexes/{index_name}/agentic-search/chat-suggestions

Headers: - Content-Type: application/json - x-marqo-index-id: {index_id} (required)

Request Parameters:

Parameter Type Required Default Description
documentId string Yes - Product document identifier (_id field)
sessionId string Yes - User session identifier
userId string Yes - User identifier
maxSuggestions integer No 5 Maximum number of suggestions to return
minSuggestions integer No 1 Minimum number of suggestions to return
contextFields array No All fields Product fields to use for context (e.g., ["material", "description"])

Example Request:

curl -X POST 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/chat-suggestions' \
  --header 'Content-Type: application/json' \
  --header 'x-marqo-index-id: abc123-my-ecom-store' \
  --data '{
    "documentId": "273301208",
    "sessionId": "session-abc123",
    "userId": "user-28389290",
    "maxSuggestions": 5,
    "minSuggestions": 1,
    "contextFields": ["material", "description"]
  }'

Example Response:

[
  "What heels would go well with this?",
  "What is the material made out of?",
  "What do people say about this product?"
]

The response is an array of suggested queries that users might want to ask about the product.


Stream conversational search results with categorized products and intelligent messaging. This is the main endpoint for conversational product discovery.

Endpoint: GET /indexes/{index_name}/agentic-search/converse

Headers:

  • x-marqo-index-id: {index_id} (required)

Query Parameters:

Parameter Type Required Description
payload string Yes Base64-encoded JSON containing the request parameters (see below)

Payload Parameters (JSON, then base64-encoded):

Parameter Type Required Default Description
q string Yes - User query
sessionId string No null Session identifier
userId string No null User identifier
conversationId string No - Conversation identifier (returned from a previous response) for maintaining context
categoryResultLimit integer No 6 Number of results per category
maxCategories integer No 4 Maximum number of categories the agent will return
filter string No - Query filter using Marqo's filter DSL (e.g., "availability:true")
attributesToRetrieve array No Default fields Product fields to return (e.g., ["productTitle", "variantTitle", "price", "variantImageUrl", "_id"])
documentIds array No - Product document IDs to use as context (e.g., for PDP page questions)
contextFields array No All fields Fields to include from the document context (e.g., ["material", "description"])
imageUrls array No - Image URLs to include in the query (max 5, must be valid URLs)
categoriesAfterMessage boolean No false When true, category-hits events are always sent after the message events (see Response Event Ordering)

Example Request: With Product Context

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
  --header 'x-marqo-index-id: abc123-my-ecom-store' \
  --data-urlencode "payload=$(echo -n '{
    "conversationId": "3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9",
    "documentIds": ["1298739082732"],
    "q": "I need outfits for a tropical vacation",
    "sessionId": "session-xyz789",
    "userId": "user-123",
    "categoryResultLimit": 6,
    "filter": "availability:true",
    "attributesToRetrieve": [
      "productTitle",
      "variantTitle",
      "price",
      "variantImageUrl",
      "_id"
    ]
  }' | base64 | tr -d '\n')"

Example Request: Simple Query

curl -G 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse' \
  --header 'x-marqo-index-id: abc123-my-ecom-store' \
  --data-urlencode "payload=$(echo -n '{
    "q": "red dress",
    "sessionId": "session-001",
    "userId": "user-456"
  }' | base64 | tr -d '\n')"

Response Events

The conversational search endpoint streams responses as Server-Sent Events (SSE). Each event has an event: field identifying its type and a data: field containing a JSON payload.

message

Streamed text deltas from the agent's conversational response. These arrive incrementally as the agent generates text and should be concatenated to build the full message.

event: message
data: {"message":"I'd be happy to help you find the perfect jacket! "}
event: message
data: {"message":"To give you the best recommendations:\n\n- What type of jacket are you looking for?"}

Fields:

  • message (string): A text delta to append to the agent's response
suggestions

Follow-up query suggestions generated by the agent based on the current conversation context. Display these as clickable prompts to help users continue exploring.

event: suggestions
data: {"suggestions":["show me trending items for her","what are popular tech gifts?","something unique and trending"]}

Fields:

  • suggestions (array of strings): Suggested follow-up queries the user might want to ask
category-hits

Search results grouped by category.

event: category-hits
data: {"categoryHits":[{"category":"Summer Dresses","query":"summer floral dresses","confidence":0.9,"hits":[{"_id":"dress_001","productTitle":"Red Sequin Dress","price":89.99},{"_id":"dress_002","productTitle":"Black Silk Gown","price":129.99}]}]}

Fields:

  • categoryHits (array): Array of category groups
    • category (string): Category name (e.g., "Summer Dresses", "Casual Jackets")
    • query (string): The search query the agent used to retrieve products in this category
    • confidence (number): The agent's confidence score for this category (0–1)
    • hits (array): Array of product documents matching this category
    • appliedFilter (string, optional): The filter that was applied to this category's search
    • filterDropped (boolean, optional): true if the agent's filter was dropped due to producing zero results
    • originalFilter (string, optional): The filter that was dropped, present when filterDropped is true
conversation-id

Emitted after the conversation is saved. Use this ID in subsequent requests to continue the conversation.

event: conversation-id
data: {"conversationId":"3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9"}

Fields:

  • conversationId (string): Unique identifier for this conversation
error

Emitted when an error occurs during processing.

event: error
data: {"error":"Failed to retrieve document doc_123: not found","status":404}

Fields:

  • error (string): Error message
  • status (number, optional): HTTP status code
stream-end

Marks the end of the SSE stream. No further events will be sent.

event: stream-end
data: {}

Response Event Ordering

By default, category-hits events are streamed as soon as search results are available, which means they may arrive before the message events. This allows clients to render product results immediately while the agent's text response is still being generated.

If you prefer to display category results after the agent's message (for example, to show the conversational text first), set categoriesAfterMessage to true in the payload. When enabled, category-hits events are buffered internally and sent after all message and suggestions events.


Get Conversation

Retrieve the history of a previous conversation by its ID.

Endpoint: GET /indexes/{index_name}/agentic-search/conversations/{conversation_id}

Headers:

  • x-marqo-index-id: {index_id} (required)

Path Parameters:

Parameter Type Required Description
index_name string Yes The name of your index
conversation_id string Yes The conversation ID returned from a previous converse response

Example Request:

curl 'https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/conversations/3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9' \
  --header 'x-marqo-index-id: abc123-my-ecom-store'

Example Response:

{
  "conversationId": "3fd8b45def95c8a98da1cfda23543699144cee5d9c89ae143040bca4ff0636e9",
  "conversation": [
    {
      "role": "user",
      "message": "I need outfits for a tropical vacation"
    },
    {
      "role": "agent",
      "message": "Here are some great options for a tropical getaway!",
      "categories": [
        {
          "query": "tropical vacation dresses",
          "category": "Summer Dresses",
          "confidence": 0.9,
          "hits": ["dress_001", "dress_002"]
        }
      ]
    }
  ]
}

Response Fields:

  • conversationId (string): The conversation identifier
  • conversation (array): Array of messages in chronological order
    • role (string): Either "user" or "agent"
    • message (string): The message content
    • categories (array, optional, agent only): Search categories from the agent's response
      • query (string): The search query used
      • category (string): The category name
      • confidence (number): Confidence score (0–1)
      • hits (array of strings): Product document IDs returned

Agentic Conversation Behavior Overview

Context Management

The system maintains conversation context across interactions:

  • Context Continuity: Previous conversation context is used to inform current responses
  • Product Context: When documentIds are provided, the system fetches those products and uses their information to provide more relevant responses. Use contextFields to limit which product fields are included.
  • Session Tracking: sessionId and userId help maintain context throughout a user's session

Question Triggering - Ambiguous Queries

The system automatically asks clarifying questions when user queries are ambiguous or too broad.

Examples:

  • Query: "jacket" → System asks: "What type of jacket are you looking for (winter coat, rain jacket, casual jacket, work blazer)?"
  • Query: "shoes" → System asks clarifying questions about style, occasion, or gender
  • Query: "dress" → System asks about occasion, style, or fit preferences

When Questions Are Triggered:

  • Queries that are too broad (single word product categories)
  • Queries missing important context (style, occasion, gender, features)
  • Queries that could match many different product types

Implementation Notes

Streaming Response Handling

When using the converse endpoint, you must handle Server-Sent Events (SSE). The response will stream multiple events, each containing different parts of the response.

Example: Using EventSource

EventSource does not support custom headers natively. If your setup allows the x-marqo-index-id header to be set via other means (e.g., cookies or a proxy), you can use EventSource with named event listeners:

const requestData = {
  q: "red dress",
  sessionId: "session-001",
  userId: "user-456",
};

const payload = btoa(JSON.stringify(requestData));
const url = `https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse?payload=${encodeURIComponent(payload)}`;

const eventSource = new EventSource(url);

let agentMessage = "";

eventSource.addEventListener("message", (event) => {
  const data = JSON.parse(event.data);
  agentMessage += data.message;
});

eventSource.addEventListener("category-hits", (event) => {
  const data = JSON.parse(event.data);
  console.log("Categories:", data.categoryHits);
});

eventSource.addEventListener("suggestions", (event) => {
  const data = JSON.parse(event.data);
  console.log("Suggestions:", data.suggestions);
});

eventSource.addEventListener("conversation-id", (event) => {
  const data = JSON.parse(event.data);
  console.log("Conversation ID:", data.conversationId);
});

eventSource.addEventListener("error", (event) => {
  const data = JSON.parse(event.data);
  console.error("Server error:", data.error);
});

eventSource.addEventListener("stream-end", () => {
  console.log("Full message:", agentMessage);
  eventSource.close();
});

Example: Using fetch with ReadableStream (supports custom headers)

const requestData = {
  q: "red dress",
  sessionId: "session-001",
  userId: "user-456",
};

const payload = btoa(JSON.stringify(requestData));
const url = `https://ecom.marqo-ep.ai/api/v1/indexes/my-ecom-store/agentic-search/converse?payload=${encodeURIComponent(payload)}`;

const response = await fetch(url, {
  method: "GET",
  headers: {
    "x-marqo-index-id": "abc123-my-ecom-store",
  },
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  buffer += decoder.decode(value, { stream: true });
  const parts = buffer.split("\n\n");
  buffer = parts.pop();

  for (const part of parts) {
    const eventMatch = part.match(/^event: (.+)$/m);
    const dataMatch = part.match(/^data: (.+)$/m);
    if (!eventMatch || !dataMatch) continue;

    const eventType = eventMatch[1];
    const data = JSON.parse(dataMatch[1]);

    switch (eventType) {
      case "message":
        console.log("Text delta:", data.message);
        break;
      case "category-hits":
        console.log("Categories:", data.categoryHits);
        break;
      case "suggestions":
        console.log("Suggestions:", data.suggestions);
        break;
      case "conversation-id":
        console.log("Conversation ID:", data.conversationId);
        break;
      case "error":
        console.error("Error:", data.error);
        break;
      case "stream-end":
        console.log("Stream complete");
        break;
    }
  }
}