Agents

Register an agent

Create an agent in the dashboard, mint a one-time registration token, and register your first key with the CLI or the API.

An agent is a named identity owned by your account. It holds up to five non-revoked Ed25519 keys — pending keys count toward the limit. Registering a key is a two-step process: upload the public key, then prove possession of the private key by signing a registration challenge. Until the first key is proven, the agent stays pending.

1. Create the agent

In the dashboard, Agents → Register agent. Give it a name (≤ 80 characters), an optional description and website. The agent id is derived from the name plus four random characters, e.g. agent_nova_8f2a.

Or via the API with your dashboard session token:

curl
curl -X POST https://imnotahuman.ai/api/v1/agents \
  -H 'authorization: Bearer <session access token>' \
  -H 'content-type: application/json' \
  -d '{"name":"Nova","description":"Shopping assistant","website":"https://nova.example"}'

2. Mint a registration token

A registration token (reg_…, 160 bits) lets a machine register one key without a dashboard session. It is shown once, only its hash is stored, it expires after 15 minutes and is consumed on first use.

curl
curl -X POST https://imnotahuman.ai/api/v1/agents/agent_nova_8f2a/registration-tokens \
  -H 'authorization: Bearer <session access token>'

# 201
# {"registration_token":"reg_...","agent_id":"agent_nova_8f2a","expires_at":"2026-09-20T12:15:00.000Z"}

3. Register with the CLI

Terminal
curl -fsSL https://imnotahuman.ai/agent.mjs -o imnotahuman-agent.mjs
node imnotahuman-agent.mjs init --token reg_... --label "prod-1"

The CLI is one file with no dependencies (Node 18+). The npm package@imnotahuman/agent will offer the same commands once published.

init generates a keypair locally, calls POST /api/v1/registration/keys with the public key, signs the returned registration challenge, and saves the identity to ~/.imnotahuman/agent.json (mode 600). If a registered identity already exists there it refuses unless --force is passed. Flags: --api, --keystore, --label, --json. The token can also come from IMNOTAHUMAN_REGISTRATION_TOKEN.

3 (alternative). Register manually

Any Ed25519 implementation works. Upload the public key with the registration token as bearer:

curl
curl -X POST https://imnotahuman.ai/api/v1/registration/keys \
  -H 'authorization: Bearer reg_...' \
  -H 'content-type: application/json' \
  -d '{"public_key":"_Gqb_W0_oiqrRCCw8P_X8DSeNSwTiMpA4rUS3OqqBZk","label":"prod-1"}'
201 Created
{
  "agent": { "id": "agent_nova_8f2a", "name": "Nova", "status": "pending", ... },
  "key": { "id": "key_b7n2xq4mfc3rtw6y", "status": "pending", "key_thumbprint": "fIpJN_bqfhSP3P4ikoK4_vs36sWvfiDG3cgfCRJ6GRo", ... },
  "challenge": {
    "challenge_id": "ch_...",
    "nonce": "...",
    "site_key": "site_live_...",
    "origin": "https://imnotahuman.ai",
    "issued_at": 1789905600,
    "expires_at": 1789906500,
    "action": "register_key",
    "intent": "key_b7n2xq4mfc3rtw6y",
    "mode": "live",
    "status": "PENDING",
    "purpose": "registration",
    "challenge_url": "https://imnotahuman.ai/c/ch_...",
    "verify_url": "https://imnotahuman.ai/api/v1/verify"
  }
}

Sign challenge exactly like a normal challenge (see Sign challenges) using the new key.id and POST the proof to /api/v1/verify. The registration challenge is valid for 15 minutes and is bound to that key: no other key can complete it. On success the key and the agent become active. Registration challenges do not issue a token.

Accepted public_key formats: base64url or base64 raw 32 bytes, base64 SPKI DER, a PEM PUBLIC KEY block, or an OKP JWK ({"kty":"OKP","crv":"Ed25519","x":"…"}) as an object or string.

Agent status

StatusMeaningVerification
pendingCreated; no key has completed registration yet.Only the bound registration challenge; otherwise KEY_PENDING
activeAt least one key proven.Allowed with active keys
disabledTemporarily switched off by the owner.AGENT_DISABLED; re-enable any time
revokedPermanently retired; all keys revoked.AGENT_REVOKED; cannot be re-enabled