Orchestrator API
API for feed generation, content ranking, and Thompson Sampling operations.
Base URL
https://api.vows.social/api
Endpoints
Get Personalized Feed
Generate personalized content feed for a user.
Endpoint: GET /feed/:userId
Parameters:
- userId (path) - User ID (UUID)
- limit (query) - Number of items (default: 20, max: 100)
- context (query) - Device context (mobile, desktop, tablet)
- refresh (query) - Force refresh (boolean)
Request:
Response:
{
"feed": [
{
"contentId": "content-456",
"vendorId": "vendor-789",
"vendorName": "Garden Weddings Melbourne",
"vendorType": "venue",
"imageUrl": "https://cdn.vows.social/...",
"description": "Beautiful botanical garden venue",
"region": "Melbourne",
"score": 0.92,
"reasoning": {
"discovery": 0.85,
"quality": 0.95,
"archivist": 0.90,
"serendipity": 0.75
},
"novelty": 0.8,
"isSerendipitous": false
}
],
"metadata": {
"thompsonExploration": 0.3,
"agentWeights": {
"discovery": 0.25,
"quality": 0.25,
"archivist": 0.25,
"serendipity": 0.25
},
"planningPhase": "vendor_research",
"diversityScore": 0.72,
"latency_ms": 450,
"cacheHit": false
}
}
Record Interaction
Log user interaction with content for Thompson Sampling updates.
Endpoint: POST /feed/interaction
Request:
{
"userId": "user-123",
"contentId": "content-456",
"action": "save", // view, save, share, skip, inquiry
"duration": 5.2, // seconds (for views)
"context": {
"device": "mobile",
"timeOfDay": "evening",
"sessionDuration": 180,
"position": 3 // Position in feed
}
}
Response:
{
"success": true,
"thompsonUpdated": true,
"reward": {
"overall": 0.85,
"engagement": 0.9,
"quality": 0.8,
"discovery": 0.7,
"diversity": 0.9
},
"updatedParams": {
"alpha": 15,
"beta": 3
}
}
Action Types:
| Action | Success Criteria | Reward |
|---|---|---|
view |
duration > 3s | 0.3 |
save |
Always | 0.8 |
share |
Always | 1.0 |
skip |
Always | -0.2 |
inquiry |
Always | 1.0 |
Refresh Feed
Force regenerate feed (bypasses cache).
Endpoint: GET /feed/refresh/:userId
Response:
{
"feed": [...],
"metadata": {
"refreshReason": "user_requested",
"previousCacheAge_ms": 300000,
"newGenerationTime_ms": 480
}
}
Get Thompson Sampling Parameters
Retrieve current Thompson Sampling parameters for debugging.
Endpoint: GET /feed/thompson/:userId
Response:
{
"userId": "user-123",
"parameters": {
"content-456": {
"alpha": 12,
"beta": 3,
"successRate": 0.8,
"totalSamples": 15
},
"content-789": {
"alpha": 5,
"beta": 8,
"successRate": 0.38,
"totalSamples": 13
}
},
"explorationRate": 0.3
}
Get Agent Scores
Retrieve detailed agent scoring breakdown.
Endpoint: POST /feed/agent-scores
Request:
Response:
{
"scores": {
"content-456": {
"discovery": {
"score": 0.85,
"reasoning": "High-quality emerging vendor",
"latency_ms": 120
},
"quality": {
"score": 0.95,
"reasoning": "Exceptional visual quality and authenticity",
"latency_ms": 80
},
"archivist": {
"score": 0.90,
"reasoning": "Perfect timing for venue booking phase",
"latency_ms": 100
},
"serendipity": {
"score": 0.75,
"reasoning": "Cross-regional discovery",
"latency_ms": 90
}
}
},
"metadata": {
"totalLatency_ms": 390
}
}
MAGRPO Status
Get MAGRPO training status and metrics.
Endpoint: GET /feed/magrpo/status
Response:
{
"status": "training",
"agents": {
"discovery": {
"policyVersion": "v1.23",
"lastUpdate": "2025-10-11T10:25:00Z",
"performance": 0.82,
"variance": 0.05
},
"quality": {
"policyVersion": "v1.21",
"lastUpdate": "2025-10-11T10:24:00Z",
"performance": 0.89,
"variance": 0.03
}
},
"groupAdvantage": {
"mean": 0.12,
"std": 0.18,
"convergence": 0.87
}
}
Feed Customization
Diversity Control
Control feed diversity via query parameters:
Parameters:
- diversityWeight (0.0-1.0) - How much to prioritize diversity
- minDiversity (0.0-1.0) - Minimum diversity threshold
- serendipityRate (0.0-1.0) - Rate of serendipitous content
Planning Phase Override
Manually set planning phase (for testing):
Phases:
- early_discovery (12-18 months out)
- vendor_research (6-12 months)
- booking (3-6 months)
- detail_planning (1-3 months)
- final_touches (0-1 month)
Advanced Features
A/B Testing Variants
Specify feed variant for A/B testing:
Response includes:
{
"metadata": {
"experiment": "thompson-enr",
"variant": "treatment",
"algorithmUsed": "enr_thompson_sampling"
}
}
Explainability
Get detailed explanation of ranking decisions:
Response:
{
"feed": [...],
"explanations": [
{
"contentId": "content-456",
"rank": 1,
"explanation": "Ranked #1 because:",
"factors": [
{
"factor": "High quality score",
"contribution": 0.35,
"value": 0.95
},
{
"factor": "Perfect timing for venue booking",
"contribution": 0.30,
"value": 0.90
},
{
"factor": "Strong style match",
"contribution": 0.25,
"value": 0.85
},
{
"factor": "Thompson Sampling exploration bonus",
"contribution": 0.10,
"value": 0.2
}
]
}
]
}
Performance Metrics
Latency Breakdown
Get detailed latency metrics:
Response:
{
"feed": [...],
"metrics": {
"total_ms": 450,
"breakdown": {
"user_embedding": 120,
"candidate_retrieval": 80,
"agent_scoring": 180,
"thompson_sampling": 50,
"deduplication": 20
},
"cacheHits": 12,
"cacheMisses": 8
}
}
Error Handling
Feed Generation Failed
{
"error": {
"code": "FEED_GENERATION_FAILED",
"message": "Unable to generate feed for user",
"details": {
"reason": "No candidate content available",
"fallback": "trending_content_used"
}
},
"fallbackFeed": [...],
"metadata": {
"isFallback": true
}
}
Thompson Sampling Error
{
"error": {
"code": "THOMPSON_SAMPLING_ERROR",
"message": "Thompson Sampling failed, using greedy ranking",
"details": {
"error": "Insufficient data for content-456"
}
},
"feed": [...],
"metadata": {
"rankingMethod": "greedy_fallback"
}
}
Usage Examples
TypeScript
import { VowsClient } from '@vows/sdk';
const client = new VowsClient({ apiKey: API_KEY });
// Get feed
const feed = await client.feed.get('user-123', {
limit: 20,
context: 'mobile',
diversityWeight: 0.8
});
// Record interaction
await client.feed.recordInteraction({
userId: 'user-123',
contentId: feed.feed[0].contentId,
action: 'save',
duration: 5.2
});
// Get agent scores
const scores = await client.feed.getAgentScores('user-123', [
'content-456',
'content-789'
]);
Python
from vows import VowsClient
client = VowsClient(api_key=API_KEY)
# Get feed
feed = client.feed.get(
user_id='user-123',
limit=20,
context='mobile'
)
# Record interaction
client.feed.record_interaction(
user_id='user-123',
content_id=feed['feed'][0]['contentId'],
action='save',
duration=5.2
)
cURL
# Get feed
curl "https://api.vows.social/api/feed/user-123?limit=20" \
-H "Authorization: Bearer $TOKEN"
# Record interaction
curl -X POST https://api.vows.social/api/feed/interaction \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"userId": "user-123",
"contentId": "content-456",
"action": "save",
"duration": 5.2
}'
# Refresh feed
curl "https://api.vows.social/api/feed/refresh/user-123" \
-H "Authorization: Bearer $TOKEN"
Webhooks
Subscribe to feed events:
Events:
- feed.generated - New feed created
- interaction.recorded - User interaction logged
- thompson.updated - Thompson parameters updated
Payload:
{
"event": "feed.generated",
"userId": "user-123",
"feedSize": 20,
"diversityScore": 0.72,
"latency_ms": 450,
"timestamp": "2025-10-11T10:30:00Z"
}
Related APIs
- Foundation Model API - Provides embeddings
- Vector Store API - Content retrieval
- Quality API - Quality scoring