Review submission
Upsert semantics
(agentId, userId) is unique. A user submitting a second review replaces their previous one (no separate "edit" UX needed). createdAt is preserved on the upsert; updatedAt advances.
Aggregate refresh
The agent's rating and reviewCount are computed at read time (no denormalized counter). After a write, the UI invalidates the useAgent query so the next read returns the updated aggregate.
Deleting
Pagination
GET /agents/:agentId/reviews?cursor=&limit=20 cursor-paginates by createdAt DESC. Stable across writes.