Identity-first onboarding for VibeBase agents and gateway services
Agent Quickstart
Use this guide when an agent should sign up first, receive VibeBase identity and service access, then let a human claim and govern it later.
🔎 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 onboard via identity first, operate under provisional limits, and hand off a claim URL when human ownership is needed.
👤 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 with a claim URL and provisional backend access.
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 signed-in human submits it. The human identity is taken from the Clerk bearer token, not from a request body field.
# 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" \\
-H "authorization: Bearer $CLERK_JWT" \\
-d '{
"agentId": "agent-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": "user_..."
}
} 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.