Agent-native onboarding — zero to first routed completion in 2 API calls, no invite, no email, no human
2026-07-11
LOCKSTEP TRACEABILITY MATRIX --- api_endpoints: [ "POST /v1/register (invite_code now optional — sandbox path)", "POST /v1/account/verify-email", "POST /v1/account/verify-email/confirm", "POST /v1/signup (typed 503 when email delivery unavailable)", ] sdk_methods_updated: [ "BrainstormRouter.register() — inviteCode/adminEmail now optional (TS + Python, sync + async)", "system.account_verify_email.* — auto-generated via gen:contract", ] mcp_tools_updated: ["none — registration is pre-auth; discovery surfaces updated instead"] ---
What We Built
An autonomous agent can now go from discovering BrainstormRouter to a successful routed completion in two API calls with no human in the loop: POST /v1/register {tenant_name, accept_tos} returns an instantly-active sandbox tenant with a community-tier br_live_ key, and the first POST /v1/chat/completions succeeds with zero BYOK (a simulated completion until a provider key is registered). The response advertises its own limits and a graduated upgrade ladder (email verify → $5/day standard tier via the new /v1/account/verify-email endpoints; claim URL → full dashboard account; invite code → full tenant at registration).
Every previously-dead signup path was also fixed: /v1/signup now returns a typed 503 ErrorEnvelope (email_delivery_unavailable, recovery.action: "use_alternate_endpoint") instead of claiming "code sent" when the deployment can't deliver email — and the email send is now awaited, never fire-and-forget. Dashboard OAuth provisioning auto-activates new tenants as sandbox when BRAINSTORMROUTER_OPEN_SIGNUP=1 (one-env-var rollback to the legacy pending-approval flow), finally matching what the quickstart docs have promised since March.
Why It Matters
Before this, all three signup paths hard-stopped an unattended agent: /v1/register demanded an admin-minted invite code, /v1/signup needed an email inbox AND silently never sent the code in production (no RESEND_API_KEY in the task definition, log.warn only), and dashboard OAuth parked new tenants in manual pending_approval — contradicting the docs. Agents discovering BR through its own MNI surfaces were led straight into these dead ends and gave up. For a platform whose persona is AI agents, onboarding IS the product surface.
How It Works
No new systems — the sandbox path composes what already existed. The one real plumbing gap was createApiKeyInTransaction having no tier parameter despite the column and enforcement middleware existing since March:
- Community-tier middleware (
src/api/middleware/community-tier.ts) enforces 100 req/day, 100K tokens/day, 2 concurrent, cost-first routing ontier="community"keys — sandbox keys are minted with that tier (limits now exported asCOMMUNITY_TIER_LIMITSso the register response advertises the same numbers the middleware enforces). - Budget killswitch bounds spend via
budget_limit_usd: 2.00 / dailyon the key. - Sandbox simulator answers unkeyed completions (a completion-shaped mock, model
brainstorm/sandbox) — no real provider is ever touched without BYOK. - Claim tokens (identity bridge) remain the dashboard upgrade path.
- ErrorEnvelope gained one recovery action (
use_alternate_endpoint) and one code (email_delivery_unavailable).
Abuse is bounded in Redis with the same pattern as the existing register limiter: 5/h per IP overall, 3/day per IP for no-invite registrations, and a global daily circuit breaker (BRAINSTORMROUTER_SANDBOX_DAILY_CAP, default 200) that 429s with quota_reset_at_iso. Platform fleet-spend exposure from unkeyed sandbox tenants: $0 — verified live 2026-07-12: without BYOK, completions return a simulated response and never touch a real provider. The $2/day key budget only governs the tenant's own BYOK spend. No CAPTCHA/PoW — those block exactly the persona being onboarded.
The tier upgrade reuses email_verification_tokens (new nullable tenant_id column, migration v64): POST /v1/account/verify-email sends a code bound to the calling tenant; /confirm promotes all community keys to standard tier ($5/day) and the tenant from plan=sandbox to free in one transaction.
Discovery surfaces were rewritten so the FIRST path an agent reads is the one that works unattended: llms.txt bootstrap front-matter now points at /v1/register, agents.json declares requires_invite_code: false with a full sandbox block, and the agent playbook leads with the one-call sandbox flow.
The Numbers
- 2 API calls from zero to first routed completion (was: impossible without human intervention)
- 3 signup paths fixed (register, signup, OAuth provision)
- $0 platform fleet-spend exposure (unkeyed sandbox completions are simulated); per-tenant $2/day budget on their own BYOK spend
- 1 plumbing change unlocked it all (tier param on key creation)
Lockstep Checklist
- [x] API Routes:
/v1/register(optional invite),/v1/account/verify-email+/confirm(new),/v1/signup(typed 503) - [x] TS SDK:
RegistrationParams.inviteCode/adminEmailoptional,RegistrationResult.limits/upgrade_paths; generated resources viapnpm gen:contract - [x] Python SDK:
register()sync + async signatures updated; generated resources viapnpm gen:contract - [x] MCP/agents.json: agents.json registration + sandbox blocks; llms.txt + agent playbook reordered (registration is pre-auth, so no MCP tool changes)
- [x] Migration: v64 —
email_verification_tokens.tenant_id - [x] Ops: terraform/fargate-minimal —
RESEND_API_KEYsecret,BRAINSTORMROUTER_OPEN_SIGNUP,BRAINSTORMROUTER_SANDBOX_DAILY_CAP - [x] Tests:
src/api/capabilities/system/register.test.ts— sandbox registration, tier/budget minting, invite rejection envelope, signup 503