Best Practices for AI Agent Design with BuyWhere
Guidelines for designing effective AI agents that integrate with the BuyWhere API.
1. Error Handling and Resilience
Always Implement Retry Logic
Network issues and rate limits are inevitable. Implement robust retry mechanisms with exponential backoff.
import time
import random
from typing import Callable, Any
def resilient_api_call(func: Callable, *args, max_retries: int = 3, **kwargs) -> Any:
"""Execute API call with exponential backoff retry logic."""
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_retries - 1:
raise
# Exponential backoff with jitter
wait_time = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait_time)
Handle Different Error Types Appropriately
Different HTTP status codes require different responses:
- 4xx Errors (Client errors): Usually indicate a problem with the request that needs fixing before retrying
- 5xx Errors (Server errors): Often temporary, safe to retry with backoff
- 429 Rate Limited: Respect the Retry-After header
- 401/403 Auth issues: Check credentials and permissions
2. Performance Optimization
Cache Aggressively
BuyWhere data is relatively static (updates every 5-10 minutes). Implement smart caching:
from cachetools import TTLCache
import time
# Different TTLs for different data types
product_cache = TTLCache(maxsize=1000, ttl=600) # 10 minutes for product details
search_cache = TTLCache(maxsize=500, ttl=60) # 1 minute for search results
deal_cache = TTLCache(maxsize=100, ttl=300) # 5 minutes for deals
Batch Operations
Minimize API calls by using batch endpoints:
# Instead of 100 individual calls:
# for product_id in product_ids:
# product = api.get_product(product_id)
# Use batch endpoint:
products = api.get_products_batch(product_ids)
Optimize Search Queries
Be specific with your search parameters to reduce unnecessary data transfer:
# Good: Specific query with filters
results = api.search_products(
query="iPhone 15 Pro 256GB",
category="electronics",
max_price=1500,
limit=10
)
# Less efficient: Broad query requiring client-side filtering
results = api.search_products(query="phone", limit=100)
# Then filter client-side for iPhone 15 Pro under $1500
3. User Experience Best Practices
Provide Clear Feedback
Keep users informed about what the agent is doing:
def search_with_feedback(query: str):
print(f"🔍 Searching for '{query}'...")
results = api.search_products(query)
print(f"✅ Found {len(results)} products")
return results
Handle Edge Cases Gracefully
Anticipate and handle common edge cases:
- No results found
- Partial results (some items unavailable)
- Timeout scenarios
- Invalid user input
Maintain Conversation Context
For conversational agents, remember important context:
class ShoppingAgent:
def __init__(self):
self.last_search_results = []
self.user_preferences = {}
self.conversation_history = []
def handle_follow_up(self, user_input: str):
# Use last search results for "show me more details on the second one"
# Use user preferences for filtering
pass
4. Monitoring and Observability
Log Key Metrics
Track important metrics for debugging and optimization:
import logging
from datetime import datetime
logger = logging.getLogger(__name__)
class MetricsTracker:
def __init__(self):
self.request_count = 0
self.error_count = 0
self.rate_limit_hits = 0
self.start_time = datetime.now()
def log_request(self, endpoint: str, status_code: int, response_time: float):
self.request_count += 1
if status_code >= 400:
self.error_count += 1
if status_code == 429:
self.rate_limit_hits += 1
logger.info(
f"API Request: {endpoint} | Status: {status_code} | "
f"Time: {response_time:.2f}s | "
f"Total Requests: {self.request_count}"
)
Set Up Alerts
Configure alerts for abnormal patterns:
- Sudden increase in error rates
- Rate limit hits exceeding thresholds
- Unusually slow response times
- Authentication failures
5. Security Considerations
Protect API Keys
Never expose API keys in client-side code or public repositories:
# ❌ Bad: Hardcoded in source code
API_KEY = "bw_live_abc123"
# ✅ Good: Environment variables
import os
API_KEY = os.getenv("BUYWHERE_API_KEY")
# ✅ Better: Secret management services
# AWS Secrets Manager, HashiCorp Vault, etc.
Validate and Sanitize Inputs
Prevent injection attacks and unexpected behavior:
def sanitize_search_query(query: str) -> str:
# Remove potentially harmful characters
# Limit length
# Normalize whitespace
return query.strip()[:100]
Use Principle of Least Privilege
Only request the permissions your agent actually needs:
- Read-only access for shopping agents
- Specific endpoint access rather than wildcards
- Separate keys for different environments (dev/test/prod)
6. Testing Strategies
Unit Test with Mocks
Test your agent logic without hitting the real API:
import unittest
from unittest.mock import Mock, patch
class TestShoppingAgent(unittest.TestCase):
@patch('buywhere_api.Client')
def test_search_handles_no_results(self, mock_client):
# Setup mock to return empty results
mock_instance = Mock()
mock_instance.search_products.return_value = []
mock_client.return_value = mock_instance
# Test agent behavior
agent = ShoppingAgent(api_key="test_key")
results = agent.search("nonexistent product xyz123")
self.assertEqual(len(results), 0)
Integration Test Against Staging
Validate real API interactions in a controlled environment:
def test_real_api_integration():
# Use staging environment or test API key
api = BuyWhereAPI(
base_url="https://staging-api.buywhere.ai",
api_key="bw_free_test_key"
)
# Test basic functionality
results = api.search_products("laptop", limit=1)
assert len(results) >= 0 # Should not crash
# Test rate limit handling
# ... etc
Load Test Your Agent
Ensure your agent performs well under expected load:
# Simulate multiple concurrent users
import concurrent.futures
import time
def simulate_user_session():
# Simulate a typical user interaction
pass
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(simulate_user_session) for _ in range(50)]
results = [f.result() for f in futures]
7. Documentation and Maintenance
Document Your Agent's Capabilities
Clearly document what your agent can and cannot do:
# My Shopping Agent Capabilities
✅ Can do:
- Search for products by name, category, or brand
- Compare prices across different retailers
- Notify users of price drops on watched items
- Handle follow-up questions about previous search results
❌ Cannot do:
- Make purchases on behalf of users
- Access user's personal shopping history (without permission)
- Guarantee real-time price accuracy (data updates every 5-10 minutes)
Keep Dependencies Updated
Regularly update your dependencies to get security fixes and new features:
# Check for outdated packages
pip list --outdated
# Update BuyWhere SDK
pip install --upgrade buywhere-sdk
Monitor Deprecation Notices
Stay informed about API changes:
- Subscribe to the BuyWhere developer newsletter
- Check the changelog regularly
- Test against beta/staging environments before upgrades