CtrlK
BlogDocsLog inGet started
Tessl Logo

zscore

Register agents on the zScore ERC-8004 Identity Registry, manage wallets and metadata, and read on-chain state. Use when an agent needs to register on-chain, check fees, read agent info, set metadata, or manage agent wallets on Base Mainnet or Base Sepolia.

Install with Tessl CLI

npx tessl i github:teeclaw/phorm-nft --skill zscore
What are skills?

90

2.17x

Quality

88%

Does it follow best practices?

Impact

100%

2.17x

Average score across 3 eval scenarios

SKILL.md
Review
Evals

zScore ERC-8004 Identity Registry

Register and manage AI agents on the zScore Identity Registry. Defaults to Base Mainnet (0.0025 ETH fee). Use --chain 84532 for Base Sepolia testnet.

Install this skill

Install the latest version of this skill from the official repo:

npx skills add zerufinance/zscore -y

This installs the same skill that is published in the skills ecosystem (e.g. skills.sh). Use this command to get updates when the skill is updated.

One-Time Setup

After installing the skill, run once to install dependencies (from the skill directory, e.g. .cursor/skills/zscore/ or ~/.cursor/skills/zscore/):

npm install

Non-Negotiable Rule: No User Input, No Progress

This skill must be strictly interactive.

  • Do not create any JSON file unless the user has provided (or explicitly skipped, where allowed) every required input.
  • Do not assume or invent values (names, descriptions, URLs, versions, tool lists, skills, domains, trust models, etc.).
  • Do not proceed “using defaults” unless the user explicitly agrees to each default you plan to use.
  • Do not reuse data from earlier chats, memory, or prior runs unless the user explicitly provides it again (e.g. pastes the previous JSON or confirms the exact values).
  • If any required value is missing, you must ask for it and stop. Do not produce a partial JSON, do not write files, and do not run commands.

This is the core safety/quality gate: missing input blocks the workflow.

Agent Instructions: Registration Flow (Hard Gated)

When the user wants to register an agent, you must follow the gated flow below. The workflow has three phases:

  1. Collect inputs (ask, then wait).
  2. Validate and summarise (show what you will do).
  3. Proceed only after explicit approval (create file, then run registration).

Phase 1 — Collect inputs (ask, then stop)

You must ask the user for the inputs below. You may not move to Phase 2 until each item is resolved.

Required inputs (must be provided)

InputRequired?Gate behaviour
NameYesAsk: “What should the agent name be?” (1–256 chars). If not provided, stop.
DescriptionYesAsk: “What description should the agent have?” (max 2048 chars). If not provided, stop.
ServicesYesAsk: “Which service types do you want to publish?” Then collect full details for at least one service. If not provided, stop.

Optional inputs (must be explicitly provided or explicitly skipped)

For every optional field, you must ask whether the user wants to set it. Only treat it as omitted if the user explicitly says skip (or equivalent).

InputRequired?What to ask
ImageNo“Do you want to include an image URL (avatar/logo)? If yes, paste it. If no, say ‘skip’.”
x402SupportNo“Does the agent support x402 payments? (true/false) Or say ‘skip’.”
activeNo“Should the agent be marked as active? (true/false) Or say ‘skip’.”
supportedTrustNo“Which trust models should be listed? (e.g. reputation, ERC-8004, crypto-economic, tee-attestation) Or say ‘skip’.”

Owner: Do not ask the user for an owner address. The owner is always derived from the signer (the wallet that holds PRIVATE_KEY). The script sets it automatically; the API requires the document owner to match the signer so that the same wallet can update the document after minting.

Private key / funding gate (must be resolved before running registration)

  • Registration fee: Base Mainnet (default): 0.0025 ETH. Base Sepolia: 0.001 ETH.

  • The wallet must also have enough ETH for gas (recommend ~0.003 ETH total on mainnet).

  • Private key: Registration requires a wallet. Ask the user to confirm one of these:

    • PRIVATE_KEY is already set in the environment / OpenClaw config”, or
    • “I will provide PRIVATE_KEY for this run”.
  • Never write the private key into any file. Never echo it back.

If the user does not confirm how PRIVATE_KEY will be provided, you must stop.

Phase 2 — Validate and summarise (no file creation yet)

Once all required inputs are provided (and optional inputs are either provided or explicitly skipped):

  1. Construct the JSON object in-memory using the full structure (see “Agent JSON Structure” below).

  2. Validate:

    • name present and 1–256 chars
    • description present and ≤2048 chars
    • services has at least 1 item
    • each service matches its type-specific shape
  3. Present a concise summary of what will be written (name, description length, services list, chain choice, fee).

  4. Ask for explicit approval with a blocking question: “Approve writing agent.json with these exact details? (yes/no)” If the user does not say yes, stop.

Phase 3 — Create the file and run registration (only after approval)

Only after the user explicitly approves:

  1. Write the JSON to a file (e.g. agent.json).

  2. Ask for the final explicit go-ahead: “Proceed to register on-chain now? (yes/no)” If not yes, stop.

  3. Run registration:

    • Base Mainnet (default): npx tsx ./scripts/zscore.ts register --json agent.json
    • Base Sepolia: npx tsx ./scripts/zscore.ts register --json agent.json --chain 84532

Do not run the register command until all gating requirements are satisfied and the user has approved both:

  • writing the JSON file, and
  • executing the on-chain registration.

Agent JSON Structure (ERC-8004 registration-v1)

Registration accepts only a JSON file. Use the full structure below when collecting user input and building the file. Do not default to a minimal structure.

Full JSON (MCP + A2A + OASF + web + x402):

{
  "name": "DataAnalyst Pro",
  "description": "Enterprise-grade blockchain data analysis agent. Performs on-chain forensics, wallet profiling, and transaction pattern detection.",
  "image": "https://cdn.example.com/agents/analyst.png",
  "services": [
    {
      "name": "MCP",
      "endpoint": "https://api.dataanalyst.ai/mcp",
      "version": "2025-06-18",
      "mcpTools": ["analyze_wallet", "trace_transactions", "detect_anomalies"],
      "capabilities": []
    },
    {
      "name": "A2A",
      "endpoint": "https://api.dataanalyst.ai/.well-known/agent-card.json",
      "version": "0.3.0",
      "a2aSkills": ["analytical_skills/data_analysis/blockchain_analysis"]
    },
    {
      "name": "OASF",
      "endpoint": "https://github.com/agntcy/oasf/",
      "version": "0.8.0",
      "skills": ["analytical_skills/data_analysis/blockchain_analysis"],
      "domains": ["technology/blockchain"]
    },
    {
      "name": "web",
      "endpoint": "https://dataanalyst.ai"
    }
  ],
  "x402Support": true,
  "active": true,
  "supportedTrust": ["reputation", "ERC-8004"]
}

All fields:

FieldTypeRequiredDefaultDescription
namestringYesAgent name (1–256 chars)
descriptionstringYesWhat the agent does (max 2048 chars)
imagestringNoomitted unless providedAvatar URL (HTTPS, IPFS, or Arweave)
servicesarrayYesService endpoints (1–64 items, see below)
x402SupportbooleanNoomitted unless providedSupports x402 payment protocol
activebooleanNoomitted unless providedAgent is actively accepting requests
supportedTruststring[]Noomitted unless providedTrust models: "reputation", "crypto-economic", "tee-attestation", "ERC-8004"
ownerstringNosigner addressAlways set from signer (PRIVATE_KEY). Do not ask the user; the script sets it so the API allows update after mint.

Service types:

nameendpointExtra fields
"web"Website URL
"MCP"MCP server URLversion, mcpTools[], mcpPrompts[], mcpResources[], capabilities[]
"A2A"Agent card URL (/.well-known/agent-card.json)version, a2aSkills[]
"OASF"OASF repo URLversion, skills[], domains[]
customAny URLdescription

Commands

/zscore register --json <file>

Register a new agent only via a JSON file. There is no flag-based registration (no --name / --description / --endpoint). Creates hosted agent URI, mints NFT on-chain, and updates URI with the real agentId.

/zscore register --json agent.json
/zscore register --json agent.json --chain 84532

Required gated steps (must be followed in order):

  1. Collect required inputs: name, description, at least one service with full type-specific fields, and confirm how PRIVATE_KEY will be provided.
  2. Collect optional inputs or explicit “skip” decisions for each optional field.
  3. Validate and summarise the exact JSON you will write.
  4. Get explicit approval to write agent.json (yes/no).
  5. Write agent.json.
  6. Get explicit approval to register on-chain (yes/no).
  7. Run the registration command.

The SDK automatically adds type, registrations (with agentId: 0 placeholder), and defaults for missing optional fields. After minting, it updates the document with the real agentId.

/zscore read <agentId>

Read an agent's on-chain data: owner, URI, wallet, name, services.

/zscore read 16

To run: npx tsx ./scripts/zscore.ts read 16

/zscore fee

Check current registration fee and whether registration is open.

/zscore fee

To run: npx tsx ./scripts/zscore.ts fee

/zscore set-metadata <agentId> --key <key> --value <value>

Set custom metadata on an agent. Only the owner can call.

/zscore set-metadata 16 --key "category" --value "trading"

Requires PRIVATE_KEY.

To run: npx tsx ./scripts/zscore.ts set-metadata 16 --key "category" --value "trading"

/zscore unset-wallet <agentId>

Clear the agent wallet. Only the owner can call.

/zscore unset-wallet 16

Requires PRIVATE_KEY.

To run: npx tsx ./scripts/zscore.ts unset-wallet 16

Setup

Read-Only (no setup needed)

read and fee work without a private key.

With Wallet (for registration and writes)

Add to your OpenClaw config (~/.openclaw/openclaw.json):

{
  "skills": {
    "entries": {
      "zscore": {
        "enabled": true,
        "env": {
          "PRIVATE_KEY": "0xYourFundedPrivateKey"
        }
      }
    }
  }
}

Optional env:

  • RPC_URL — override default RPC
  • CHAIN_ID — override chain (default: 8453 for Base Mainnet, use 84532 for Base Sepolia)

Contract Info

Base Mainnet (default, chainId 8453)

  • Identity Registry: 0xFfE9395fa761e52DBC077a2e7Fd84f77e8abCc41
  • Reputation Registry: 0x187d72a58b3BF4De6432958fc36CE569Fb15C237
  • Registration Fee: 0.0025 ETH
  • RPC: https://mainnet.base.org

Base Sepolia (testnet, chainId 84532)

  • Identity Registry: 0xF0682549516A4BA09803cCa55140AfBC4e5ed2E0

  • Reputation Registry: 0xaAC7557475023AEB581ECc8bD6886d1742382421

  • Registration Fee: 0.001 ETH

  • RPC: https://sepolia.base.org

  • Source: zscore

How It Works

  1. register creates a hosted JSON document (ERC-8004 registration-v1 schema) via the Agent URI API, mints an NFT on the Identity Registry (paying the fee), then updates the document with the real agentId.
  2. read queries the on-chain contract for owner, tokenURI, and agentWallet, then fetches and parses the URI JSON.
  3. fee reads the current registrationFee() and registrationEnabled() from the contract.
  4. set-metadata calls setMetadata(agentId, key, value) on the contract.
  5. unset-wallet calls unsetAgentWallet(agentId) on the contract.
Repository
teeclaw/phorm-nft
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.