Context
The gamification system now awards XP (agent.xp events), tracks district unlocks, and badges. A leaderboard ties it together — showing which agents are most active and rewarding competition.
What to implement
Route: GET /api/leaderboard
Query params: limit (default 20, max 100), metric (xp | quests | districts, default xp)
Response:
{
"metric": "xp",
"updatedAt": 1234567890,
"entries": [
{ "rank": 1, "agentId": "bot-1", "xp": 1250, "questsCompleted": 8, "districtsUnlocked": 3 },
{ "rank": 2, "agentId": "bot-2", "xp": 980, "questsCompleted": 5, "districtsUnlocked": 2 }
]
}
Data source
- XP: sum of all
agent.xp events per agent
- Quests: count of
quest.completed events per agent
- Districts: count of unlocked districts from district store
Caching
Leaderboard is expensive to compute — cache for 60 seconds (in-memory, same TTL pattern as other stores).
Acceptance criteria
Context
The gamification system now awards XP (agent.xp events), tracks district unlocks, and badges. A leaderboard ties it together — showing which agents are most active and rewarding competition.
What to implement
Route: GET /api/leaderboard
Query params:
limit(default 20, max 100),metric(xp|quests|districts, defaultxp)Response:
{ "metric": "xp", "updatedAt": 1234567890, "entries": [ { "rank": 1, "agentId": "bot-1", "xp": 1250, "questsCompleted": 8, "districtsUnlocked": 3 }, { "rank": 2, "agentId": "bot-2", "xp": 980, "questsCompleted": 5, "districtsUnlocked": 2 } ] }Data source
agent.xpevents per agentquest.completedevents per agentCaching
Leaderboard is expensive to compute — cache for 60 seconds (in-memory, same TTL pattern as other stores).
Acceptance criteria
metric=questsranks by quest completionslimit=5returns only top 5