← Blog

How to Build a Claude-Powered Product Recommendation Engine

2026-11-06 · 5 min read · SubToAPI Team

How to Build a Claude-Powered Product Recommendation Engine

Building a product recommendation engine with Claude means using the model's reasoning ability to match users to products based on natural-language context — browsing history, stated preferences, past purchases — instead of relying purely on collaborative filtering or embedding similarity. You feed Claude structured product data and user context, it returns ranked, explainable recommendations, and you integrate that output into your product flow via API.

This approach works best as a layer on top of (not a replacement for) your existing catalog and retrieval system. Claude is good at reasoning over a shortlist of candidates and explaining why something fits; it's not a vector database. The practical architecture is: retrieve candidates with your existing search/filter logic, then let Claude re-rank, personalize, and justify the top results. Below is a step-by-step guide to building this.

Step 1: Narrow the candidate pool before calling Claude

Never send your entire catalog to the model. Use your existing filters (category, price range, stock availability) or a vector search to cut the candidate set down to 20–50 products. This keeps latency and token cost under control and gives Claude a manageable reasoning task instead of a search problem.

const candidates = await db.products.find({
  category: userContext.category,
  inStock: true,
}).limit(40);

Step 2: Structure the prompt for ranking, not generation

The core prompt pattern has three parts: user context, the candidate list as structured data, and explicit output format instructions. Being explicit about the JSON schema you want back saves you a parsing headache later.

const prompt = `
You are a product recommendation assistant. Given the user context and
a list of candidate products, return the top 5 most relevant products
ranked by fit, with a one-sentence reason for each.

User context:
${JSON.stringify(userContext)}

Candidate products:
${JSON.stringify(candidates)}

Return only valid JSON in this format:
[{"productId": "", "reason": ""}]
`;

Step 3: Call the API and parse the response

If you're using Claude through SubToAPI, the request looks like a standard Messages API call — you get your own sub_live_... key from the dashboard after signup, and usage is tracked per key without needing separate Anthropic billing setup.

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 500,
    "messages": [
      {"role": "user", "content": "PROMPT_HERE"}
    ]
  }'

Parse the response, validate it against your schema, and fall back gracefully (e.g., return the unranked candidate list) if the model returns malformed JSON. For the full request/response shape, see the messages docs.

Step 4: Add user signals for real personalization

Generic "here are 5 products" output isn't personalization — the quality comes from what you put in userContext. Useful signals include:

Keep this context compact. A dense, well-labeled JSON object of 10–15 fields outperforms a verbose paragraph of raw behavioral logs.

Step 5: Make recommendations explainable

One of Claude's real advantages over a pure embedding-similarity approach is that it can generate a reason alongside each recommendation. "Recommended because it matches your recent search for noise-cancelling headphones and fits your stated budget" converts better than an unexplained product tile. Ask for this explicitly in your prompt's output schema, and surface it in the UI — it also gives you a debugging signal when recommendations seem off.

Step 6: Stream for large candidate sets or multi-step reasoning

If you're asking Claude to reason over a larger set of products, or to produce a longer explanation per item, streaming avoids making users stare at a blank loading state. Render recommendations as they arrive rather than waiting for the full JSON payload.

const response = await fetch("https://api.subtoapi.app/v1/messages", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "claude-sonnet-4-5",
    max_tokens: 800,
    stream: true,
    messages: [{ role: "user", content: prompt }],
  }),
});

See the streaming docs for handling server-sent events on the client side.

Step 7: Use tool calling for dynamic catalog lookups

If your catalog changes frequently or recommendations need live inventory/pricing checks, tool use lets Claude call a function mid-reasoning rather than relying on a static candidate list you pasted into the prompt.

{
  "name": "get_product_details",
  "description": "Fetch current price and stock for a product ID",
  "input_schema": {
    "type": "object",
    "properties": {
      "productId": { "type": "string" }
    },
    "required": ["productId"]
  }
}

This is useful when recommendations need to reflect real-time stock levels or flash-sale pricing. Details on defining and handling tools are in the tool use docs.

Step 8: Cache and monitor

Recommendation requests are often repeatable (same user segment, same category browse) — cache responses for a short TTL to cut latency and cost. Also track which recommendations get clicked or purchased, and feed that back into your candidate-selection logic over time; Claude's ranking quality is only as good as the candidates and context you give it.

A note on getting started quickly

If you don't already have Claude API access set up, SubToAPI wraps it into a single HTTPS API with per-key usage metadata, so you can see exactly how many tokens your recommendation engine is consuming per request, per team member, or per environment. Start with the quickstart guide, and check pricing for the Solo, Team, and Scale plans — there's a free trial at signup if you want to prototype the ranking prompt before committing.

questions

Do I need a vector database to use Claude for recommendations? Not strictly, but it helps at scale. Use a vector search or basic filters to narrow your catalog to a manageable candidate set (20–50 items), then let Claude re-rank and personalize within that set.

How do I keep recommendation latency low? Limit candidate list size, cache repeatable requests with a short TTL, and use streaming for longer outputs so users see partial results instead of waiting for the full response.

Can Claude recommend products it wasn't given in the prompt? No — it only reasons over the candidates you provide. If it needs live data like current stock or pricing, use tool calling to let it fetch that information during the request instead of hardcoding it into the prompt.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →