{"type":"text/markdown","content":"---\nname: IdentyClaw\ndescription: Practical IdentyClaw API guide for agents — API session login (JWT), multi-API / federated hosts (same SR/CR family), HOLA peer handshake lines, verify (`POST /api/identity/verify`), and identity lookup. Runtime-agnostic HTTP; OpenClaw uses plugin tools, Hermes/IronClaw/NanoClaw/Cursor use host login (curl, script, or sidecar). Use when verifying peer agents, proving your identity, resolving Passport IDs, or reading `face.categories` (see `references/token-metadata.md`).\n---\n\n# IdentyClaw Agent Skills\n\n**Home API (default):** `https://api.identyclaw.com`  \n**Federated example:** `https://api-b.example.com` (same SR/CR family)\n\nIdentyClaw is an HTTP API for IdentyClaw Passport holders and the **HOLA** mutual authentication protocol. Deep protocol detail lives in linked references; this doc is the **runnable cheat sheet** for **all** agent runtimes.\n\n**Fetch via MCP:** `doc:discovery` (index) · `doc:skills` (cheat sheet) · `curl https://api.identyclaw.com/api/mcp/resource/doc:skills`\n\n**Backend federation contract:** `@rodit/rodit-auth-be` **≥9.13**. Runtime packaging index: MCP `doc:reference:agent-frameworks` or [`agent-frameworks.md`](agent-frameworks.md).\n\n---\n\n## Pick your runtime (how you call the API)\n\nThe protocol is the same everywhere (JWT session + HOLA lines). **How you obtain the JWT** depends on the harness:\n\n| Runtime | Session / login | HOLA create | Deep guide |\n| --- | --- | --- | --- |\n| **OpenClaw** | Plugin tools (`identyclaw_ensure_session`, …) — do **not** curl login in chat | `identyclaw_create_hola` | [openclaw-identyclaw-plugin](https://github.com/discernible-io/openclaw-identyclaw-plugin) **v1.6.0+** |\n| **Hermes** | Host: curl, [`identyclaw-login.mjs`](../scripts/identyclaw-login.mjs), or login script → file JWT | `@rodit/hola-client` or shell | [`hermes-integration-guide.md`](hermes-integration-guide.md) · [`hermes-identyclaw-skill/`](../hermes-identyclaw-skill/) |\n| **IronClaw** | Host sidecar or script (keys **outside** WASM sandbox) | Sidecar / `@rodit/hola-client` | [`ironclaw-integration-guide.md`](ironclaw-integration-guide.md) |\n| **NanoClaw** | curl / Node sidecar in bind-mounted secrets | curl / sidecar | [`nanoclaw-integration-guide.md`](nanoclaw-integration-guide.md) |\n| **Cursor / Claude Desktop / shell / CI** | curl or login script; store JWT on disk | `@rodit/hola-client` on host | [`mcp-auth-tools.md`](mcp-auth-tools.md) · [`mcp-connection-guide.md`](mcp-connection-guide.md) |\n\n**Agent rules (all runtimes):**\n\n1. Never invent Ed25519 signatures or paste private keys / full JWTs into chat.\n2. Never treat a redacted `eyJ…` fragment as a bearer token ([`mcp-auth-tools.md`](mcp-auth-tools.md)).\n3. **OpenClaw only:** call `identyclaw_*` tools (auto-login + JWT cache per API URL). Pass `apiEndpoint` for federated hosts.\n4. **Hermes / IronClaw / NanoClaw / Cursor / shell:** host login against `$BASE` (home or federated URL) is the **correct** path — not a fallback. Store `jwt_token` on the host; use Bearer on protected calls. Portable API capabilities (HOLA, envelopes, webhooks via host handler): [`agent-frameworks.md`](agent-frameworks.md#what-this-api--repo-provides-all-runtimes).\n5. **A2A P2P** (`POST /a2a`) is OpenClaw’s separate **`identyclaw-a2a`** plugin. Other runtimes exchange HOLA / collaboration envelopes on their own channels.\n\nWire format for host login: [`login-authentication.md`](login-authentication.md).\n\n---\n\n## Two lanes — do not mix them\n\n| Lane | Artifact | Typical TTL | Docs |\n| --- | --- | --- | --- |\n| **API login** | Bearer JWT (`jwt_token`) | ~1 hour | [login-authentication.md](login-authentication.md) |\n| **HOLA protocol** | HOLA line (wire string) | ~5 min (nonce) | [hola-howto.md](hola-howto.md), [hola-agent-authentication.md](hola-agent-authentication.md) |\n\n| Endpoint | Fields | Purpose |\n| --- | --- | --- |\n| `GET /api/login/timestamp` | `timestamp`, `timestamp_iso` | API login signing |\n| `GET /api/holanonce16ts` | `noncetsHex`, `timestamp` | HOLA line construction — [holanonce-api.md](holanonce-api.md) |\n\nA JWT is **not** a HOLA line. Protected HOLA endpoints need an API session; the handshake payload is the HOLA string.\n\n---\n\n## Install and entry points\n\n```text\nMCP (docs, all runtimes):  https://api.identyclaw.com/mcp\nDiscovery index:           doc:discovery\nCheat sheet:               doc:skills\n\nOpenClaw skill:            openclaw skills install clawhub:identyclaw\nOpenClaw plugin (API):     openclaw plugins install clawhub:@identyclaw/openclaw-identyclaw-plugin\nOpenClaw plugin (A2A):     openclaw plugins install clawhub:@identyclaw/openclaw-a2a-plugin\n\nHermes skill:              copy hermes-identyclaw-skill/ → ~/.hermes/skills/identity/identyclaw/\nIronClaw / NanoClaw:       MCP + host sidecar / curl (see agent-frameworks.md)\nHost login helper:         scripts/identyclaw-login.mjs  → writes jwt_token to a file\n```\n\nFull discovery map: MCP resource `doc:discovery` or [`mcp-discovery-index.md`](mcp-discovery-index.md). Runtime matrix: [`agent-frameworks.md`](agent-frameworks.md).\n\n**Verifiers (integrators):** **Verify before execute** — peer HOLA is **offline P2P** between agents; each peer verifies **independently** (IdentyClaw API or direct NEAR RPC, peer's choice). Recipes: [`verify-hola-recipes.md`](verify-hola-recipes.md) (MCP `doc:reference:verify-hola-recipes`). Publish your canonical `tokenId` on channels you control.\n\n---\n\n## Multi-API sessions and federation\n\nPassport holders can hold **concurrent JWT sessions** against a **home** API and one or more **federated** APIs in the **same SR/CR family**. Federation is **login → remint a local JWT** on the target host — foreign JWTs are not accepted without re-login. Mutual auth (reverse login) remains optional.\n\n| Concept | OpenClaw plugin | Hermes / IronClaw / NanoClaw / shell |\n| --- | --- | --- |\n| Home API | `baseUrl` / `IDENTYCLAW_BASE_URL` | `$BASE=https://api.identyclaw.com` (or your home deploy) |\n| Federated host | `apiEndpoints` / `IDENTYCLAW_API_ENDPOINTS` | Same wire login with `$BASE=https://api-b.example.com` |\n| Per-call target | Tool arg `apiEndpoint` | Choose which JWT / base URL for that request |\n| Open / refresh | `identyclaw_ensure_session` ± `apiEndpoint` | Re-run host login against that `$BASE`; keep one JWT file per host |\n| List sessions | `identyclaw_list_sessions` | Operator-managed (e.g. `~/.identyclaw/jwt-<host>.txt`) |\n| SDK apps | — | `@rodit/rodit-auth-be` ≥9.13 — `login_server({ apiEndpoint })` |\n\n**Federated JWT claims** (aligned with `@rodit/rodit-auth-be` ≥9.13):\n\n| Claim | Same-API login | Federated login |\n| --- | --- | --- |\n| `iss` | Receiving server URL | Client home `subjectuniqueidentifier_url` |\n| `aud` | Server `owner_id` | Federated server `owner_id` |\n| `rodit_subjectuniqueidentifier_url` | `null` | Federated API URL |\n\nAfter login to a non-home URL, soft MITM checks (SDK and OpenClaw plugin) expect `rodit_subjectuniqueidentifier_url` = intended target and `iss` = client home. Failures: `FEDERATED_ISSUER_MISSING`, `FEDERATED_ISSUER_MISMATCH`. Curl-only agents should still pin hostname + TLS and use the federated `$BASE` deliberately.\n\n**Not the same as A2A:** multi-API sessions are **HTTP API** JWTs. Agent-to-agent messaging over `/a2a` is OpenClaw’s **`identyclaw-a2a`** only; other runtimes use HOLA + their own channels.\n\nDetails: [`login-authentication.md`](login-authentication.md#federated-login-same-family-different-api-url). OpenClaw config example: [plugin README](https://github.com/discernible-io/openclaw-identyclaw-plugin/blob/main/README.md).\n\n---\n\n## Agent cheat sheet\n\nProtected routes need an API session (OpenClaw auto-login **or** host Bearer JWT from `POST /api/login`). **`POST /api/identity/verify` is public** — no JWT required (nginx edge rate limit); an optional bearer enables `RECIPIENT_MISMATCH` warnings (suppress with `expectedRecipient`). Field name is **`jwt_token`**. JWT lasts ~1 hour; HOLA nonces last ~5 minutes — fetch a **new** nonce immediately before each HOLA you sign.\n\n| # | Goal | OpenClaw | Hermes / IronClaw / NanoClaw / host | Lane |\n|---|------|----------|-------------------------------------|------|\n| 1 | API session (home or federated) | `identyclaw_ensure_session` ± `apiEndpoint` | Login against `$BASE` (curl / `identyclaw-login.mjs` / sidecar) | API login |\n| 2 | List live sessions | `identyclaw_list_sessions` | One JWT file (or env) per API host | API login |\n| 3 | **Create outbound HOLA line** | `identyclaw_create_hola` (± `apiEndpoint`) | `@rodit/hola-client` `createHola()` or manual nonce+sign | HOLA (+ API session) |\n| 4 | **Verify peer HOLA line** | `identyclaw_verify_hola` (± `apiEndpoint`) | `POST /api/identity/verify` | HOLA (public; optional JWT) |\n| 5 | Resolve Passport → full DN | `identyclaw_get_agent_identity` | `GET /api/identity/token/{tokenId}/full` | API session |\n| 6 | List public agents | `identyclaw_list_agents` | `GET /api/agents?limit=20` | Public |\n| 7 | Resolve DID | `identyclaw_resolve_did` | `GET /.well-known/did/resolve?did=did:rodit:{tokenId}` | API session |\n| 8 | Message another agent | **`identyclaw-a2a`** plugin | HOLA + channel / collaboration envelope | A2A or P2P |\n\n### 1a. API session — OpenClaw\n\n```text\nidentyclaw_ensure_session\nidentyclaw_ensure_session  apiEndpoint=https://api-b.example.com\nidentyclaw_get_my_identity apiEndpoint=https://api-b.example.com\nidentyclaw_list_sessions\n```\n\nSessions are **cached per URL**. Home and federated can be live at once. The plugin never returns the JWT to the model.\n\n### 1b. API session — Hermes / IronClaw / NanoClaw / shell (host login)\n\n**curl** (also: `node scripts/identyclaw-login.mjs` → file JWT without printing the secret)\n\n```bash\nBASE=https://api.identyclaw.com   # or federated peer URL\n\n# One-time challenge — use both fields from the same response, once\nTS_JSON=$(curl -sS \"$BASE/api/login/timestamp\")\nTIMESTAMP=$(echo \"$TS_JSON\" | jq -r '.timestamp')\nTIMESTAMP_ISO=$(echo \"$TS_JSON\" | jq -r '.timestamp_iso')\n\n# Sign UTF-8 bytes of: <accountid> + <timestamp_iso> (no separator)\n# → base64url_signature with your NEAR/Passport Ed25519 key (see login-authentication.md)\n\nJWT=$(curl -sS -X POST \"$BASE/api/login\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"accountid\\\":\\\"<64-char-hex>\\\",\\\"timestamp\\\":$TIMESTAMP,\\\"base64url_signature\\\":\\\"<sig>\\\"}\" \\\n  | jq -r '.jwt_token')\n\ncurl -sS \"$BASE/api/me/identity\" -H \"Authorization: Bearer $JWT\"\n```\n\n**Node** (requires `accountid` + NEAR private key in env; uses `tweetnacl` + `bs58` like the OpenClaw plugin)\n\n```javascript\nimport nacl from \"tweetnacl\";\nimport bs58 from \"bs58\";\n\nconst BASE = process.env.IDENTYCLAW_BASE_URL ?? \"https://api.identyclaw.com\";\nconst accountid = process.env.IDENTYCLAW_ACCOUNT_ID; // 64-char hex NEAR account\nconst nearPrivateKey = process.env.IDENTYCLAW_NEAR_PRIVATE_KEY; // ed25519:...\n\nfunction base64Url(bytes) {\n  return Buffer.from(bytes).toString(\"base64url\");\n}\n\nconst keyBody = nearPrivateKey.replace(/^ed25519:/, \"\").trim();\nconst secretKey = bs58.decode(keyBody).slice(0, 32);\n\nconst ts = await (await fetch(`${BASE}/api/login/timestamp`)).json();\nconst message = `${accountid}${ts.timestamp_iso}`;\nconst sig = nacl.sign.detached(new TextEncoder().encode(message), secretKey);\n\nconst login = await fetch(`${BASE}/api/login`, {\n  method: \"POST\",\n  headers: { \"content-type\": \"application/json\" },\n  body: JSON.stringify({\n    accountid,\n    timestamp: ts.timestamp,\n    base64url_signature: base64Url(sig),\n  }),\n}).then((r) => r.json());\n\nconst JWT = login.jwt_token; // ~1 hour; refresh when 401\n```\n\n**SDK federated login** (`@rodit/rodit-auth-be` ≥9.13):\n\n```javascript\nconst { RoditClient } = require(\"@rodit/rodit-auth-be\");\nconst client = await RoditClient.create(\"client\");\nawait client.login_server(); // home\nawait client.login_server({ apiEndpoint: \"https://api-b.example.com\" }); // federated\n```\n\nFull signing steps: [`references/login-authentication.md`](login-authentication.md#quick-start-login-pattern). JWT storage pitfalls: [`references/mcp-auth-tools.md`](mcp-auth-tools.md).\n\n---\n\n### 2. Create outbound HOLA\n\n**OpenClaw:** `identyclaw_create_hola` (± `apiEndpoint`). **Hermes / IronClaw / NanoClaw / host:** `@rodit/hola-client` `createHola()` or manual nonce + local sign. API session fetches nonce; **HOLA line signed locally** (`nearPrivateKey` never sent to HTTP except inside the finished HOLA string).\n\n```bash\n# OpenClaw: allowlist identyclaw_create_hola; nearPrivateKey in plugin config\n# Host:     node + @rodit/hola-client, or GET /api/holanonce16ts then sign\n# Returns:  { hola, noncetsHex, timestamp, tokenId, recipient, ... }\n```\n\n**Outbound HOLA rules (agents):**\n\n- **Signer / origin** is always **this agent's Passport ID** — resolved from `GET /api/me/identity` / `identyclaw_get_my_identity`.\n- Call **`identyclaw_create_hola`** without `tokenId` (OpenClaw), or pass your own `tokenId` from `/api/me/identity` when using `@rodit/hola-client`.\n- **Never ask the user for your own Passport ID** to create an outbound HOLA line.\n- **Only `recipient`** may be user-supplied (peer Passport ID or `MUNDO` for broadcast intros).\n\n```javascript\nconst { createHola } = require(\"@rodit/hola-client\");\n\nconst { hola } = await createHola({\n  baseUrl: process.env.IDENTYCLAW_BASE_URL ?? \"https://api.identyclaw.com\",\n  jwt: JWT,\n  nearPrivateKey: process.env.IDENTYCLAW_NEAR_PRIVATE_KEY,\n  tokenId: \"yourpassportid\", // from GET /api/me/identity (OpenClaw plugin resolves this for you)\n  recipient: \"MUNDO\",\n});\n```\n\n**Manual path** — use **`noncetsHex`** and **`timestamp`** from `GET /api/holanonce16ts` (not login `timestamp_iso`). Standard line:\n\n```text\nHOLA/<recipient>/<tokenId>/<timestamp>/<noncetsHex>/API.IDENTYCLAW.COM/<base32-signature>/<checksum>\n```\n\n**curl — fetch nonce** (host path)\n\n```bash\ncurl -sS \"$BASE/api/holanonce16ts\" \\\n  -H \"Authorization: Bearer $JWT\"\n# → { \"noncetsHex\", \"timestamp\", \"length\", \"algorithm\", \"requestId\" }\n```\n\nSelf-test your line before sending to peers:\n\n```bash\ncurl -sS -X POST \"$BASE/api/testhola\" \\\n  -H \"Authorization: Bearer $JWT\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"hola\":\"<your line>\"}'\n```\n\nBuild/sign walkthrough: [`references/hola-howto.md`](hola-howto.md). Full spec: [`references/hola-agent-authentication.md`](hola-agent-authentication.md).\n\n---\n\n### 3. Verify an incoming HOLA (most important)\n\n**One call validates format, checksum, freshness, nonce replay, token existence/active, and on-chain signature.** No Passport or JWT is required; pin the API hostname (see [finding-agents.md](finding-agents.md#6-verify-the-api-server-mitm-protection)). OpenClaw: `identyclaw_verify_hola`. Everyone else: `POST /api/identity/verify`.\n\n```bash\n# Plugin: identyclaw_verify_hola  hola=<line>  expectedRecipient=MUNDO  [apiEndpoint=...]\n\ncurl -sS -X POST https://api.identyclaw.com/api/identity/verify \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"hola\":\"HOLA/MUNDO/<peerTokenId>/2026-06-03T12:00:00.000Z/<noncetsHex>/API.IDENTYCLAW.COM/<sig>/<checksum>\",\"expectedRecipient\":\"MUNDO\"}'\n# Optional: -H \"Authorization: Bearer $JWT\" when logged in — enables RECIPIENT_MISMATCH unless expectedRecipient is set\n```\n\nOptional body fields on `POST /api/identity/verify`:\n\n- `expectedRecipient` — suppress `RECIPIENT_MISMATCH` when verifying a peer HOLA intentionally (e.g. `recipient=MUNDO` while logged in as yourself, or when sending optional JWT)\n- `constraints.maxAgeMs` — freshness window (default 300000 ms)\n\n`POST /api/testhola` accepts only `hola` and optional `expectedRecipient` (no `constraints`).\n\n**Node**\n\n```javascript\nconst headers = { \"content-type\": \"application/json\" };\n// if (JWT) headers.authorization = `Bearer ${JWT}`; // optional — RECIPIENT_MISMATCH when authenticated\n\nconst result = await fetch(\"https://api.identyclaw.com/api/identity/verify\", {\n  method: \"POST\",\n  headers,\n  body: JSON.stringify({\n    hola: peerHolaLine,\n    expectedRecipient: \"MUNDO\",\n  }),\n}).then((r) => r.json());\n\nif (result.verified) {\n  const peerTokenId = result.peerTokenId; // 12-letter Passport ID\n  // Best action next: send your own HOLA back immediately (cheat sheet §2) — do not wait for the user to ask\n  // then identity lookup + impersonation guard\n}\n```\n\nSee [Verify any HOLA in one call](#verify-any-hola-in-one-call) below for the response shape and failure codes.\n\n**Do not** trust a peer based on local checksum/signature alone — wait for `verified: true` from this endpoint (or equivalent direct on-chain verification).\n\n**After `verified: true` on an inbound peer HOLA:** reply with **your own** outbound HOLA on the **same channel** without waiting for a user prompt. Verifying them is only half of mutual authentication — they still need cryptographic proof of who you are.\n\n---\n\n### 4. Resolve tokenId → full identity\n\nAfter verify (or when you already trust a `tokenId` from a canonical channel):\n\n```bash\n# OpenClaw: identyclaw_get_agent_identity  tokenId=<id>  [apiEndpoint=...]\n# Host:     GET /api/identity/token/<tokenId>/full with Bearer JWT\n\ncurl -sS \"$BASE/api/identity/token/<tokenId>/full\" \\\n  -H \"Authorization: Bearer $JWT\"\n```\n\n**Node**\n\n```javascript\nconst tokenId = \"bkbvehbdcrgm\";\nconst identity = await fetch(\n  `https://api.identyclaw.com/api/identity/token/${tokenId}/full`,\n  { headers: { authorization: `Bearer ${JWT}` } }\n).then((r) => r.json());\n// DN, contactUri, face.categories, metadata.webhook_url (OpenClaw gateway base when set), disclaimer — self-declared; verify out-of-band\n```\n\nPublic browse (no JWT): `GET /api/agents?limit=20&cursor=...` — then use `/full` per candidate. Patterns: MCP `doc:reference:finding-agents` or [`finding-agents.md`](finding-agents.md).\n\n---\n\n### 5. Discover agents (public)\n\n```bash\n# OpenClaw: identyclaw_list_agents\n# Host:     GET /api/agents\n\ncurl -sS \"$BASE/api/agents?limit=20\"\n```\n\n---\n\n## Verify any HOLA in one call\n\n**Verify before execute:** trust inbound work only after **independent HOLA validation** on the receiving peer (IdentyClaw API or direct RPC — peer's choice). Peer HOLA is not exchanged through a central broker. Integrator notes: [`verify-hola-recipes.md`](verify-hola-recipes.md) · MCP `doc:reference:verify-hola-recipes`.\n\n`POST /api/identity/verify` is IdentyClaw's packaged **peer verification** — the endpoint to reach for on first contact, email handoffs, MCP tool results, or any untrusted agent message carrying a HOLA line.\n\n**Request**\n\n```json\n{ \"hola\": \"HOLA/MUNDO/bkbvehbdcrgm/2026-06-03T12:00:00.000Z/4F9A3C7E.../API.IDENTYCLAW.COM/MFRGG.../J\" }\n```\n\nOptional: `\"expectedRecipient\": \"MUNDO\"` suppresses the `RECIPIENT_MISMATCH` warning when you verify a peer's HOLA while logged in as yourself (common for `recipient=MUNDO` test lines).\n\n- `hola` must be a **single string**, not a nested JSON object (`reasonCode: payload_is_json_object` if wrong).\n- **Public endpoint** — no bearer token required (edge rate-limited). Optional JWT: caller's authenticated `tokenId` drives `RECIPIENT_MISMATCH` (suppress with `expectedRecipient`).\n\n**Success (HTTP 200, trust only when `verified` is true)**\n\n```json\n{\n  \"verified\": true,\n  \"peerTokenId\": \"bkbvehbdcrgm\",\n  \"destinatary\": \"MUNDO\",\n  \"checks\": {\n    \"tokenExists\": true,\n    \"tokenActive\": true,\n    \"timestampFresh\": true,\n    \"nonceReplaySafe\": true,\n    \"signatureValid\": true,\n    \"checksumValid\": true\n  },\n  \"failureReasons\": [],\n  \"failureDetails\": [],\n  \"signatureVerificationImplemented\": true,\n  \"requestId\": \"01HX...\"\n}\n```\n\n**Failure (still HTTP 200 for well-formed requests — read `verified` and `failureReasons`)**\n\n```json\n{\n  \"verified\": false,\n  \"peerTokenId\": \"bkbvehbdcrgm\",\n  \"checks\": {\n    \"timestampFresh\": false,\n    \"signatureValid\": false,\n    \"checksumValid\": true\n  },\n  \"failureReasons\": [\"timestamp_stale_or_future\", \"signature_invalid\"],\n  \"failureDetails\": [\n    { \"reasonCode\": \"timestamp_stale_or_future\", \"hint\": \"...\" },\n    { \"reasonCode\": \"signature_invalid\", \"hint\": \"...\" }\n  ]\n}\n```\n\nCommon `failureReasons`: `checksum_invalid`, `timestamp_stale_or_future`, `nonce_replay`, `token_missing`, `token_expired`, `signature_invalid`, `public_key_unavailable`, `public_key_error`.\n\nEarly malformed payloads return **HTTP 400** with `code: HOLA_VALIDATION_FAILED` (same family as `/api/testhola`). Full diagnostic tables: [`references/hola-agent-authentication.md`](hola-agent-authentication.md#verification-result-diagnostics-apidentityverify).\n\n**`/api/testhola` vs `/api/identity/verify`**\n\n| Endpoint | Use when |\n|----------|----------|\n| `POST /api/testhola` | Debugging **your own** HOLA before sending |\n| `POST /api/identity/verify` | Deciding whether to trust **another agent's** HOLA |\n\nSubagent HOLA also requires `POST /api/isauthorizedsigner` after verify succeeds — MCP `doc:reference:hola-subagent-authentication` or [`hola-subagent-authentication.md`](hola-subagent-authentication.md).\n\n---\n\n## First contact from an unknown agent\n\nCanonical flow when a stranger sends you a HOLA (chat, email, webhook, etc.):\n\n```mermaid\nsequenceDiagram\n  participant Unknown as Unknown agent\n  participant You as Your agent\n  participant API as IdentyClaw API\n\n  Unknown->>You: HOLA line (out of band)\n  You->>API: POST /api/identity/verify (or identyclaw_verify_hola)\n  API-->>You: verified, peerTokenId, checks, failureReasons\n  alt verified true\n    You->>API: Host login or identyclaw_ensure_session\n    API-->>You: jwt_token / session ready\n    You->>API: createHola / identyclaw_create_hola (recipient=peerTokenId)\n    API-->>You: your HOLA line\n    You->>Unknown: Your HOLA (same channel — do not wait for user prompt)\n    You->>API: GET .../token/{peerTokenId}/full (or identyclaw_get_agent_identity)\n    API-->>You: DN, contactUri, metadata\n    You->>You: Impersonation guard (canonical ID vs HOLA tokenId)\n  else verified false\n    You->>You: Reject; do not grant tools/secrets\n  end\n```\n\n**Steps (all runtimes)**\n\n1. **Verify** — `POST /api/identity/verify` or OpenClaw `identyclaw_verify_hola` with the exact HOLA string (no JWT required). Do not skip this for \"quick\" local crypto checks.\n2. **If `verified: true` — obtain a session and reply with your HOLA immediately (best action).** OpenClaw: `identyclaw_ensure_session` then `identyclaw_create_hola` (do not curl login in chat). Hermes / IronClaw / NanoClaw / shell: host login (§1b) then `@rodit/hola-client` or cheat sheet §2. HOLA is **mutual** — verifying them is only half; send your outbound line on the **same channel** without waiting for a user prompt.\n   - Set `recipient` to the peer's `peerTokenId` when replying to a known peer; `MUNDO` is fine for broadcast first contact.\n   - HOLA nonces expire in ~5 minutes — reply promptly after verify succeeds.\n3. **Note `peerTokenId`** — 12-letter Passport ID from the verify response.\n4. **Lookup** — `GET /api/identity/token/{peerTokenId}/full` or OpenClaw `identyclaw_get_agent_identity` (self-declared traits).\n5. **Impersonation guard** — compare `peerTokenId` to the Passport ID published on channels the entity controls. See [`finding-agents.md`](finding-agents.md#5-guard-against-impersonation).\n6. **Subagent only** — `POST /api/isauthorizedsigner` or `identyclaw_check_subagent_signer` when delegation fields present.\n7. **Ongoing messaging** — OpenClaw may use **A2A** (`identyclaw-a2a`); other runtimes keep using HOLA + collaboration envelope / their channel.\n\n**Host script (verify + lookup) — Hermes / IronClaw / NanoClaw / shell**\n\n```bash\nBASE=https://api.identyclaw.com   # or federated peer URL\nPEER_HOLA='HOLA/MUNDO/...'  # exact string from the unknown agent\n\nVERIFY=$(curl -sS -X POST \"$BASE/api/identity/verify\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \"$(jq -n --arg h \"$PEER_HOLA\" '{hola:$h}')\")\n\necho \"$VERIFY\" | jq .\nVERIFIED=$(echo \"$VERIFY\" | jq -r '.verified')\nTOKEN=$(echo \"$VERIFY\" | jq -r '.peerTokenId')\n\nif [ \"$VERIFIED\" = \"true\" ] && [ -n \"$TOKEN\" ] && [ \"$TOKEN\" != \"null\" ]; then\n  # Lookup requires JWT (cheat sheet §1b)\n  curl -sS \"$BASE/api/identity/token/$TOKEN/full\" \\\n    -H \"Authorization: Bearer $JWT\" | jq .\nfi\n```\n\n---\n\n## Extended workflows (by reference)\n\n| Topic | Document | MCP resource |\n|-------|----------|--------------|\n| Agent frameworks | [`agent-frameworks.md`](agent-frameworks.md) | `doc:reference:agent-frameworks` |\n| Hermes | [`hermes-integration-guide.md`](hermes-integration-guide.md) | `doc:reference:hermes-integration-guide` |\n| IronClaw | [`ironclaw-integration-guide.md`](ironclaw-integration-guide.md) | `doc:reference:ironclaw-integration-guide` |\n| NanoClaw | [`nanoclaw-integration-guide.md`](nanoclaw-integration-guide.md) | `doc:reference:nanoclaw-integration-guide` |\n| Discovery index | [`mcp-discovery-index.md`](mcp-discovery-index.md) | `doc:discovery` |\n| ClawHub skill pointer | [`identyclaw-skill.md`](identyclaw-skill.md) | `doc:reference:identyclaw-skill` |\n| Find agents + impersonation guard | [`finding-agents.md`](finding-agents.md) | `doc:reference:finding-agents` |\n| Email + channel outreach | [`inter-agent-communication.md`](inter-agent-communication.md) | `doc:reference:inter-agent-communication` |\n| Collaboration envelope (normative) | [`collaboration-envelope.md`](collaboration-envelope.md) | `doc:reference:collaboration-envelope` |\n| OpenClaw webhooks | [`openclaw-integration-guide.md`](openclaw-integration-guide.md) | `doc:reference:openclaw-integration-guide` |\n| Verify before execute (verifier recipes) | [`verify-hola-recipes.md`](verify-hola-recipes.md) | `doc:reference:verify-hola-recipes` |\n| Linear HOLA path (login → verify) | [`hola-howto.md`](hola-howto.md) | `doc:reference:hola-howto` |\n| Enrollment + NEAR setup | [`enrollment.md`](enrollment.md) | `guide:enrollment`, `onboarding:near` |\n| Standard HOLA spec | [`hola-agent-authentication.md`](hola-agent-authentication.md) | `doc:reference:hola-authentication` |\n| Subagent delegation | [`hola-subagent-authentication.md`](hola-subagent-authentication.md) | `doc:reference:hola-subagent-authentication`, `guide:subagents` |\n| Nonce JSON shape | [`holanonce-api.md`](holanonce-api.md) | `doc:reference:holanonce-api` |\n| API login + federation + MITM | [`login-authentication.md`](login-authentication.md) | `doc:reference:login-authentication`, `doc:reference:mcp-auth-tools` |\n| Endpoint catalog | [`api-reference.md`](api-reference.md) | `openapi:swagger` |\n| DID resolution | [`did-rodit-method.md`](did-rodit-method.md) | `doc:reference:did-rodit-method`, `did:resolve:{tokenId}` |\n| Key rotation | [`key-rotation.md`](key-rotation.md) | `guide:key-rotation` |\n| MCP setup | [`mcp-connection-guide.md`](mcp-connection-guide.md) | `doc:reference:mcp-connection-guide` |\n\n**HOLA formats**\n\nStandard:\n\n```text\nHOLA/<recipient>/<tokenId>/<timestamp>/<noncetsHex>/API.IDENTYCLAW.COM/<signature>/<checksum>\n```\n\nSubagent (delegation):\n\n```text\nHOLA/<recipient>/<delegateID>/<issuer_tokenId>/<publicKey>/<timestamp>/<noncetsHex>/API.IDENTYCLAW.COM/<signature>/<checksum>\n```\n\n**DID (JWT required)**\n\n```bash\n# Plugin: identyclaw_resolve_did\n\ncurl -sS \"https://api.identyclaw.com/.well-known/did/resolve?did=did:rodit:<tokenId>\" \\\n  -H \"Authorization: Bearer $JWT\"\n```\n\n---\n\n## MCP quick connect\n\n```json\n{\n  \"mcpServers\": {\n    \"IdentyClaw\": {\n      \"url\": \"https://api.identyclaw.com/mcp\",\n      \"description\": \"IdentyClaw API documentation (MCP docs-only — use plugin or curl for authenticated calls)\"\n    }\n  }\n}\n```\n\nList/fetch docs without MCP client:\n\n```bash\ncurl https://api.identyclaw.com/api/mcp/resources\ncurl https://api.identyclaw.com/api/mcp/resource/doc:skills\n```\n\nTools: `list_resources`, `get_resource`. Client-side auth patterns: [`mcp-auth-tools.md`](mcp-auth-tools.md).\n\n**Interactive API:** OpenAPI at `GET https://api.identyclaw.com/openapi.json` (alias `GET /swagger.json`)\n\n---\n\n## OpenClaw agent tools (plugin v1.6.0+)\n\nFor **OpenClaw** Gateways only — Hermes / IronClaw / NanoClaw use host login (§1b) and [`agent-frameworks.md`](agent-frameworks.md).\n\n```bash\nopenclaw plugins install clawhub:@identyclaw/openclaw-identyclaw-plugin\n```\n\nExample plugin config (home + federated):\n\n```json5\n{\n  plugins: {\n    entries: {\n      \"identyclaw-tools\": {\n        enabled: true,\n        config: {\n          baseUrl: \"https://api.identyclaw.com\",\n          apiEndpoints: [\"https://api-b.example.com\"],\n          accountid: \"<64-char-hex-near-implicit-account>\",\n          nearPrivateKey: \"ed25519:...\"\n        }\n      }\n    }\n  }\n}\n```\n\nEnv alternative: `IDENTYCLAW_API_ENDPOINTS=https://api-b.example.com`.\n\n### Session tools (multi-API)\n\n| Tool | Role |\n| --- | --- |\n| `identyclaw_ensure_session` | Open/refresh JWT for home or `apiEndpoint` (metadata only — never returns JWT) |\n| `identyclaw_list_sessions` | List cached sessions + configured `apiEndpoints` |\n\n### Public (no API session)\n\n| Tool | Endpoint |\n| --- | --- |\n| `identyclaw_list_agents` | `GET /api/agents` |\n| `identyclaw_list_resources` | `GET /api/mcp/resources` |\n| `identyclaw_get_resource` | `GET /api/mcp/resource/{uri}` |\n\n### API session only\n\n| Tool | Endpoint |\n| --- | --- |\n| `identyclaw_get_my_identity` | `GET /api/me/identity` |\n| `identyclaw_get_agent_identity` | `GET /api/identity/token/{tokenId}/full` |\n| `identyclaw_check_subagent_signer` | `POST /api/isauthorizedsigner` |\n| `identyclaw_resolve_did` | `GET /.well-known/did/resolve` |\n\n### HOLA protocol\n\n| Tool | Notes |\n| --- | --- |\n| `identyclaw_get_nonce` | `GET /api/holanonce16ts` — HOLA nonce fields |\n| `identyclaw_create_hola` | HOLA line via `@rodit/hola-client` (API session + local sign); signer from `/api/me/identity` |\n| `identyclaw_verify_hola` | `POST /api/identity/verify` (peer HOLA line; JWT optional) |\n\nMost HTTP tools accept optional **`apiEndpoint`**. Allowlist optional tools in `tools.allow` when credentials are configured.\n\n`nearPrivateKey` on the Gateway: **API login** (base64url) and **HOLA create** (base32) — different messages. Configure under `plugins.entries.identyclaw-tools.config`. README: [openclaw-identyclaw-plugin](https://github.com/discernible-io/openclaw-identyclaw-plugin/blob/main/README.md).\n\n**ClawHub skill (workflows):** `openclaw skills install clawhub:identyclaw`\n\n---\n\n## Notes and conventions\n\n### Terminology\n\n| Term | Meaning | When to use |\n|------|---------|-------------|\n| **IdentyClaw Passport** | On-chain credential holders mint (12-letter Passport ID) | Enrollment, identity, user-facing copy |\n| **RODiT** | Underlying technology (token format, HOLA proofs, `did:rodit`, JSON-LD) | Protocol specs, SDK names, implementation only |\n| **IdentyClaw API** | Optional HTTP service for Passport holders | Login, nonces, discovery, verify helpers |\n| **Federated API** | Another host in the same SR/CR family | Multi-API sessions via `apiEndpoint` |\n\n**Do not say \"RODiT Passport.\"** Passports are IdentyClaw Passports; RODiT is the technology they use.\n\nPassport holders may use the API for convenience or verify peers directly on-chain without API involvement. See [`public/policies/why-identyclaw.md`](../public/policies/why-identyclaw.md) §3.1.\n\n### Two clocks\n\n| Clock | TTL | Source | Used for |\n|-------|-----|--------|----------|\n| **JWT session** | ~1 hour | Plugin auto-login / `POST /api/login` | Bearer on protected routes (per API URL) |\n| **HOLA nonce** | ~5 minutes | `GET /api/holanonce16ts` | Timestamp + nonce inside each HOLA line |\n\n### Token ID and metadata\n\nFacial trait ranges: [`token-metadata.md`](token-metadata.md#facial-token-id-encoding). Decoded selections on your identity: `GET /api/me/identity` → `face.categories`.\n\n### Pricing (summary)\n\n- **Personal:** formula-based, min 0.066 NEAR / 30 days (48 req/min)\n- **Enterprise:** 148–1,806 NEAR/year (4,999 req/min)\n- **Collectible:** 496 NEAR one-time\n\nDetails: [`pricing-philosophy.md`](pricing-philosophy.md).\n\n### Policies\n\n`public/policies/` and `/.well-known/` — terms, privacy, data retention, why-identyclaw.\n","requestId":"6bbb4c6414e5bd9d27aa2d4731f3a36b"}