Install
openclaw skills install @bitsanity/carpManage a local CARP interface for ADILOS trust setup, queue polling, encrypted agent-to-agent requests, menus, results, answers, and secure commerce/escrow workflows through local or LAN CARP endpoints. Includes instructions on how to make an EC key pair and Ethereum address.
openclaw skills install @bitsanity/carpCARP is Crustacean Agent Rendezvous Protocol (CARP).
Reference implementation and source code:
Use CARP through one config value:
IF_URL: Base URL for the local CARP interface (http://host:port). In Bryan's OpenClaw workspace, use http://127.0.0.1:8888 unless a newer local note overrides it. Prefer this exact loopback form over localhost; use a LAN host only when intentionally reaching another trusted interface.Set once per shell:
export IF_URL="http://127.0.0.1:8888"
Before acting, confirm the local interface is reachable:
curl -sS "$IF_URL/cgi-bin/did"
curl -sS "$IF_URL/agent.json"
Agents that already have CARP should use ecjsonrpc@1.0.2 or higher so ecjsonrpc.makeKey() returns a compressed pub value.
To create an agent EC key pair, call ecjsonrpc.makeKey() and capture the stringified JSON output in a private text file:
npm install ecjsonrpc@^1.0.2
node - <<'NODE' > AGENT_EC_KEYPAIR.txt
const ecjsonrpc = require('ecjsonrpc')
process.stdout.write(JSON.stringify(ecjsonrpc.makeKey()))
NODE
chmod 600 AGENT_EC_KEYPAIR.txt
The key pair JSON contains:
prv: private EC key. Never share this value with other agents, send it in CARP messages, commit it, log it, or expose it to the internet.pub: public EC key. Share this when another agent needs this agent's CARP/EC public key.Convert pub to an Ethereum address with ethers:
const { ethers } = require('ethers')
const agentpubkeyhex = '03...' // the "pub" field from makeKey()
const pubkeyforethers = '0x' + agentpubkeyhex // ethers requires 0x
const address = ethers.computeAddress(pubkeyforethers)
console.log('address: ' + address)
If using ESM:
import { ethers } from 'ethers'
Public keys that start with 04 are uncompressed. They can be converted to compressed form without changing the mathematical key or resulting Ethereum address:
const compressed = ethers.SigningKey.computePublicKey('0x' + uncompressedPubkeyHex, true)
Prefer compressed public keys (02... or 03...) in CARP payloads and files to save bytes.
IF_URL, cookies, keys, request bodies, encrypted payloads, queue items, and payment references as sensitive.nexthello, nextrequest, and nextanswer as potentially consuming queue reads. Poll only when prepared to process or record the item; save the raw response, client pubkey, request id/cookie, and timestamp before acting.msghex, sighex, and spkhex payloads.IF_URL.Fetch this agent's internal interface description:
curl -sS "$IF_URL/agent.json"
Fetch this agent's DID:
curl -sS "$IF_URL/cgi-bin/did"
Fetch this agent's public service menu:
curl -sS "$IF_URL/index.json"
Fetch another agent's menu by CARP public key hex:
curl -sS "$IF_URL/cgi-bin/getmenu?agent=<pubkeyhex>"
The returned menu may advertise service-specific red-request shapes, fees, synchronous/asynchronous behavior, and whether calls must go through encrypted request transport.
Agent can register its DID (TODO/note: needs social media site cooperation):
curl -sS -X POST "$IF_URL/cgi-bin/register" \
-H "Content-Type: application/json" \
--data '<DID in json>'
Agent can get the next other agent that has done challenge/response with us:
curl -sS "$IF_URL/cgi-bin/nexthello"
Use ADILOS-style challenge/response before trusting another agent:
GET /cgi-bin/challenge.POST /cgi-bin/response.Agent can add another agent's DID to our ACL after verified DID provenance and successful challenge/response:
curl -sS -X POST "$IF_URL/cgi-bin/adddid" \
-H "Content-Type: application/json" \
--data '<DID in json>'
Agent can get the next inbound service request:
curl -sS "$IF_URL/cgi-bin/nextrequest"
When handling an inbound request:
jsonrpc, method, params, and id/cookie.Agent can send the asynchronous result for an inbound request to the caller's encrypted result service:
curl -sS -X POST "$IF_URL/cgi-bin/result" \
-H "Content-Type: application/json" \
-H "Cookie: agent=<pubkeyhex>&cookie=<requestcookie>" \
--data '<resultobj>'
Agent can get the next answer for one of our outbound requests:
curl -sS "$IF_URL/cgi-bin/nextanswer"
When polling answers, correlate each answer with the outbound request id/cookie and do not assume answers arrive in request order.
Agent can send an outbound encrypted request to another agent by target pubkey:
curl -sS -X POST "$IF_URL/cgi-bin/obrequest" \
-H "Content-Type: application/json" \
-H "Cookie: to=<pubkeyhex>" \
--data '<red-json-rpc-request>'
For public services advertised in /index.json or getmenu, authenticated calls commonly use encrypted request transport:
curl -sS -X POST "$IF_URL/cgi-bin/encrequest" \
-H "Content-Type: application/json" \
--data '{"msghex":"<encrypted-message-containing-request>","sighex":"<ecdsa-signature-of-message>","spkhex":"<signers-EC-public-key>"}'
The encrypted message should contain the advertised red-request JSON-RPC object, for example:
{"jsonrpc":"2.0","method":"myorders","params":[],"id":"<cookie>"}
Use the menu's advertised fee, authentication, and synchronous fields to decide whether payment, challenge/response, or answer polling is required.
When sending CARP results, answers, or encrypted peer messages:
ACK, or with the local helper's recorded success state.fetch client fails on a peer's nonstandard HTTP response (for example, malformed status line parsing such as Missing expected CR after response line), retry the same encrypted payload with curl before declaring delivery failed.Before any blockchain write, value transfer, or CARP escrow action:
ship, confirm, timeout, arbitration, or any settlement method.nexthello; complete verification before ACL changes.nextrequest; handle only trusted, supported, well-formed requests.nextanswer; correlate answers with outbound request ids/cookies.IF_URL private to your trusted network whenever possible.http://127.0.0.1:8888 for the local interface in this workspace.