Identity-first onboarding for VibeBase agents and gateway services
Agent Quickstart
Use this guide when you want to provision VibeBase identity and service access for agents. The flow is identity-first, then gateway-based for services like email.
🔎 Discovery
Agents should start at https://gateway.vibebase.app. For automated discovery, use
https://vibebase.app/api or https://vibebase.app/.well-known/agent.json.
👥 Human Signup vs Agent Onboarding
Humans sign up in the console. Agents should not use the web signup flow — they should onboard via identity and then use the gateway.
👤 Humans: use the Console
If you're a human user, create your account in the console first: console sign up. This guide is for agent self-onboarding via API.
1. Create an Agent Identity
Agents self-create using an Ed25519 public key. This creates an orphan agent.
curl -sX POST https://identity.vibebase.app/v1/agent/init \\
-H "content-type: application/json" \\
-d '{
"publicKey": "83a54e...a2d",
"name": "bullseye",
"metadata": {
"notifications": {
"claimedWebhookUrl": "https://agent.example.com/webhooks/claimed"
}
}
}' | jq Response shape:
{
"success": true,
"data": {
"id": "agent-id",
"publicKey": "83a54e...a2d",
"tier": "orphan",
"name": "bullseye",
"claimUrl": "https://console.vibebase.app/claim/<token>",
"claimUrlExpiresAt": "2026-05-02T12:34:56.000Z",
"claimNotificationSubscription": {
"id": "sub_...",
"callbackUrl": "https://agent.example.com/webhooks/claimed",
"eventTypes": ["agent_claimed"]
}
}
}
If metadata.notifications.claimedWebhookUrl is provided, VibeBase automatically
subscribes that URL to agent_claimed events and returns
claimNotificationSubscription in the init response. The response also includes a
one-time claimUrl for human handoff.
Optional: Regenerate Claim URL
Agents can request a fresh one-time claim URL (24h default TTL) using their agent JWT.
curl -sX POST https://identity.vibebase.app/v1/claim/link \\
-H "content-type: application/json" \\
-H "authorization: Bearer $AGENT_JWT" \\
-d '{
"agentId": "agent-id",
"expiresInMinutes": 1440
}' | jq Response shape:
{
"success": true,
"data": {
"claimUrl": "https://console.vibebase.app/claim/<token>",
"expiresAt": "2026-05-02T12:34:56.000Z"
}
} 2. Claim the Agent (Human)
The agent signs the claim challenge and a human submits it.
# get challenge
curl -sX POST https://identity.vibebase.app/v1/challenge \\
-H "content-type: application/json" \\
-d '{
"action": "claim",
"agentId": "agent-id"
}' | jq
# submit claim
curl -sX POST https://identity.vibebase.app/v1/claim \\
-H "content-type: application/json" \\
-d '{
"agentId": "agent-id",
"humanId": "clerk-user-id",
"signature": "hex...",
"challenge": "vibebase:claim:..."
}' | jq Challenge response shape:
{
"success": true,
"data": {
"challenge": "vibebase:claim:agent-id:timestamp:nonce",
"expiresAt": "2026-05-01T12:34:56.000Z"
}
} Claim response shape:
{
"success": true,
"data": {
"id": "agent-id",
"tier": "claimed",
"claimedBy": "clerk-user-id"
}
} 3. Exchange for Identity JWT
The agent signs the token challenge and exchanges it for a JWT.
# get challenge
curl -sX POST https://identity.vibebase.app/v1/challenge \\
-H "content-type: application/json" \\
-d '{
"action": "token",
"agentId": "agent-id"
}' | jq
# exchange for JWT
curl -sX POST https://identity.vibebase.app/v1/token \\
-H "content-type: application/json" \\
-d '{
"agentId": "agent-id",
"signature": "hex...",
"challenge": "vibebase:token:..."
}' | jq Challenge response shape:
{
"success": true,
"data": {
"challenge": "vibebase:token:agent-id:timestamp:nonce",
"expiresAt": "2026-05-01T12:34:56.000Z"
}
} Token response shape:
{
"success": true,
"data": {
"token": "eyJhbGciOi...",
"expiresAt": "2026-05-02T12:34:56.000Z"
}
} 4. Request Gateway Service Tokens
Use the identity JWT to request service tokens from the gateway. This is the canonical entrypoint for agent service access.
# get gateway challenge
curl -sX POST https://gateway.vibebase.app/v1/challenge \\
-H "content-type: application/json" \\
-d '{
"action": "token",
"agentId": "agent-id"
}' | jq
# request scoped service token
curl -sX POST https://gateway.vibebase.app/v1/token \\
-H "content-type: application/json" \\
-H "authorization: Bearer $AGENT_JWT" \\
-d '{
"service": "email",
"action": "send",
"scope": ["send"],
"challenge": "gateway:token:agent-id:timestamp:nonce",
"signature": "hex..."
}' | jq Gateway challenge response shape:
{
"success": true,
"data": {
"challenge": "gateway:token:agent-id:timestamp:nonce",
"expiresAt": "2026-05-01T12:34:56.000Z"
}
} Gateway token response shape:
{
"success": true,
"data": {
"serviceToken": "vb_email_agent_...",
"endpoint": "https://email.vibebase.app",
"expiresIn": 3600,
"permissions": ["send"]
}
} 5. Testing Your Integration
The full SAL smoke test is the reference end-to-end integration sample for envelope handling and full identity flow checks.
# from repo root
bun sal-smoke-test.ts Full source is documented in the SAL protocol page: /docs/sal-protocol#testing-your-integration.
Note: claim submission is intentionally skipped in smoke tests because claim requires a real signed-in console user.
Notes
- Orphans (email trial): orphan agents can send email with a trial cap of 10 lifetime sends.
- Orphans (email constraints): plain-text only, no attachments, max 3 unique recipients before claim.
- Address stability: orphan and claimed use the same address format:
agent_{id}@mail.vibebase.app. - Claim notification: optional claimed webhook is pushed through the identity event delivery pipeline.
- Challenges: challenges expire after ~5 minutes.
- Gateway: service tokens are short-lived and scoped.