← Back to documentation

SDK Quickstart — Agent Builders (OpenAI, LangChain, CrewAI)

v1Updated: April 19, 2026Finalized — Ready for Aria (DevRel) reviewBy: Milo (Backend Engineer — SDK & Developer Tools)

Get started with the BuyWhere SDK for AI agent development

SDK Quickstart — Agent Builders (OpenAI, LangChain, CrewAI)

Version: 1.0
Last Updated: 2026-04-19
Author: Milo (Backend Engineer — SDK & Developer Tools)
Status: Finalized — Ready for Aria (DevRel) review


Executive Summary

This document overhauls the BuyWhere developer quickstart for the three dominant AI agent frameworks. Goal: agent developer gets from zero to first product query in under 5 minutes, using their preferred framework.

Key changes from v0.1:

  • Framework-first structure (OpenAI → LangChain → CrewAI), not language-first
  • Complete tool-calling loop patterns for OpenAI
  • Proper LangChain Tool + Toolkit implementations
  • First-ever CrewAI integration guide
  • Unified 5-minute quickstart per framework
  • API gap analysis with优先级

Quickstart Outline

Section 1 — 5-Minute Quickstart (Per Framework)

Each framework section follows: Install → API Key → First Query → Next Steps

  1. OpenAI Assistants APIbuywhere tool definition + function-calling loop
  2. LangChainBuyWhereTool as @tool decorator + agent toolkit
  3. CrewAIBuyWhereTool as CrewAI Tool with async execution

Section 2 — Core Patterns

  1. Auth + Basic Search (copy-paste ready)
  2. Compare + Best-Price Workflow
  3. Affiliate Link Generation
  4. Batch Search (parallel queries for agents)

Section 3 — Framework-Specific Gap Analysis

Identified gaps per framework with优先级 and Rex action items.

Section 4 — Implementation Recommendations

SDK package structure, versioning, and publish checklist.


Section 1: 5-Minute Quickstarts

OpenAI Assistants — 5 Minutes to First Query

Step 1: Install

npm install @buywhere/sdk @buywhere/openai openai

Step 2: Configure

import { createBuyWhereOpenAIAdapter, getAllTools } from '@buywhere/openai';
import OpenAI from 'openai';

const buywhere = createBuyWhereOpenAIAdapter({
  apiKey: process.env.BUYWHERE_API_KEY!
});

const openai = new OpenAI();
const tools = getAllTools();

Step 3: Tool Executor

async function executeToolCall(toolName: string, args: Record<string, unknown>) {
  const result = await buywhere.callTool(toolName, args);
  if (!result || (Array.isArray(result) && result.length === 0)) {
    return "No products found.";
  }
  
  const formatProduct = (p: any) => 
    `- ${p.name}: ${p.currency} ${p.price} on ${p.merchant} [${p.rating ?? 'N/A'}★] (Buy: ${p.url})`;
  
  if (Array.isArray(result) && result[0]?.products) {
    return result[0].products.slice(0, 5).map(formatProduct).join('\n');
  }
  return JSON.stringify(result, null, 2);
}

Step 4: Assistant Loop

const assistant = await openai.beta.assistants.create({
  name: "Shopping Agent",
  instructions: "You help users find the best products and prices using BuyWhere search.",
  tools: tools,
  model: "gpt-4o"
});

const thread = await openai.beta.threads.create();

async function runAssistant(message: string) {
  await openai.beta.threads.messages.create({
    thread_id: thread.id,
    role: "user",
    content: message
  });

  let run = await openai.beta.threads.runs.createAndPoll({
    thread_id: thread.id,
    assistant_id: assistant.id
  });

  while (run.status === "requires_action") {
    const toolCalls = run.required_action?.submit_tool_outputs?.tool_calls ?? [];
    const toolOutputs: Array<{ tool_call_id: string; output: string }> = [];

    for (const toolCall of toolCalls) {
      const args = JSON.parse(toolCall.function.arguments);
      const output = await executeToolCall(toolCall.function.name, args);
      toolOutputs.push({ tool_call_id: toolCall.id, output });
    }

    run = await openai.beta.threads.runs.submitToolOutputsAndPoll({
      thread_id: thread.id,
      run_id: run.id,
      tool_outputs: toolOutputs
    });
  }

  return run;
}

// First query
const result = await runAssistant("Find me the best wireless headphones in Singapore under SGD 500");

LangChain — 5 Minutes to First Query

Step 1: Install

pip install buywhere-sdk langchain langchain-openai

Step 2: Define the Tool

from buywhere import BuyWhereClient
from langchain.tools import tool
import os

client = BuyWhereClient(api_key=os.environ["BUYWHERE_API_KEY"])

@tool
def search_products(query: str, country: str = "SG", limit: int = 5) -> str:
    """Search BuyWhere product catalog for products by query.
    
    Args:
        query: Natural language search query (e.g., 'sony wh-1000xm5')
        country: ISO country code (SG, MY, PH, US, VN, TH)
        limit: Number of results to return (1-100)
    
    Returns:
        Formatted list of products with name, price, merchant, rating, and buy link.
    """
    results = client.search(query=query, country=country, limit=limit)
    if not results["items"]:
        return "No products found for this query."
    
    lines = [f"Found {results['total']} products. Top results:"]
    for p in results["items"][:limit]:
        lines.append(
            f"- {p['name']}: {p['currency']} {p['price']} "
            f"on {p['source']} ★{p.get('rating', 'N/A')} "
            f"[Buy]({p.get('affiliate_url', p.get('buy_url', ''))})"
        )
    return "\n".join(lines)

@tool
def compare_prices(product_ids: list[int]) -> str:
    """Compare product prices across multiple platforms.
    
    Args:
        product_ids: List of BuyWhere product IDs (max 10)
    
    Returns:
        Formatted comparison showing best price per product.
    """
    comparison = client.compare(product_ids)
    lines = []
    for c in comparison["comparisons"]:
        best = c.get("best_price")
        if best:
            lines.append(
                f"- {c['product_name']}: Best price "
                f"{best['currency']} {best['price']} on {best['source']} "
                f"[Buy]({best.get('affiliate_url', best.get('buy_url', ''))})"
            )
        else:
            lines.append(f"- {c['product_name']}: No prices found.")
    return "\n".join(lines) if lines else "No comparison data available."

Step 3: Bind to LLM

from langchain_openai import ChatOpenAI
from langchain.agents import initialize_agent, AgentType

llm = ChatOpenAI(model="gpt-4o")
tools = [search_products, compare_prices]

agent = initialize_agent(
    tools=tools,
    llm=llm,
    agent=AgentType.OPENAI_FUNCTIONS,
    verbose=True
)

# First query
agent.run("Find me wireless headphones in Singapore and compare prices if there are multiple options")

LangChain Toolkit (recommended for production):

# For agents that need multiple BuyWhere tools
class BuyWhereToolkit:
    def __init__(self, api_key: str):
        self.client = BuyWhereClient(api_key=api_key)
    
    def get_tools(self):
        return [
            search_products,
            compare_prices,
            # Add more tools as needed
        ]

CrewAI — 5 Minutes to First Query

Step 1: Install

pip install buywhere-sdk crewai crewai-tools

Step 2: Define Tools

from crewai_tools import BaseTool
from buywhere import BuyWhereClient
from pydantic import Field
import os

client = BuyWhereClient(api_key=os.environ["BUYWHERE_API_KEY"])

class BuyWhereSearchTool(BaseTool):
    name: str = "buywhere_search"
    description: str = "Search BuyWhere product catalog. Input should be a dict with 'query' (required), 'country' (optional, default SG), 'limit' (optional, default 5)."
    
    def _run(self, query: str, country: str = "SG", limit: int = 5) -> str:
        results = client.search(query=query, country=country, limit=limit)
        if not results["items"]:
            return "No products found."
        
        lines = []
        for p in results["items"][:limit]:
            lines.append(
                f"- {p['name']}: {p['currency']} {p['price']} "
                f"on {p['source']} ★{p.get('rating', 'N/A')}"
            )
        return "\n".join(lines)

class BuyWhereCompareTool(BaseTool):
    name: str = "buywhere_compare"
    description: str = "Compare product prices across platforms. Input should be a dict with 'product_ids' (list of BuyWhere product IDs)."
    
    def _run(self, product_ids: list) -> str:
        comparison = client.compare(product_ids)
        lines = []
        for c in comparison["comparisons"]:
            best = c.get("best_price")
            if best:
                lines.append(
                    f"- {c['product_name']}: {best['currency']} {best['price']} on {best['source']}"
                )
        return "\n".join(lines) if lines else "No comparison data."

search_tool = BuyWhereSearchTool()
compare_tool = BuyWhereCompareTool()

Step 3: Create Agents

from crewai import Agent, Task, Crew

researcher = Agent(
    role="Product Researcher",
    goal="Find the best products based on user requirements",
    backstory="Expert at finding and comparing products using BuyWhere",
    tools=[search_tool],
    verbose=True
)

comparer = Agent(
    role="Price Comparer",
    goal="Compare product prices across platforms to find the best deal",
    backstory="Expert at analyzing prices and finding the best value",
    tools=[compare_tool],
    verbose=True
)

Step 4: Create Tasks and Crew

task1 = Task(
    description="Search for {product_query} in {country}",
    agent=researcher,
    expected_output="List of top 5 products with name, price, merchant, and rating"
)

task2 = Task(
    description="Compare prices for the top products found",
    agent=comparer,
    expected_output="Best price recommendation with platform comparison"
)

crew = Crew(
    agents=[researcher, comparer],
    tasks=[task1, task2],
    verbose=True
)

result = crew.kickoff(inputs={"product_query": "wireless headphones", "country": "SG"})

Section 2: Core Patterns

Pattern 1: Minimal Search (5 lines)

Python (httpx direct):

import httpx
response = httpx.get(
    "https://api.buywhere.ai/v1/products/search",
    params={"q": "wireless headphones", "country": "SG", "limit": 5},
    headers={"Authorization": f"Bearer {api_key}"}
)
for p in response.json()["items"]:
    print(f"{p['name']} — {p['currency']} {p['price']}")

TypeScript (fetch):

const res = await fetch("https://api.buywhere.ai/v1/products/search?q=wireless+headphones&country=SG&limit=5", {
  headers: { Authorization: `Bearer ${apiKey}` }
});
const { items } = await res.json();
items.forEach(p => console.log(`${p.name} — ${p.currency} ${p.price}`));

Pattern 2: Compare + Best Deal

# Search → narrow to top 5 → batch compare → surface best deal
results = client.search("sony wh-1000xm5", country="SG", limit=10)
top5_ids = [p["id"] for p in results["items"][:5]]

comparison = client.compare(top5_ids)
for c in comparison["comparisons"]:
    best = c.get("best_price")
    if best:
        print(f"{c['product_name']}: {best['currency']} {best['price']} on {best['source']}")

Pattern 3: Affiliate Link for Monetization

results = client.search("iphone 15 pro 256gb", country="SG", limit=3)
top = min(results["items"], key=lambda p: float(p["price"]))

recommendation = {
    "product": top["name"],
    "price": f"{top['currency']} {top['price']}",
    "buy_link": top.get("affiliate_url", top.get("buy_url")),  # Use for monetization
    "merchant": top["source"],
    "rating": top.get("rating"),
    "in_stock": top.get("in_stock")
}

Section 3: Framework-Specific Gap Analysis

OpenAI Assistants API

GapDescriptionPriorityRex Action
No streaming support in tool loopReal-time token display unavailable during tool executionMediumAdd streaming callback support to tool executor pattern
No vision/image inputProduct images not processedLowDocument image_url field usage separately
Rate limit handlingNo built-in retry with backoff in tool executorHighAdd @retry decorator to execute_buywhere_search

LangChain

GapDescriptionPriorityRex Action
No official BuyWhere ToolkitDevelopers must copy-paste tool definitionsHighPublish buywhere-langchain package
Async support@tool decorator is sync-only; async agents need AsyncToolMediumAdd BuyWhereAsyncTool base class
Structured outputcompare returns nested dicts; LangChain prefers PydanticMediumAdd Pydantic models to SDK

CrewAI

GapDescriptionPriorityRex Action
No BuyWhere Tools libraryFirst-ever integration guide neededHighCreate and publish buywhere-crewai-tools
BaseTool inheritance complexityCrewAI tools require specific signatureMediumProvide working BaseTool subclass examples
Parallel task executionNo pattern for agents working simultaneouslyMediumDocument task dependency graph

Section 4: API Gaps (Cross-Framework)

Critical (Blocks Beta Launch)

  1. Batch search endpoint missing — Agents often need 3-5 queries in parallel. No /v1/products/batch-search.

    • Workaround: Use asyncio.gather with multiple client.search() calls
    • Fix: Rex to add batch endpoint
  2. Path inconsistency for best-price — Blog uses /v2/agents/best-price, docs show GET /v1/products/best-price.

    • Workaround: Use /v1/products/best-price (documented)
    • Fix: Rex to align v2 path or deprecate

High (SDK Beta)

  1. UTM/tracking parameter append — Cannot append custom UTM to affiliate_url.

    • Workaround: None (affiliate tracking not customizable)
    • Fix: Rex to add ?utm_* passthrough to affiliate endpoint
  2. POST /v1/products/compare/diff undocumented — Only compare is in main docs; diff only in TypeScript types.

    • Fix: Rex to document both compare and compare/diff

Medium (SDK v0.2)

  1. Price history endpoint — Agents cannot say "price at 90-day low".

    • Fix: Rex to implement /v1/products/{id}/price-history
  2. Stock granularityin_stock: boolean but agents want low/medium/high urgency.

    • Fix: Rex to add stock_level field

Low (SDK v1.0)

  1. Webhooks — Docs show "Coming Soon" but no ETA.
    • Fix: Rex to provide timeline

Section 5: Implementation Recommendations

SDK Package Structure

buywhere-sdk/
├── src/
│   ├── client.py          # BuyWhereClient (httpx-based)
│   ├── tools/
│   │   ├── __init__.py
│   │   ├── openai_tools.py   # OpenAI function calling adapters
│   │   ├── langchain_tools.py # LangChain @tool decorators
│   │   └── crewai_tools.py    # CrewAI BaseTool subclasses
│   └── models.py           # Pydantic models for typed responses
├── package.json            # For npm variant
└── pyproject.toml

buywhere-mcp/
├── src/
│   └── index.ts           # MCP server implementation
├── package.json
└── smithery.yaml

Publish Checklist (for Rex/Board)

  • buywhere-sdk Python package to PyPI
  • buywhere-sdk TypeScript package to npm (buywhere or @buywhere/sdk)
  • buywhere-mcp to npm (blocked: needs npm automation token with 2FA bypass — see BUY-2433)
  • buywhere-langchain package (future)
  • buywhere-crewai-tools package (future)

Documentation Priority

  1. Now (Day 45): This quickstart doc + existing docs/index.md
  2. Day 50: Framework-specific integration guides (OpenAI, LangChain, CrewAI)
  3. Day 60: API reference with TypeScript types fully populated

Prepared by Milo — Backend Engineer (SDK & Developer Tools)
Review: Rex (API alignment), Aria (DevRel content review)