ClawKey
Integration Guide
This guide walks through the complete flow: generating an AgentChallenge, registering your agent, having the human owner verify, and checking registration status.
Prerequisites
- An Ed25519 key pair — used to sign challenges and prove key ownership
- A stable deviceId — ties the agent to its registration (e.g. hash of public key or an app-chosen identifier)
- A human owner — the person who will complete VeryAI palm verification
The AgentChallenge
The AgentChallenge is a signed payload that proves you control an Ed25519 key. It's used for both registration (/agent/register/init) and verification (/agent/verify/signature).
Challenge Format
| Field | Type | Description |
|---|---|---|
deviceId | string | Stable agent/device identifier |
publicKey | string | Ed25519 public key, base64 DER SPKI |
message | string | Exact message that was signed |
signature | string | Ed25519 signature over message, base64 |
timestamp | int64 | Unix timestamp in milliseconds when challenge was created |
Building the Challenge Step-by-Step
- Choose a message to sign
For registration, use a one-time challenge to prevent replay attacks:
clawkey-register-<unix_timestamp_ms>
Example:clawkey-register-1738500000000 - Sign the message with your Ed25519 private key. The signature must be over the exact UTF-8 bytes of
message(no prefix or suffix). - Encode for the API:
- publicKey — Ed25519 public key in SPKI DER form, then base64 encoded (no PEM wrapper)
- signature — Raw Ed25519 signature bytes, base64 encoded
- timestamp — Unix time in milliseconds (e.g.
Date.now())
Where Identity Comes From (OpenClaw)
If you run on OpenClaw, device identity is stored at:
~/.openclaw/identity/device.json That file contains:
| Field | Use |
|---|---|
deviceId | Use as deviceId in the challenge. Stable ID for this agent. |
publicKeyPem | Derive the base64 DER SPKI publicKey from this. |
privateKeyPem | Use only locally to sign. Never send to any server. |
If you don't use OpenClaw, use your own identity store — just ensure you have a stable deviceId, an Ed25519 key pair, and that you sign the exact string you send as message.
Example: Node.js
const crypto = require("crypto");
const fs = require("fs");
const identityPath = `${process.env.HOME}/.openclaw/identity/device.json`;
const identity = JSON.parse(fs.readFileSync(identityPath, "utf8"));
const message = `clawkey-register-${Date.now()}`;
const privateKey = crypto.createPrivateKey(identity.privateKeyPem);
const signature = crypto.sign(null, Buffer.from(message, "utf8"), privateKey);
const publicKeyDer = crypto
.createPublicKey(identity.publicKeyPem)
.export({ type: "spki", format: "der" });
const challenge = {
deviceId: identity.deviceId,
publicKey: publicKeyDer.toString("base64"),
message,
signature: signature.toString("base64"),
timestamp: Date.now(),
};
// POST challenge to https://api.clawkey.ai/v1/agent/register/init Quick Start
Step 1: Start Registration
Build an AgentChallenge as above, then POST it to start a registration session:
curl -X POST https://api.clawkey.ai/v1/agent/register/init \
-H "Content-Type: application/json" \
-d '{
"deviceId": "my-agent-device-id",
"publicKey": "<base64-DER-SPKI-Ed25519>",
"message": "clawkey-register-1738500000000",
"signature": "<base64-Ed25519-signature>",
"timestamp": 1738500000000
}' Response (201):
sessionId— Use to poll statusregistrationUrl— Present this to the human owner as a clickable linkexpiresAt— Session expiry (ISO 8601)
If the agent is already registered (deviceId exists), the API returns 409 Conflict.
Step 2: Human Completes Verification
Present the registrationUrl to the human owner. They open it in their browser and complete VeryAI's palm verification via OAuth. When they finish, the agent is registered under their ownership.
Important: Never open the browser programmatically. Always output the URL as a text or markdown link for the user to click.
Step 3: Poll Registration Status
Poll until the human has completed verification or the session has expired:
curl https://api.clawkey.ai/v1/agent/register/SESSION_ID/status The status field will be one of:
| Status | Meaning |
|---|---|
pending | Human has not yet completed verification |
completed | Agent is now registered under the verified human |
expired | Session expired before verification completed |
failed | Verification failed |
When status is completed, the response includes deviceId and registration details.
Step 4: Verify an Agent
Once registered, anyone can verify the agent in two ways:
Verify a signature — Check that a message was signed by the given key and whether the agent is registered under a verified human:
curl -X POST https://api.clawkey.ai/v1/agent/verify/signature \
-H "Content-Type: application/json" \
-d '{
"deviceId": "...",
"publicKey": "...",
"message": "...",
"signature": "...",
"timestamp": 1738500000000
}' Response includes verified (signature valid) and registered (agent under verified human).
Look up by device ID — Get registration and verification status directly:
curl https://api.clawkey.ai/v1/agent/verify/device/DEVICE_ID Response includes registered, verified, and optionally registeredAt.
Heartbeat Checks
Agents should periodically check their registration status:
curl https://api.clawkey.ai/v1/agent/verify/device/YOUR_DEVICE_ID | Result | Action |
|---|---|
registered: false | Not in ClawKey yet. Start registration via /agent/register/init. |
registered: true, verified: true | All good. Agent is under a verified human owner. |
registered: true, verified: false | Registered but human may not have completed verification. Have them open the registration flow again. |
Need Help?
See the full API Reference for detailed endpoint documentation, or contact support@very.org.