{"type":"text/markdown","content":"# OpenClaw Integration Guide\n\nWire IdentyClaw Passport metadata and webhooks to an OpenClaw gateway so inbound identity events (HOLA validation outcomes, future attestation) trigger agent tasks.\n\n**MCP resource URI:** `doc:reference:openclaw-integration-guide`\n\n**Related:** `doc:discovery`, `doc:reference:collaboration-envelope`, [`openclaw-passport-value.md`](openclaw-passport-value.md) (why Passport vs static secrets), [`login-authentication.md`](login-authentication.md) (webhook signature verification), [`token-metadata.md`](token-metadata.md) (`webhook_url` field).\n\n---\n\n## Why Passport for OpenClaw (not just webhooks)\n\nA minimal OpenClaw deployment can use a static webhook token and fixed peer URLs. Passport adds value when peers must be **identities**, not hostnames:\n\n- **Stable `tokenId`** — peers resolve your live gateway via `GET /api/identity/token/{tokenId}/full` → `metadata.webhook_url`; redeploy without re-sharing secrets.\n- **Split auth** — A2A wire JWT (`POST /a2a`), webhook origin signatures (`/hooks/wake`, `/hooks/agent`), and IdentyClaw API session JWT are separate surfaces.\n- **Three channels** — use A2A for multi-turn work, webhooks for cheap signed wake/heartbeat, API/HOLA for discovery and first-contact trust.\n\n| Channel | Good for |\n| --- | --- |\n| **A2A** (`POST /a2a`) | Tasks, files, multi-turn dialogue — P2P RODiT JWT via `@identyclaw/openclaw-a2a-plugin` |\n| **Webhooks** (`/hooks/wake`, `/hooks/agent`) | Signed liveness nudge or identity-driven automation — this guide |\n| **API / HOLA** | Discovery (`GET /api/agents`), verify unknown agents (`POST /api/identity/verify`) |\n\nFull operator rationale, use cases, and “when to skip Passport”: [`openclaw-passport-value.md`](openclaw-passport-value.md).\n\n---\n\n## Install complementary artifacts\n\n```text\nSkill (workflows):     openclaw skills install clawhub:identyclaw\nPlugin (API + HOLA):   openclaw plugins install clawhub:@identyclaw/openclaw-identyclaw-plugin\nPlugin (A2A P2P):      openclaw plugins install clawhub:@identyclaw/openclaw-a2a-plugin\nMCP (docs):            https://api.identyclaw.com/mcp\nDiscovery index:       doc:discovery\nCheat sheet:           doc:skills\n```\n\nThe **identyclaw-tools** plugin covers outbound API calls (multi-API sessions, verify HOLA, list agents, fetch identity) — prefer its tools over curl login. This guide covers **inbound** events from IdentyClaw to your gateway.\n\n---\n\n## Passport metadata — base URL vs hook path\n\nSet `webhook_url` in Passport metadata to the **OpenClaw gateway base** (no hook path):\n\n```text\nPassport metadata webhook_url:  https://my-openclaw.example.com\nIdentyClaw POST target:         https://my-openclaw.example.com/hooks/agent\n```\n\nIdentyClaw appends hook paths when sending (`sendWebhookToEndpoint` in the API). Do **not** embed `/hooks/agent` in metadata unless your deployment expects a full URL without path appending.\n\nExample metadata fragment:\n\n```json\n{\n  \"webhook_url\": \"https://my-openclaw.example.com\",\n  \"webhook_cidr\": \"203.0.113.0/24\"\n}\n```\n\nOptional `webhook_cidr` restricts accepted source IPs when your gateway has a stable egress range.\n\n---\n\n## When to use `/hooks/agent` vs `/hooks/wake`\n\n| Hook | OpenClaw behavior | IdentyClaw use case |\n| --- | --- | --- |\n| `/hooks/wake` | Enqueue heartbeat / system event for main session | Liveness nudge after validation |\n| `/hooks/agent` | Run isolated agent task; optional reply to messaging channels | **Primary** — process HOLA verify outcomes, run follow-up logic |\n\n**Recommendation:** Use **`/hooks/agent`** as the default integration point for identity-driven automation. Use `/hooks/wake` only when you need session keep-alive without a full task.\n\nDuring development, successful `POST /api/testhola` validation fires webhooks to **both** paths when `WEBHOOK_TEST_ENABLED=true`.\n\n---\n\n## Event payload and task mapping\n\n**Event type (development test):** `testhola_validation_success`\n\n**Example payload** (from `/api/testhola` webhook delivery):\n\n```json\n{\n  \"event\": \"testhola_validation_success\",\n  \"data\": {\n    \"peerTokenId\": \"abc123def456\",\n    \"serverTokenId\": \"xyz789uvw012\",\n    \"recipient\": \"MUNDO\",\n    \"timestamp\": \"2026-04-24T18:30:00.000Z\",\n    \"endpoint\": \"/api/testhola\"\n  }\n}\n```\n\n**OpenClaw task mapping (suggested prompt chain):**\n\n1. Parse `event` and `data.peerTokenId`.\n2. Call `identyclaw_verify_hola` or `POST /api/identity/verify` if the inbound message carries a HOLA line (webhook alone does not replace verify for untrusted channels).\n3. Call `identyclaw_get_agent_identity` or `GET /api/identity/token/{tokenId}/full` for DN and `contactUri`.\n4. Run delegated work; reply on the channel implied by `contactUri` or your collaboration envelope — see `doc:reference:collaboration-envelope`.\n\nFor inbound messages that embed a [collaboration envelope](collaboration-envelope.md), verify the envelope's `hola` field before processing `task`.\n\n---\n\n## Development vs production\n\n| Setting | **development** | **main** |\n| --- | --- | --- |\n| `WEBHOOK_TEST_ENABLED` | `\"true\"` — testhola fires webhooks | `\"false\"` |\n| `WEBHOOK_TLS_SKIP_VERIFY` | may be `\"true\"` (dev only) | must be `\"false\"` |\n| Webhook signature verification | document `verifyWebhookSignature()` / `getWebhookHandler()` | **required** on receiver |\n\nTest with `POST /api/testhola` in development before promoting Passport metadata on main.\n\n---\n\n## Receiver checklist (OpenClaw side)\n\n1. Register Passport `webhook_url` pointing at your OpenClaw gateway host (base URL only).\n2. Expose `/hooks/agent` (and optionally `/hooks/wake`) with TLS.\n3. Verify Ed25519 webhook signatures per [`login-authentication.md`](login-authentication.md) — reject unsigned or invalid payloads.\n4. Restrict source IPs with `webhook_cidr` when possible.\n5. Install the IdentyClaw plugin and skill for outbound verify/lookup tools.\n6. Map inbound payloads to agent prompts; never trust raw `peerTokenId` without verify when the channel is untrusted.\n\n---\n\n## End-to-end test flow\n\n```bash\n# 1. Set webhook_url on your Passport metadata (gateway base URL)\n# 2. In development, ensure WEBHOOK_TEST_ENABLED=true on the API host\n# 3. Login and self-test HOLA\nJWT=...  # from POST /api/login\ncurl -sS -X POST https://api.identyclaw.com/api/testhola \\\n  -H \"Authorization: Bearer $JWT\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"hola\":\"<your valid HOLA line>\"}'\n# 4. Confirm OpenClaw received POST on /hooks/agent (and optionally /hooks/wake)\n```\n\n---\n\n## Non-goals\n\n- IdentyClaw does not host your OpenClaw gateway or deliver arbitrary chat messages.\n- MCP (`https://api.identyclaw.com/mcp`) is docs-only — webhooks are HTTP POST to your gateway, not MCP resources.\n- Outbound HOLA creation: `identyclaw_create_hola` (plugin) or `@rodit/hola-client`.\n","requestId":"7b9da940d801dc02fd34fac94e2c25e8"}