Install
openclaw skills install humanos-openclawRequire verifiable human approval before high-risk agent actions.
openclaw skills install humanos-openclawAI agents can execute actions. Humanos lets them prove human authorization before they do.
Require a mandate signature before high-risk execution.
Humanos provides the authorization proof. Your runtime decides whether to execute.
Use Humanos when your agent can:
If the action affects money, data, identity, ownership, or legal position, require a mandate signature.
requestMandate(action, constraints)verifyMandate(signature)No valid mandate signature -> execution should not proceed.
requestMandate(action, constraints) -> mandate_signature
verifyMandate(mandate_signature) -> true / false
revokeMandate(mandate_signature)
Simple. Programmable. Deterministic.
Use this skill whenever the agent is about to do something that requires a human to say "yes" first. It sends a secure approval request to the right person - they receive a link, review the details, and approve or reject. The result comes back as a W3C Verifiable Credential with cryptographic proof that the action was authorized.
The agent should NEVER proceed with a sensitive action (payment, signing, data access, transfer) without first using this skill to get authorization.
Use this skill when the user says things like:
Also use this skill when the agent is about to:
Trigger keywords: approval, authorize, mandate, sign, consent, credential, KYC, identity verification, human approval, compliance, permission, delegation.
VIA_API_KEY — Bearer token for API authenticationVIA_SIGNATURE_SECRET — HMAC secret for request signingVIA_API_URL — Override API base URL (default: https://api.humanos.id)Windows note: this skill is currently supported on macOS/Linux shells. On Windows, use WSL or Git Bash with bash, curl, jq, and openssl installed.
All API requests require:
Authorization: Bearer $VIA_API_KEY
X-Timestamp: <unix-timestamp-ms>
X-Signature: <hmac-sha256 of (timestamp + "." + body) using VIA_SIGNATURE_SECRET>
Use the signing script: scripts/sign-request.sh
Official API documentation: https://humanos.mintlify.app/essentials/introduction
Use this as the primary lookup table before reading detailed sections.
| Goal | Script | Method | Endpoint | Required Args |
|---|---|---|---|---|
| Create approval request | scripts/create-request.sh | POST | /v1/request | --contact, --type, --name |
| Check request status | scripts/get-request.sh | GET | /v1/request/:id | --id |
| Find requests | scripts/find-requests.sh | GET | `/v1/request?contact | did |
| Get credential proof | scripts/get-credential.sh | GET | /v1/credential/:id | --id |
| Get mandate | scripts/get-mandate.sh | GET | /v1/via/mandates/:id | --id |
| Get mandate VC | scripts/get-mandate-vc.sh | GET | /v1/via/mandates/:id/vc | --id |
| Resolve DID | scripts/resolve-did.sh | GET | /v1/via/dids/:did | --did |
| Look up user | scripts/get-user.sh | GET | `/v1/user?contact | did |
| Cancel request | scripts/cancel-request.sh | DELETE | /v1/request/:id | --id |
| Resend OTP | scripts/resend-otp.sh | PATCH | /v1/request/resend/:id | --id (and optional --contact) |
Follow these rules to avoid generic 400 Failed to generate credentials request responses.
--type as: document, consent, or json (lowercase input; script converts internally).form is not supported as inline credential in this script. Use resource IDs for forms.--data should be JSON array of fields. A single object is also accepted and auto-wrapped.label (string)type (string, number, boolean, date, url, pdf, object, array)value (matches type)hidden (boolean; defaults to false)consent: must include {"label":"text","type":"string","value":"...","hidden":false}document: must include {"label":"pdf","type":"pdf","value":"<base64>","hidden":false}Consent (recommended for simple approvals):
scripts/create-request.sh \
--contact "+351919307983" \
--type "consent" \
--name "Football approval" \
--data '[{"label":"text","type":"string","value":"I approve football tomorrow.","hidden":false}]'
JSON mandate:
scripts/create-request.sh \
--contact "user@example.com" \
--type "json" \
--name "Hotel Booking Authorization" \
--data '[
{"label":"amount","type":"number","value":450,"hidden":false},
{"label":"currency","type":"string","value":"EUR","hidden":false}
]'
Document signature:
scripts/create-request.sh \
--contact "user@example.com" \
--type "document" \
--name "NDA Signature" \
--data '[{"label":"pdf","type":"pdf","value":"<base64-pdf>","hidden":false}]'
All 401 Invalid signature incidents should be debugged against this section.
timestamp in unix milliseconds (13 digits).timestamp + "." + body when body is not emptytimestamp when body is emptysignature = HMAC_SHA256_HEX(payload, VIA_SIGNATURE_SECRET).jq -c or jq -n to build compact JSON.printf, not echo, when signing (avoid accidental newline).%3N incompatibility on macOS).When the agent needs human authorization for an action:
scripts/create-request.sh \
--contact "user@example.com" \
--type "json" \
--name "Hotel Booking Authorization" \
--security "CONTACT" \
--data '[{"label":"amount","type":"number","value":450,"hidden":false}]'
Parameters:
--contact — Email or phone number of the person who must approve (required)--type — Type of credential: document, json, or consent (required). form inline is not supported.--name — Human-readable name for the approval (required)--security — Security level: CONTACT, ORGANIZATION_KYC, HUMANOS_KYC (default: CONTACT)--data — JSON array of mandate fields (optional for json; strongly recommended for consent/document)--language — Language for the approval UI: ENG or PRT (default: ENG)--redirect — URL to redirect user after approval (optional)--internal-id — Your internal reference ID (optional)What happens:
Response includes: requestId — save this to check status later.
scripts/get-request.sh --id "request-id-here"
Returns the full request with all credentials and their statuses (PENDING, APPROVED, REJECTED).
scripts/find-requests.sh --contact "user@example.com"
# or
scripts/find-requests.sh --did "did:key:z6Mk..."
# or
scripts/find-requests.sh --internal-id "order-123"
scripts/get-credential.sh --id "credential-id-here"
Returns the W3C Verifiable Credential with cryptographic proofs that the human authorized the action.
scripts/get-mandate.sh --id "mdt_uuid-here"
Returns mandate details including scope, validity period, and constraints.
scripts/get-mandate-vc.sh --id "mdt_uuid-here"
Returns the mandate in W3C Verifiable Credential format for use in Verifiable Presentations.
scripts/resolve-did.sh --did "did:key:z6Mk..."
Returns the DID Document with verification methods. Use this to verify signatures on credentials.
scripts/get-user.sh --contact "user@example.com"
Returns user details, identity information, and associated DIDs.
scripts/cancel-request.sh --id "request-id-here"
Cancels a pending request. This is irreversible.
scripts/resend-otp.sh --id "request-id-here" --contact "user@example.com"
Resends the verification code to the user if they didn't receive it.
When you need human approval, follow this flow:
scripts/create-request.shscripts/get-request.sh or wait for webhookAPPROVED → Proceed with the action. The credential contains cryptographic proof.REJECTED → Do NOT proceed. Inform the user the action was denied.PENDING → Still waiting. Ask the user if they want to resend the OTP.| Level | Description | Use When |
|---|---|---|
CONTACT | OTP verification only | Low-risk actions (view data, basic approvals) |
ORGANIZATION_KYC | Organization-level identity check | Medium-risk (sign documents, access records) |
HUMANOS_KYC | Full KYC with identity verification | High-risk (payments, legal signatures) |
HUMANOS_REVALIDATION | Re-verification of previously verified identity | Periodic re-checks |
| Type | Description | User Experience |
|---|---|---|
document | PDF document for review and signature | User sees PDF, can draw signature |
form | Dynamic form with fields | User fills form fields step by step |
json | Structured data for review | User sees data and approves/rejects |
consent | Consent text or URL | User reads and agrees to terms |
Follow this exact sequence before escalating:
https://api.humanos.id.timestamp + "." + body (non-empty body), ortimestamp (empty body).curl.VIA_SIGNATURE_SECRET and VIA_API_KEY come from the same environment.sha256(body)Escalation note for support: "GET succeeds with same key/secret, POST returns 401 Invalid signature using payload=timestamp.body."
Always present results to the user in this format:
For request creation:
Request created successfully. An approval link has been sent to [contact]. Request ID: [id] Status: PENDING
For status checks:
Request [id] — Status: [APPROVED/REJECTED/PENDING] Credential: [name] — [status] Approved by: [contact] on [date]
For errors:
Failed to [action]: [error message] Suggestion: [what to do next]
| Endpoint | Data Sent | Purpose |
|---|---|---|
$VIA_API_URL/v1/request | Contacts, credential data | Create approval requests |
$VIA_API_URL/v1/request/:id | Request ID | Check approval status |
$VIA_API_URL/v1/credential/:id | Credential ID | Retrieve signed credentials |
$VIA_API_URL/v1/via/mandates/:id | Mandate ID | Get mandate details |
$VIA_API_URL/v1/via/mandates?scope=<scope>&toolName=<tool> | Scope, tool name | Query mandates for policy checks |
$VIA_API_URL/v1/via/dids/:did | DID identifier | Resolve DID documents |
$VIA_API_URL/v1/user | Contact/DID/internal ID | Look up users |
Default base URL is https://api.humanos.id when VIA_API_URL is not set.
~/.openclaw/openclaw.json (set secure file permissions: chmod 600)