Skip to main content

Agent Self-Onboarding

This guide covers the full journey from an agent's perspective: self-enroll with zero credentials, receive access from your human, create and read secrets, and share them back.

Try it out

Try out the example in this repo: Basic (includes enrollment and sharing). The examples README lists all runnable demos.

Overview

Agent (no credentials)

├── 1. POST /v1/agents/enroll (public, no auth)
│ └── Pending enrollment; human approves via email link or approval_url
│ └── Credentials emailed to the human after approval

├── 2. Human creates access policies in the dashboard

├── 3. Agent exchanges API key for JWT
│ └── POST /v1/auth/agent-token

├── 4. Agent reads / writes secrets
│ └── GET/PUT /v1/vaults/:id/secrets/:path

└── 5. Agent shares secrets back to human
└── POST /v1/secrets/:id/share { recipient_type: "creator" }

1. Self-enroll

The enrollment endpoint is public — no authentication required. Provide name and optionally human_email:

  • With email: A pending enrollment is created for that account; Allow/Deny links are emailed, and the response may include approval_url as a fallback.
  • Name only: A link-only pending enrollment is created; the response includes approval_url for the human to open while signed in (no email required to start).
curl -s -X POST https://api.1claw.xyz/v1/agents/enroll \
-H "Content-Type: application/json" \
-d '{
"name": "my-agent",
"human_email": "alice@example.com",
"description": "CI pipeline agent"
}'

Link-only (no email):

curl -s -X POST https://api.1claw.xyz/v1/agents/enroll \
-H "Content-Type: application/json" \
-d '{"name":"my-agent"}'

npx @1claw/cli agent enroll my-agent

What happens:

  1. The API creates a pending enrollment (email-bound or link-only).
  2. The human approves via the emailed link or by opening approval_url while signed in.
  3. After approval, an agent is created in the approver's organization; an API key is generated and emailed — the plaintext key is never returned from POST /v1/agents/enroll.
  4. Responses use a uniform 201 shape where needed to limit email enumeration (some branches omit approval_url).

Rate limits: One enrollment per email per 10 minutes (when email is used), caps on pending enrollments, plus IP-based rate limiting.

2. Human grants access

The human receives an email with the agent's ID and API key. In the dashboard:

  1. Go to Vaults and select (or create) a vault.
  2. Navigate to PoliciesCreate Policy.
  3. Set principal type to Agent, select the agent, choose a path pattern (e.g. api-keys/**), and grant read (and optionally write) permission.

The agent now has zero-access-by-default elevated to the specific paths the human chose.

3. Exchange API key for JWT

Once the human shares the API key with the agent's deployment:

TOKEN=$(curl -s -X POST https://api.1claw.xyz/v1/auth/agent-token \
-H "Content-Type: application/json" \
-d '{"agent_id":"<AGENT_ID>","api_key":"ocv_..."}' \
| jq -r .access_token)

4. Read and write secrets

# Read a secret
curl -s "https://api.1claw.xyz/v1/vaults/$VAULT_ID/secrets/api-keys/openai" \
-H "Authorization: Bearer $TOKEN"

# Store a secret
curl -s -X PUT "https://api.1claw.xyz/v1/vaults/$VAULT_ID/secrets/credentials/db-password" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"password","value":"s3cret!"}'

5. Share secrets back to your human

Agents can share any secret they own back to the human who created them using recipient_type: "creator". No email address or user ID is needed — the API resolves it from created_by.

curl -s -X POST "https://api.1claw.xyz/v1/secrets/$SECRET_ID/share" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"recipient_type": "creator",
"expires_at": "2026-12-31T00:00:00Z",
"max_access_count": 10
}'

The human sees the share in their Inbound tab on the Sharing page and accepts it.

Complete example

Here is a typical agent lifecycle in a single script:

import { createClient, AgentsResource } from "@1claw/sdk";

// Step 1: Self-enroll (first run only)
const enrollment = await AgentsResource.enroll("https://api.1claw.xyz", {
name: "deploy-bot",
human_email: "ops@mycompany.com",
});
console.log("Pending:", enrollment.message, enrollment.approval_url);
// Wait for human to approve, then email you the API key and create policies...

// Steps 3-5: Normal operation (after receiving credentials)
const client = createClient({
baseUrl: "https://api.1claw.xyz",
agentId: process.env.ONECLAW_AGENT_ID,
apiKey: process.env.ONECLAW_AGENT_API_KEY,
});

// Read a secret
const { data: secret } = await client.secrets.get(VAULT_ID, "api-keys/deploy-token");

// Store a newly generated credential
await client.secrets.set(VAULT_ID, "credentials/session-key", newSessionKey, {
type: "api_key",
});

// Share it back to the human
const { data: secretMeta } = await client.secrets.describe(VAULT_ID, "credentials/session-key");
await client.sharing.create(secretMeta.id, {
recipient_type: "creator",
expires_at: "2026-06-01T00:00:00Z",
});

Security notes

  • Zero access by default — A freshly enrolled agent cannot read any secrets until the human creates policies.
  • API key is never in the enroll response — It is emailed to the human after they approve. The agent never sees its own key via POST /v1/agents/enroll.
  • Rate limiting — Enrollment is rate-limited per email (10 min cooldown when email is used), with caps on pending rows and per IP.
  • Uniform responses — Some branches use the same 201 shape to limit email enumeration; approval_url may be omitted in those cases.

Next steps