Install
An install is a (userId, agentId) row recording that a user clicked the "install" button. It is idempotent — calling install twice on the same agent does nothing the second time.
Schema (agent_installs)
| Column | Type | Notes |
|---|---|---|
id | UUID | PK |
agentId | UUID | FK → agents |
userId | UUID | FK → user (better-auth) |
installedAt | timestamptz |
Unique on (agentId, userId).
Endpoints
| Verb | Path | Guard |
|---|---|---|
| POST | /agents/:agentId/install | bearer |
Returns { installed: true }. The endpoint is intentionally minimal — no deferred work, no fanout.
What install does NOT do
- It does not provision anything on the agent side.
- It does not create a subscription.
- It does not open the agent's frontend.
- It does not trigger any webhook.
Why it exists
Two purposes:
- Social proof — the catalog displays
installscount per agent. It's a vanity metric. - User dashboard — the marketplace UI shows "agents you've installed" as a quick-access list.
A user can be "installed" on an agent without an active subscription — that's a deliberate signal of intent.
Subscription vs install
| Concern | Install | Subscription |
|---|---|---|
| Implies payment? | No | Yes (for paid tiers) |
| Implies usage access? | No | Yes |
| Idempotent? | Yes — UPSERT on (userId, agentId) | One active row per (userId, agentId), enforced by partial unique index |
| Auto-created? | No, user clicks "install" | Yes, on first subscribe |
| Source of truth for tier? | N/A | Yes — user_agent_subscriptions.tierId |
Most users will have install rows for agents they've signed up to try, plus subscription rows for the ones they're actively paying for.