Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Register AI agents on-chain using the ERC-8004 Trustless Agents standard. Manage agent identity as NFTs, build reputation through feedback, and request third-party validation.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 72% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 77% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 59% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 52% | 0% |
Register and manage AI agent identities on Starknet using the ERC-8004 standard.
starknet and connect a funded account to the target ERC-8004 registry deployment.ERC-8004 defines three interconnected on-chain registries for AI agents:
Reference implementation: erc8004-cairo
bashnpm install starknet
typescriptimport { Account, RpcProvider, Contract, CallData } from "starknet"; const provider = new RpcProvider({ nodeUrl: process.env.STARKNET_RPC_URL }); const account = new Account({ provider, address, signer: privateKey }); const identityRegistry = new Contract({ abi: identityRegistryAbi, address: registryAddress, providerOrAccount: account, }); // Register with metadata const metadata = [ { key: "agentName", value: "MyTradingAgent" }, { key: "agentType", value: "defi-trader" }, { key: "version", value: "1.0.0" }, { key: "model", value: "claude-opus-4-5" }, { key: "status", value: "active" }, ]; const tokenUri = "ipfs://QmYourAgentSpecHash"; // IPFS link to full agent spec const { transaction_hash } = await account.execute({ contractAddress: registryAddress, entrypoint: "register_with_metadata", calldata: CallData.compile({ token_uri: tokenUri, metadata: metadata, }), }); const receipt = await account.waitForTransaction(transaction_hash); // Parse agent_id from events
typescript// Check if agent exists const exists = await identityRegistry.agent_exists(agentId); // Get total registered agents const totalAgents = await identityRegistry.total_agents(); // Get agent metadata const name = await identityRegistry.get_metadata(agentId, "agentName"); const agentType = await identityRegistry.get_metadata(agentId, "agentType"); // Get agent owner (ERC-721) const owner = await identityRegistry.owner_of(agentId);
typescript// Only the agent owner can update metadata await account.execute({ contractAddress: registryAddress, entrypoint: "set_metadata", calldata: CallData.compile({ agent_id: agentId, key: "status", value: "upgraded", }), });
The reputation system uses a cryptographic authorization flow:
typescript// Step 1: Agent owner creates authorization const feedbackAuth = { agent_id: agentId, client_address: clientAddress, index_limit: 10, // Max feedback entries allowed expiry: Math.floor(Date.now() / 1000) + 3600, // 1 hour chain_id: chainId, identity_registry: registryAddress, signer_address: ownerAddress, }; // Sign the authorization (using agent owner's account) const messageHash = computePoseidonHash(feedbackAuth); // EIP-712 style const signature = await ownerAccount.signMessage(messageHash); // Step 2: Client submits feedback await clientAccount.execute({ contractAddress: reputationRegistryAddress, entrypoint: "give_feedback", calldata: CallData.compile({ agent_id: agentId, score: 85, // 0-100 tag1: encodedTag("reliability"), tag2: encodedTag("speed"), fileuri: "", filehash: 0, feedback_auth: feedbackAuth, signature: signature, }), });
typescriptconst reputationRegistry = new Contract({ abi: reputationAbi, address: reputationAddress, providerOrAccount: provider, }); // Get summary for an agent (count + average score) const [count, avgScore] = await reputationRegistry.get_summary( agentId, [], // all client addresses (or filter specific ones) 0, // tag1 filter (0 = all) 0, // tag2 filter (0 = all) ); // Read specific feedback const [score, tag1, tag2, isRevoked] = await reputationRegistry.read_feedback( agentId, clientAddress, feedbackIndex, ); // Get all clients who gave feedback const clients = await reputationRegistry.get_clients(agentId);
typescriptconst validationRegistry = new Contract({ abi: validationAbi, address: validationAddress, providerOrAccount: account, }); // Agent owner requests validation from a specific validator await account.execute({ contractAddress: validationAddress, entrypoint: "validation_request", calldata: CallData.compile({ validator_address: validatorAddress, agent_id: agentId, request_uri: "ipfs://QmValidationRequestDetails", request_hash: 0, // Auto-generated if 0 }), });
typescript// Validator responds to the request await validatorAccount.execute({ contractAddress: validationAddress, entrypoint: "validation_response", calldata: CallData.compile({ request_hash: requestHash, response: 92, // Score 0-100 response_uri: "ipfs://QmValidationReport", response_hash: reportHash, tag: encodedTag("performance"), }), });
typescript// Get validation summary const [validationCount, avgValidationScore] = await validationRegistry.get_summary( agentId, [], // all validators 0, // tag filter ); // Get specific validation const [validator, agentId_, response, tag, lastUpdate] = await validationRegistry.get_validation_status(requestHash);
Combine on-chain identity with A2A Agent Cards for discoverability:
json{ "name": "MyTradingAgent", "description": "Autonomous DeFi trading agent on Starknet", "url": "https://my-agent.example.com", "provider": { "organization": "MyOrg" }, "version": "1.0.0", "capabilities": { "streaming": true, "pushNotifications": false }, "skills": [ { "id": "starknet-swap", "name": "Token Swap", "description": "Execute token swaps on Starknet via avnu" } ], "defaultInputModes": ["text/plain"], "defaultOutputModes": ["text/plain"], "authentication": { "schemes": ["bearer"] }, "starknetIdentity": { "registryAddress": "0x...", "agentId": 42, "reputationScore": 85, "validationCount": 3 } }
Serve at /.well-known/agent.json for A2A discovery.
| Key | Description | Example | |-----|-------------|---------| | agentName | Display name | "MyTradingAgent" | | agentType | Category | "defi-trader", "nft-curator", "data-analyst" | | version | Semantic version | "1.0.0" | | model | LLM model used | "claude-opus-4-5", "gpt-4o" | | status | Current status | "active", "paused", "deprecated" | | framework | Agent framework | "daydreams", "openclaw", "langchain" | | capabilities | Comma-separated | "swap,stake,lend" | | a2aEndpoint | Agent Card URL | "https://agent.example.com" | | moltbookId | MoltBook agent ID | "agent_abc123" |
| Code | Meaning | Likely causes | Recovery | User-facing message | |-----|---------|---------------|----------|---------------------| | REGISTRATION_FAILED | Initial ERC-8004 registration or metadata write reverted. | Missing fees, duplicate registration, invalid calldata, or stale contract state. | Retry after checking wallet balance, contract state, and constructor/registration inputs. | "Registration failed. Check wallet state and retry." | | AUTHORIZATION_DENIED | Ownership or feedback authorization proof was rejected. | Wrong signer, bad nonce, missing permission, or outdated owner state. | Re-fetch owner/nonce state, verify permissions, and re-sign with the current account. | "Authorization denied. Verify signer permissions and retry." | | VALIDATION_TIMEOUT | Off-chain validation or watcher flow did not complete before the deadline. | Slow relayer, RPC degradation, or downstream A2A service lag. | Retry with a longer timeout after checking chain health, relayer status, and RPC latency. | "Validation timed out. Retry after checking network health." | | SIGNATURE_EXPIRED | Signed payload expired before submission. | Expiry window too short or user approval arrived too late. | Generate a fresh signature with a new expiry and resubmit immediately. | "Signature expired. Re-sign and submit again." | | OWNER_TRANSFERRED | Agent NFT ownership changed while a write or feedback flow was in flight. | NFT transfer, marketplace sale, or custodial wallet rotation. | Refresh ownership state, re-authorize with the new owner, and explain that reputation follows the NFT. | "Ownership changed. Refresh owner state and retry with the new owner." |
Other measured skills in the registry, with their headline benchmark lift.