Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Register and manage ERC-8004 Identity NFTs on Monad. Use when the agent needs to mint an on-chain identity for CEO Protocol registration or other ERC-8004–integrated protocols.
Register and manage ERC-8004 Identity NFTs on Monad. Use when the agent needs to mint an on-chain identity for CEO Protocol registration or other ERC-8004–integrated protocols.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
Use this skill when the agent must register on the ERC-8004 Identity Registry to obtain an on-chain identity NFT. This identity is required to register as an agent in The CEO Protocol (CEOVault). Reference: EIP-8004 Trustless Agents
ContractAddressERC-8004 Identity0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
The Identity Registry is ERC-721 based. Registering mints an NFT to msg.sender; the token ID is the agent ID.
FunctionPurposeregister(string agentURI)Register with a URI; mints NFT, returns agentIdregister(string agentURI, MetadataEntry[] metadata)Register with URI and on-chain metadataregister()Register with no URI (set later via setAgentURI)setAgentURI(uint256 agentId, string newURI)Update the agent's URIsetMetadata(uint256 agentId, string metadataKey, bytes metadataValue)Set on-chain metadata
FunctionReturnsUseownerOf(uint256 tokenId)addressCheck who owns an agent NFTtokenURI(uint256 tokenId)stringGet agent URI (same as agentURI)getAgentWallet(uint256 agentId)addressGet wallet linked to agentgetMetadata(uint256 agentId, string metadataKey)bytesGet on-chain metadata
EventUseRegistered(uint256 indexed agentId, string agentURI, address indexed owner)Emitted on mintURIUpdated(uint256 indexed agentId, string newURI, address indexed updatedBy)Emitted on URI changeMetadataSet(uint256 indexed agentId, string indexed metadataKey, string metadataKey, bytes metadataValue)Emitted on metadata set
The agentURI must resolve to a JSON document conforming to EIP-8004 registration. Use this template and replace placeholders before hosting (IPFS or data URI): { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "AGENT_NAME", "description": "AGENT_DESCRIPTION", "image": "https://example.com/agent-image.png", "services": [ { "name": "A2A", "endpoint": "https://YOUR_DOMAIN/.well-known/agent-card.json", "version": "0.3.0" }, { "name": "MCP", "endpoint": "https://YOUR_DOMAIN/mcp", "version": "2025-06-18" } ], "x402Support": false, "active": true, "registrations": [], "supportedTrust": [ "reputation" ] } FieldReplace withAGENT_NAMEAgent display nameAGENT_DESCRIPTIONShort description of capabilitiesimageURL to agent avatar/imageYOUR_DOMAINYour domain for A2A/MCP endpoints (or omit services if not applicable)supportedTrustTrust models (e.g. ["reputation"] for CEO Protocol) For a minimal CEO Protocol–only registration, you can omit services or set them to empty; supportedTrust: ["reputation"] is typical.
The Docker image includes production-ready scripts at: /opt/erc8004-scripts Source in workspace: /root/.openclaw/workspace/skills/8004-skill/scripts
MONAD_RPC_URL MONAD_CHAIN_ID=143 (or pass --chainId) AGENT_PRIVATE_KEY PINATA_JWT PINATA_GATEWAY (recommended for verification fetch)
# 1) Register on-chain with empty URI -> returns agentId node /opt/erc8004-scripts/register.mjs --network monad-mainnet # 2) Build card JSON with registrations[] embedded node /opt/erc8004-scripts/build-card.mjs \ --network monad-mainnet \ --agentId 42 \ --template /root/.openclaw/workspace/skills/8004-skill/assets/registration-template.json \ --name "CEO-1" \ --description "Autonomous strategist for The CEO Protocol" \ --out /tmp/agent-42.json # 3) Upload to Pinata -> returns ipfs://CID node /opt/erc8004-scripts/upload-pinata.mjs --file /tmp/agent-42.json # 4) Set token URI on-chain node /opt/erc8004-scripts/set-agent-uri.mjs \ --network monad-mainnet \ --agentId 42 \ --uri ipfs://CID # 5) Verify owner, tokenURI, wallet, and registrations[] match node /opt/erc8004-scripts/verify.mjs --network monad-mainnet --agentId 42
node /opt/erc8004-scripts/full-register.mjs \ --network monad-mainnet \ --name "CEO-1" \ --description "Autonomous strategist for The CEO Protocol" \ --template /root/.openclaw/workspace/skills/8004-skill/assets/registration-template.json \ --outCard /tmp/agent-card.json \ --identityFile /root/.openclaw/workspace/AGENT_IDENTITY.md This executes all 4 registration steps (register -> build card -> upload -> set URI) and writes identity state for later CEO Protocol onboarding.
Prerequisites Wallet with MON for gas (use viem-local-signer address to confirm signer). agentURI: a URI pointing to your registration JSON (use the template above). Use IPFS (ipfs://...) or a data URI (data:application/json;base64,...). Call register(agentURI) Encode calldata with encodeFunctionData. Send via viem-local-signer send-contract. Parse Registered event or return value for agentId. Store agentId The returned agentId (token ID) is required for CEO Protocol registerAgent(metadataURI, ceoAmount, erc8004Id). Persist it in an identity file (see below).
FieldSourceExampleAddressviem-local-signer address (signer wallet)0xB4AF3708DA37a485E84b4F09c146eD0A8B7Df5c4Agent IDReturn value from register(agentURI)42Agent RegistryERC-8004 Identity contract (Monad: eip155:143:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432)eip155:143:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432Chain IDMonad mainnet143
[ { "type": "function", "name": "register", "stateMutability": "nonpayable", "inputs": [{ "name": "agentURI", "type": "string" }], "outputs": [{ "name": "agentId", "type": "uint256" }] }, { "type": "function", "name": "register", "stateMutability": "nonpayable", "inputs": [ { "name": "agentURI", "type": "string" }, { "name": "metadata", "type": "tuple[]", "components": [ { "name": "metadataKey", "type": "string" }, { "name": "metadataValue", "type": "bytes" } ] } ], "outputs": [{ "name": "agentId", "type": "uint256" }] }, { "type": "function", "name": "register", "stateMutability": "nonpayable", "inputs": [], "outputs": [{ "name": "agentId", "type": "uint256" }] }, { "type": "function", "name": "setAgentURI", "stateMutability": "nonpayable", "inputs": [ { "name": "agentId", "type": "uint256" }, { "name": "newURI", "type": "string" } ], "outputs": [] }, { "type": "function", "name": "setMetadata", "stateMutability": "nonpayable", "inputs": [ { "name": "agentId", "type": "uint256" }, { "name": "metadataKey", "type": "string" }, { "name": "metadataValue", "type": "bytes" } ], "outputs": [] }, { "type": "function", "name": "ownerOf", "stateMutability": "view", "inputs": [{ "name": "tokenId", "type": "uint256" }], "outputs": [{ "name": "", "type": "address" }] }, { "type": "function", "name": "tokenURI", "stateMutability": "view", "inputs": [{ "name": "tokenId", "type": "uint256" }], "outputs": [{ "name": "", "type": "string" }] }, { "type": "function", "name": "getAgentWallet", "stateMutability": "view", "inputs": [{ "name": "agentId", "type": "uint256" }], "outputs": [{ "name": "", "type": "address" }] }, { "type": "function", "name": "getMetadata", "stateMutability": "view", "inputs": [ { "name": "agentId", "type": "uint256" }, { "name": "metadataKey", "type": "string" } ], "outputs": [{ "name": "", "type": "bytes" }] } ]
Use viem to encode, then viem-local-signer send-contract to broadcast. Example (Node/script): import { encodeFunctionData } from "viem"; const ERC8004_IDENTITY = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432"; const abi = [ { type: "function", name: "register", stateMutability: "nonpayable", inputs: [{ name: "agentURI", type: "string" }], outputs: [{ name: "agentId", type: "uint256" }], }, ] as const; const agentURI = "ipfs://Qm..."; // or data:application/json;base64,... const data = encodeFunctionData({ abi, functionName: "register", args: [agentURI], }); // Then run: // viem-local-signer send-contract --to 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 --data <hex> --value-wei 0 --wait
Confirm signer: viem-local-signer address Ensure wallet has MON for gas. Prepare agentURI (IPFS or data URI with registration JSON). Encode register(agentURI) with viem. Present tx summary and ask for user confirmation. Run viem-local-signer send-contract --to 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 --data <calldata> --value-wei 0 --wait Parse receipt/logs for agentId (or read from Registered event). Write identity file (workspace/AGENT_IDENTITY.md or workspace/IDENTITY.md) using the template above with Address, Agent ID, Agent Registry, Chain ID.
CEOVault requires an ERC-8004 identity before registerAgent: CEOVault.registerAgent(metadataURI, ceoAmount, erc8004Id) erc8004Id = the token ID from ERC8004Identity.register(...). Caller must own that NFT (ownerOf(erc8004Id) == msg.sender).
Monad: https://monadscan.com/ Tx link: https://monadscan.com/tx/<hash> Contract: https://monadscan.com/address/0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
Long-tail utilities that do not fit the current primary taxonomy cleanly.
Largest current source with strong distribution and engagement signals.