Description
Recommended offchain data profile for ERC-8004 agent registration
This document provides implementation-agnostic guidance for structuring agent metadata referenced by the agentURI field in ERC-8004 Identity Registry contracts.
Document Purpose
This profile document offers practical, non-normative recommendations for agent metadata formats, based on analysis of real-world ERC-8004 deployments and community feedback.
Key Characteristics:
- ✅ Implementation-agnostic: Applicable to any ERC-8004 registry or explorer
- ✅ Evidence-based: Informed by analysis of 4,725 production agents
- ✅ Flexible: Supports custom extensions while promoting interoperability
- ✅ Non-normative: Guidelines and best practices, not requirements
Relationship to EIP-8004
Important: This is not part of the official EIP-8004 specification.
Official EIP-8004 defines:
- Smart contract interfaces for Identity Registry
- The
agentURIfield that references metadata - Onchain behavior requirements
This profile suggests:
- Offchain JSON structure and field patterns
- Protocol endpoint formats (MCP, A2A, OASF)
- Best practices from production deployments
The official EIP-8004 specification does not mandate specific offchain formats. These are community-developed guidelines to improve interoperability.
Terminology
This document follows conventions defined in Conventions, including:
- RFC 2119 keywords: MUST, SHOULD, MAY (see Conventions - RFC 2119)
- Field types: string, number, boolean, object, array (see Conventions - Field Type System)
- CAIP formats: CAIP-2 for blockchain IDs, CAIP-10 for addresses (see Conventions - Address Formats)
- Timestamps: ISO 8601 format in UTC (see Conventions - Timestamp Format)
Intended Audience
- Agent Developers: Creating and registering new agents
- Registry Implementers: Building ERC-8004 Identity Registry contracts and indexers
- Explorer Developers: Parsing and displaying agent metadata
- Tool Builders: Creating SDKs and validation libraries
Table of Contents
- Overview
- AgentURI Metadata Format
- Recommended Fields
- Endpoint Types
- Optional Fields
- URI Format Standards
- Data URI Compression Extension (Optional) ⭐
- Onchain Metadata
- Validation Levels
- Real-World Patterns
- Migration Guides
Overview
What is AgentURI Metadata?
The AgentURI (also called Agent Metadata or Registration File) is the offchain data that describes an AI agent registered on ERC-8004 registries. It resolves from the agentURI field in the onchain NFT to a JSON object containing the agent's identity, capabilities, and communication endpoints.
Key Functions:
- 📋 Agent Profile: Name, description, and avatar for explorers and NFT marketplaces
- 🔌 Connectivity: Endpoints for MCP, A2A, OASF protocols
- 💰 Payments: Agent wallet addresses for x402 protocol
- 🔗 Verification: Bidirectional link to onchain registry
- 🏷️ Trust Models: Supported validation and reputation patterns
Non-normative: These functions represent common use cases observed in production deployments. Implementations MAY use agent metadata for other purposes.
Architecture
┌─────────────────────────────────────────────────────────────┐
│ ERC-8004 Registry │
│ AgentNFT #123 │
│ ├─ owner: 0xABCD... │
│ ├─ agentURI: ipfs://bafkrei... ────────┐ │
│ └─ metadata[]: key-value pairs │ │
└───────────────────────────────────────────│─────────────────┘
│
▼
┌─────────────────────────┐
│ AgentURI Metadata │
│ (Offchain JSON) │
└─────────────────────────┘
│
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Agent Profile│ │ Endpoints │ │ Registrations│
│ │ │ │ │ │
│ - name │ │ - MCP │ │ - agentId │
│ - description│ │ - A2A │ │ - registry │
│ - image │ │ - OASF │ │ │
│ - active │ │ - agentWallet│ │ │
└──────────────┘ └──────────────┘ └──────────────┘2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
AgentURI Metadata Format
Complete Schema
{
// ============ REQUIRED FIELDS (MUST) ============
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "DataAnalyst Pro",
"description": "A specialized AI agent that performs advanced data analysis on blockchain transactions, providing insights and anomaly detection.",
"image": "https://cdn.example.com/agents/dataanalyst-pro.png",
// ============ RECOMMENDED FIELDS (SHOULD) ============
"endpoints": [
{
"name": "MCP",
"endpoint": "https://api.example.com/mcp",
"version": "2025-06-18",
"mcpTools": ["analyze_wallet", "detect_anomalies"],
"mcpPrompts": ["What are the risks?", "Analyze this address"]
},
{
"name": "A2A",
"endpoint": "https://agent.example/.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": "v0.8.0",
"skills": [
"analytical_skills/data_analysis/blockchain_analysis",
"analytical_skills/pattern_recognition/anomaly_detection"
],
"domains": ["technology/blockchain", "finance_and_business/investment_services"]
},
{
"name": "agentWallet",
"endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7"
}
],
"registrations": [
{
"agentId": 241,
"agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847"
}
],
// ============ OPTIONAL FIELDS (MAY) ============
"supportedTrust": ["reputation", "crypto-economic"],
"active": true,
"x402support": true,
"updatedAt": 1763112328
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Recommended Fields
The following fields are recommended for maximum interoperability. Implementations MAY omit these fields or add custom extensions, but including them improves compatibility with explorers and tools.
type (Recommended)
Type: string
Constraints: For this profile, SHOULD be "https://eips.ethereum.org/EIPS/eip-8004#registration-v1"
Purpose: Identifies this metadata as following the ERC-8004 agent registration profile.
Note: The EIP-8004 specification does not mandate this field. This is a profile identifier to help parsers recognize the format. Other profile identifiers MAY exist for alternative metadata formats.
Example:
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1"
}2
3
Validation:
- ⚠️ Missing:
missing_required_typewarning (reduces interoperability) - ⚠️ Non-standard value:
invalid_type_fieldwarning
name (Recommended)
Type: string
Constraints: Recommended length: 3–200 characters
Purpose: Agent name displayed in explorers, NFT marketplaces, and user interfaces.
Guidelines:
- SHOULD be unique and descriptive
- Avoid generic names like "Agent #123" (use meaningful identifiers)
- For ERC-721 compatibility, this field is highly recommended
Examples:
{
"name": "DataAnalyst Pro"
}2
3
Validation:
- ⚠️ Missing:
missing_required_namewarning - ⚠️ Empty string: validation warning
Note: While the official EIP-8004 lists
nameas SHOULD (not MUST), this profile treats it as practically required for visibility in explorers and NFT marketplaces. The field is derived from ERC-721 token metadata standards.
description (MUST)
Type: string
Purpose: Natural language description of what the agent does, how it works, pricing, and interaction methods.
Guidelines:
Explain agent capabilities clearly
Include interaction methods (e.g., "Call via MCP endpoint")
Mention pricing if applicable (e.g., "Free tier available")
Recommended length: 50-500 characters
Examples:
{
"description": "A specialized AI agent that performs advanced data analysis on blockchain transactions, providing insights and anomaly detection. Supports both free and premium tiers via x402 protocol."
}2
3
Validation:
- ❌ Missing:
missing_required_descriptionwarning
image (MUST)
Type: string (URI)
Purpose: Agent avatar/logo displayed in explorers and NFT marketplaces.
Supported Formats:
- PNG (recommended)
- SVG (vector graphics)
- WebP (modern format)
- JPG/JPEG (acceptable)
URI Schemes:
https://- Direct HTTPS URL (recommended for reliability)ipfs://- IPFS content hashar://- Arweave transaction IDdata:image/png;base64,...- Inline base64 (only for small images)
Guidelines:
Recommended size: 512x512 px minimum
Aspect ratio: 1:1 (square) preferred
Max file size: 5 MB
Use CDN for faster loading
Examples:
{
"image": "https://cdn.example.com/agents/dataanalyst-pro.png"
}2
3
{
"image": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4"
}2
3
Validation:
- ❌ Missing:
missing_recommended_imagewarning - ⚠️ Relative path: validation warning (should be absolute URI)
Additional Recommended Fields
endpoints (SHOULD)
Type: array of endpoint objects
Purpose: Communication endpoints for interacting with the agent.
Importance: MUST include at least one endpoint if agent is meant to be interacted with.
General Structure:
{
"name": "EndpointType",
"endpoint": "url_or_identifier",
"version": "protocol_version"
// ... type-specific fields
}2
3
4
5
6
7
Validation:
- ❌ Missing:
missing_endpointswarning - ⚠️ Empty array:
empty_endpointswarning (agent not reachable) - ⚠️ Common typo:
endpoint(singular) instead ofendpoints(plural)
See Endpoint Types section for detailed specifications.
registrations (SHOULD)
Type: array of registration objects
Purpose: Links to on-chain NFT identity, creating cryptographic bidirectional verification.
Structure:
{
"registrations": [
{
"agentId": 241,
"agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847"
}
]
}2
3
4
5
6
7
8
Fields:
agentId(number): Token ID from ERC-721 registryagentRegistry(string): CAIP-10 formatnamespace:chainId:contractAddress
CAIP-10 Format:
namespace : chainId : reference
↓ ↓ ↓
eip155 : 1 : 0x8004a6090Cd10A7288092483047B097295Fb88472
3
Chain ID Examples:
- Ethereum Mainnet:
eip155:1:0x... - Sepolia Testnet:
eip155:11155111:0x... - Base Mainnet:
eip155:8453:0x... - Base Sepolia:
eip155:84532:0x... - Polygon:
eip155:137:0x...
Validation:
✅ MUST match the on-chain agent ID and registry that points to this metadata file
❌ Missing:
missing_registrationswarning⚠️ Empty array:
empty_registrationswarning⚠️ Null agentId:
registration_null_agent_idwarning⚠️ ID mismatch:
registration_agent_id_mismatchwarning⚠️ Invalid CAIP-10:
invalid_caip10_formatwarning
Circular Verification:
NFT (on-chain)
↓ agentURI points to
Metadata (offchain)
↓ registrations[0] points back to
NFT (on-chain) ✅ verified2
3
4
5
Endpoint Types
1. MCP (Model Context Protocol)
Purpose: Standard protocol for AI agents to expose tools, prompts, and resources.
Specification: MCP Protocol Docs
Structure:
{
"name": "MCP",
"endpoint": "https://api.example.com/mcp",
"version": "2025-06-18",
"mcpTools": ["analyze_wallet", "detect_anomalies"],
"mcpPrompts": ["What are the risks?", "Analyze this address"],
"mcpResources": ["wallet_history"],
"capabilities": {
"tools": {},
"prompts": {}
}
}2
3
4
5
6
7
8
9
10
11
12
Fields:
endpoint(string, REQUIRED): MCP server URLversion(string, REQUIRED): MCP protocol version (standard:"2025-06-18")mcpTools(array, OPTIONAL): List of available MCP toolsmcpPrompts(array, OPTIONAL): List of available promptsmcpResources(array, OPTIONAL): List of available resourcescapabilities(object, OPTIONAL): MCP server capabilities per spec
Validation:
- ❌ Missing
endpoint:mcp_missing_endpointwarning - ❌ Missing
version:mcp_missing_versionwarning - ⚠️ Non-standard version:
mcp_nonstandard_versionwarning
Example Usage:
// Client connects to MCP server
const client = new MCPClient("https://api.example.com/mcp");
const tools = await client.listTools(); // Returns mcpTools array
await client.callTool("analyze_wallet", { address: "0x..." });2
3
4
2. A2A (Agent-to-Agent Protocol)
Purpose: Enables agent-to-agent communication and collaboration.
Specification: A2A Protocol v0.3.0
Structure:
{
"name": "A2A",
"endpoint": "https://agent.example/.well-known/agent-card.json",
"version": "0.3.0",
"a2aSkills": [
"analytical_skills/coding_skills/text_to_code",
"natural_language_processing/information_retrieval_synthesis/question_answering"
]
}2
3
4
5
6
7
8
9
10
Fields:
endpoint(string, REQUIRED): URL to agent card (SHOULD use/.well-known/agent-card.jsonpath)version(string,https://schema.oasf.outshift.com/0.8.0dard:"0.3.0")a2aSkills(array, OPTIONAL but highly recommended): OASF skill slugs
Agent Card Format:
The endpoint should resolve to an agent card JSON file:
{
"name": "DataAnalyst Pro",
"description": "...",
"skills": ["analytical_skills/data_analysis/blockchain_analysis"],
"url": "https://agent.example",
"contact": "support@example.com"
}2
3
4
5
6
7
Validation:
- ❌ Missing
endpoint:a2a_missing_endpointwarning - ❌ Missing
version:a2a_missing_versionwarning - ⚠️ Non-standard version:
a2a_nonstandard_versionwarning - ⚠️ Missing
.well-knownpath:a2a_missing_well_knownwarning
Common Version Values:
"0.3.0"(standard)"0.30"(common typo, should be"0.3.0")
3. OASF (Open Agentic Schema Framework)
Purpose: Declares agent capabilities using standardized taxonomies for skills and domains.
Specification: OASF v0.8.0 Taxonomy
Schema Browser: https://schema.oasf.outshift.com/0.8.0
Structure:
{
"name": "OASF",
"endpoint": "https://github.com/agntcy/oasf/",
"version": "v0.8.0",
"skills": [
"analytical_skills/data_analysis/blockchain_analysis",
"analytical_skills/pattern_recognition/anomaly_detection",
"natural_language_processing/information_retrieval_synthesis/search"
],
"domains": [
"technology/blockchain",
"technology/blockchain/cryptocurrency",
"finance_and_business/investment_services"
]
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Fields:
endpoint(string, REQUIRED): OASF repository URL (standard:"https://github.com/agntcy/oasf/")version(string, REQUIRED): OASF taxonomy version (standard:"v0.8.0")skills(array, REQUIRED): OASF skill slugs (at least one ofskillsordomainsrequired)domains(array, REQUIRED): OASF domain slugs (at least one ofskillsordomainsrequired)
Skill Taxonomy:
OASF skills follow a hierarchical structure:
category / subcategory / specific_skill
↓ ↓ ↓
analytical_skills / data_analysis / blockchain_analysis2
3
Top 5 Skills (by usage in production):
natural_language_processing/natural_language_generation/summarization(40%)tool_interaction/api_schema_understanding(35%)multi_modal/image_processing/text_to_image(30%)natural_language_processing/information_retrieval_synthesis/search(28%)tool_interaction/workflow_automation(25%)
Domain Taxonomy:
OASF domains categorize agent application areas:
industry / sector / specialization
↓ ↓ ↓
finance_and_business / investment_services2
3
Top 5 Domains (by usage in production):
technology/blockchain(45%)finance_and_business/finance(35%)technology/software_engineering/apis_integration(30%)technology/blockchain/cryptocurrency(28%)media_and_entertainment/content_creation(25%)
Validation:
❌ Missing both
skillsanddomains:oasf_emptywarning⚠️ Invalid skill slug:
oasf_invalid_skillwarning⚠️ Invalid domain slug:
oasf_invalid_domainwarning⚠️ Non-standard version:
oasf_nonstandard_versionwarning
Resources:
- Complete skill list: all_skills.json
- Complete domain list: all_domains.json
4. agentWallet
Purpose: Payment wallet address for x402 protocol and agent-to-agent transactions.
Format: CAIP-10 (Account ID Specification)
Structure:
{
"name": "agentWallet",
"endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7"
}2
3
4
CAIP-10 Format:
namespace : chainId : accountAddress
↓ ↓ ↓
eip155 : 1 : 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb72
3
Chain Examples:
Ethereum Mainnet:
"eip155:1:0x..."Sepolia Testnet:
"eip155:11155111:0x..."Base Mainnet:
"eip155:8453:0x..."Base Sepolia:
"eip155:84532:0x..."Polygon:
"eip155:137:0x..."
Validation:
- ⚠️ Invalid CAIP-10 format:
wallet_invalid_formatwarning - ⚠️ Invalid checksum:
wallet_invalid_checksumwarning
Multiple Wallets:
Agents can have wallets on multiple chains:
{
"endpoints": [
{
"name": "agentWallet",
"endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7"
},
{
"name": "agentWallet",
"endpoint": "eip155:8453:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7"
}
]
}2
3
4
5
6
7
8
9
10
11
12
13
5. ENS Name
Purpose: Human-readable Ethereum Name Service identifier.
Structure:
{
"name": "ENS",
"endpoint": "dataanalyst.eth",
"version": "v1"
}2
3
4
5
Fields:
endpoint(string, REQUIRED): ENS name (e.g.,"myagent.eth")version(string, OPTIONAL): ENS version (typically"v1")
Usage:
Resolves to Ethereum address
Can be used for agent discovery
Human-friendly identifier
6. DID (Decentralized Identifier)
Purpose: W3C DID standard for decentralized identity.
Structure:
{
"name": "DID",
"endpoint": "did:ethr:0x1234567890abcdef1234567890abcdef12345678",
"version": "v1"
}2
3
4
5
6
Supported DID Methods:
did:ethr:...- Ethereum DIDdid:web:...- Web DIDdid:key:...- Key DID
Fields:
endpoint(string, REQUIRED): DID identifierversion(string, OPTIONAL): DID version
7. Custom Endpoints
The ERC-8004 spec allows arbitrary endpoint types for protocol-specific needs.
Example 1: Custom API:
{
"name": "StarCard API",
"version": "1.0.0",
"endpoint": "https://aliasai.io/api/v1/star_card/agent/{uid}",
"description": "Retrieve the user's complete star card information"
}2
3
4
5
6
Example 2: Custom Protocol:
{
"name": "wallet",
"endpoint": "eip155:11155111:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7"
}2
3
4
Guidelines:
- Use descriptive
namefield - Include
descriptionfor custom endpoints - Follow CAIP standards when applicable
Optional Fields
supportedTrust (MAY)
Type: array of strings
Purpose: Declares trust models the agent supports for validation and reputation.
Structure:
{
"supportedTrust": ["reputation", "crypto-economic", "tee-attestation"]
}2
3
Standard Values:
"reputation"- On-chain feedback and reputation system"crypto-economic"- Stake-secured validation with slashing"tee-attestation"- Trusted Execution Environment proofs"social-graph"- Social graph-based trust (emerging)
Validation:
- ⚠️ Unknown value:
unknown_trust_modelwarning - ⚠️ Empty array:
empty_supported_trustwarning
Usage in Production:
reputation: 80% of agentscrypto-economic: 50% of agentstee-attestation: 20% of agents
active (MAY)
Type: boolean
Purpose: Production readiness flag.
Structure:
{
"active": true
}2
3
Values:
true- Agent is production-ready and actively accepting requestsfalse- Agent is in development, testing, or inactive
Default: false or undefined (inactive)
Validation:
- ⚠️
active: false:agent_not_activewarning (not production-ready) - ⚠️ Non-boolean:
invalid_boolean_activewarning
x402support (MAY)
Type: boolean
Purpose: Indicates support for x402 payment protocol (HTTP 402 Payment Required).
Structure:
{
"x402support": true
}2
3
Values:
true- Agent accepts x402 payment requestsfalse- Agent does not support x402
Requirements:
If x402support: true, agent SHOULD have an agentWallet endpoint defined.
Validation:
- ⚠️ Non-boolean:
invalid_boolean_x402warning
updatedAt (MAY)
Type: number (Unix timestamp)
Purpose: Last update timestamp for metadata freshness tracking.
Structure:
{
"updatedAt": 1763112328
}2
3
Format: Unix timestamp (seconds since epoch)
Usage:
- Helps explorers show "last updated" time
- Can be used for ranking/sorting by freshness
Example:
// Generate current timestamp
const updatedAt = Math.floor(Date.now() / 1000);2
URI Format Standards
Recommended Priority (by Immutability)
For production agents, choose URI format based on immutability guarantees:
| Priority | Format | Immutability | Gas Cost | Recommendation |
|---|---|---|---|---|
| 🥇 Best | Data URI | ✅✅✅ Guaranteed (on-chain) | 💰💰💰 High | Most Recommended - Perfect immutability |
| 🥈 Good | IPFS/Arweave | ✅✅ Strong (content-addressed) | 💰 Low | Good balance of immutability & cost |
| 🥉 Acceptable | HTTP/HTTPS | ❌ None (mutable, centralized) | 💰 Low | Least Recommended - Can change/disappear |
Immutability Trade-offs:
Data URI (Best Immutability) ✅
Pros:
Metadata stored directly on-chain
Cannot be changed or removed
No external dependencies
Instant retrieval (no network fetch)
Cons:
- High gas cost (~70,000-340,000 gas for 3KB-20KB metadata)
- Limited size (practical limit ~50KB due to block gas limit)
When to Use: Production agents requiring absolute immutability, regulatory compliance
IPFS/Arweave (Good Immutability) ⚖️
- Pros:
- Content-addressed (CID verifies integrity)
- Low gas cost (~40,000-70,000 gas for URI storage only)
- Decentralized storage
- Cons:
- Requires gateway availability
- Pinning needed to ensure availability
- Potential network delays
- When to Use: Most production agents, balance of cost and immutability
- Pros:
HTTP/HTTPS (No Immutability) ⚠️
Pros:
- Low gas cost (~40,000-70,000 gas for URI storage only)
- Easy updates (dynamic metadata)
- Fast retrieval from CDN
Cons:
Can be changed at any time (mutable)
Can disappear (centralized, single point of failure)
Trust required in server operator
When to Use: Development/testing only, or agents that need frequent metadata updates
Recommendation Summary:
🏆 Production agents: Use Data URI for critical metadata, IPFS for larger files
🧪 Development/Testing: HTTP/HTTPS acceptable for rapid iteration
🔄 Hybrid Approach: Store core metadata in Data URI, reference additional files via IPFS
Supported URI Schemes
8004scan supports 7 URI formats for AgentURI metadata, ensuring maximum compatibility with different storage systems.
1. Data URI (🥇 Most Recommended for Immutability)
Base64 Format:
data:application/json;base64,<BASE64_ENCODED_JSON>Plain Format:
data:application/json,<JSON_STRING>Example (Base64):
data:application/json;base64,ewogICJ0eXBlIjogImh0dHBzOi8vZWlwcy5ldGhlcmV1bS5vcmcvRUlQUy9laXAtODAwNCNyZWdpc3RyYXRpb24tdjEiLAogICJuYW1lIjogIkFnZW50IE5hbWUiCn0=Example (Plain):
data:application/json,{"type":"https://eips.ethereum.org/EIPS/eip-8004#registration-v1","name":"Agent"}Benefits:
✅✅✅ Perfect immutability (stored on-chain)
✅ No external dependencies
✅ Instant retrieval (no network fetch)
✅ Cryptographically verified by blockchain
Drawbacks:
- ⚠️ High gas cost (~70,000-340,000 gas for 3KB-20KB metadata)
- ⚠️ Size limit (practical limit ~50KB due to block gas limit)
Parser Behavior:
- Extract base64 payload after
data:application/json;base64, - Base64 decode → UTF-8 decode → JSON parse
- For plain format: URL decode if needed → JSON parse
Edge Case: Some URIs claim base64 but contain plain JSON. Parser detects { or [ at start and skips base64 decode.
Usage: 18% of production agents
Recommendation: 🏆 Use for production agents requiring absolute immutability
2. IPFS URIs (🥈 Good Balance - Recommended)
Format:
ipfs://CID
ipfs://CID/path/to/file.json2
3
Examples:
ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4
ipfs://QmXXX/metadata.json2
Benefits:
- ✅✅ Strong immutability (content-addressed)
- ✅ Decentralized storage
- ✅ Low gas cost (~40,000-70,000 gas for URI storage)
- ✅ Global availability via gateways
- ✅ CID verifies content integrity
Drawbacks:
- ⚠️ Requires gateway availability
- ⚠️ Pinning needed to ensure long-term availability
- ⚠️ Potential network delays (gateway fetch time)
Gateway Resolution:
8004scan uses fallback gateways for reliability:
https://ipfs.io/ipfs/{CID}https://cloudflare-ipfs.com/ipfs/{CID}https://gateway.pinata.cloud/ipfs/{CID}
Usage: 51% of production agents
Recommendation: ⚖️ Best balance of immutability and cost for most production agents
3. Arweave URIs (🥈 Good Balance - Permanent Storage)
Format:
ar://TX_ID
ar://TX_ID/path2
3
Examples:
ar://a1b2c3d4e5f6Benefits:
- ✅ Permanent storage (pay once, store forever)
- ✅ Content-addressed
- ✅ Decentralized
Gateway Resolution:
https://arweave.net/{TX_ID}
Usage: <5% of production agents
4. HTTP/HTTPS URLs (🥉 Least Recommended - Use Only for Development)
Format:
https://example.com/metadata.json
http://example.com/api/agent/1232
3
Examples:
https://cdn.example.com/agents/dataanalyst-pro.json
https://api.example.com/v1/agents/241/metadata2
Benefits:
- ✅ Low gas cost (~40,000-70,000 gas for URI storage)
- ✅ Fast updates (dynamic metadata)
- ✅ Direct control over content
- ✅ Fast CDN retrieval
Drawbacks:
- ❌❌❌ NO IMMUTABILITY (metadata can be changed at any time)
- ❌ Can disappear (server downtime, domain expiration, operator decision)
- ⚠️ Centralized (single point of failure)
- ⚠️ Trust required in server operator
- ⚠️ May require authentication
Security Note: HTTPS is strongly preferred over HTTP.
Usage: 22% of production agents
Recommendation: ⚠️ Use only for development/testing, or agents requiring frequent metadata updates. NOT recommended for production agents requiring trust.
5. Data URI (Non-Standard) - Edge Case
Observed formats:
data:text/plain;base64,<BASE64>
data:;base64,<BASE64>
data:application/json;charset=utf-8;base64,<BASE64>2
3
4
Parser Behavior:
- Generic fallback parser
- Try base64 decode first
- If fails, try plain JSON
- Log warning about non-standard format
Usage: Rare (<1% of production agents)
6. Plain JSON (No URI Scheme) - Edge Case
Format: Raw JSON stored as metadata URI (no URI scheme)
Example:
{ "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent" }Parser Behavior:
- Fallback parser
- Direct JSON parse
- Log warning:
plain_json_without_uri_scheme
Usage: Rare (<1% of production agents)
Data URI Compression Extension (Optional)
Purpose
Reduce on-chain gas costs while maintaining Data URI's perfect immutability guarantees.
Standard Data URI metadata requires significant gas (70,000-340,000 gas for 3KB-20KB data), making it expensive for many use cases. This compression extension is expected to reduce gas costs by 60-70% through data compression while preserving all benefits of on-chain storage.
Key Innovation: Add enc=<algorithm> parameter to compress JSON before base64 encoding.
Status: Protocol designed, implementation complete. Real-world gas savings need to be measured with production data.
Protocol Format
data:application/json;enc=<algorithm>[;level=<level>];base64,<compressedData>Parameters:
enc: Compression algorithm (zstd|gzip|br|lz4)level: Compression level (optional, algorithm-specific defaults apply)
Examples:
data:application/json;enc=zstd;base64,KLUv/WD8zQAUfRS…
data:application/json;enc=zstd;level=9;base64,KLUv/WD8zQAUfRS…
data:application/json;enc=gzip;base64,H4sIAAAAAAAA…
data:application/json;enc=br;level=11;base64,iwmASNKB…2
3
4
Supported Compression Algorithms
| Algorithm | Compression Ratio | Decompression Speed | Recommendation |
|---|---|---|---|
| Zstd ⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Best Choice - High ratio + fast |
| Brotli | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | Slightly better compression, slower |
| Gzip | ⭐⭐⭐ | ⭐⭐⭐⭐ | Best compatibility, average ratio |
| LZ4 | ⭐⭐ | ⭐⭐⭐⭐⭐ | Fastest decompression, lower ratio |
Recommendation: Zstd level 9 (optimal balance of compression ratio and speed)
Gas Fee Savings
Real-World Test Results (tested with 4,916 production agent metadata):
| Data Size | Algorithm | Compression Ratio | Gas Saved | Speed |
|---|---|---|---|---|
| < 2KB (99% of agents) | Zstd-15 | 35% | ~4,500 gas | 0.11ms |
| < 2KB | Brotli-11 | 48% | ~6,200 gas | 2.62ms |
| 2-5KB (1% of agents) | Zstd-15 | 59% | ~31,600 gas | 0.68ms |
| 2-5KB | Brotli-11 | 67% | ~35,300 gas | 6.91ms |
Gas Calculation Formula:
Gas = data_size_bytes × 16 + 21,000Key Findings:
- Real compression ratios (35-67%) are lower than theoretical estimates (60-70%)
- Most agents use small metadata (<2KB), saving 4,000-6,000 gas per registration
- Recommended: Zstd-15 (best balance: good compression + fast speed)
Quick Implementation
Python (Zstd-15 recommended):
import zstandard as zstd
import base64
import json
# Compress
json_bytes = json.dumps(metadata, separators=(',', ':')).encode('utf-8')
compressed = zstd.ZstdCompressor(level=15).compress(json_bytes)
encoded = base64.b64encode(compressed).decode('ascii')
uri = f"data:application/json;enc=zstd;level=15;base64,{encoded}"
# Decompress
header, data = uri.split(',', 1)
compressed = base64.b64decode(data)
json_bytes = zstd.ZstdDecompressor().decompress(compressed)
metadata = json.loads(json_bytes)2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TypeScript:
import { compress, decompress } from "fflate";
// Compress
const json = JSON.stringify(metadata);
const compressed = compress(new TextEncoder().encode(json), { level: 9 });
const encoded = btoa(String.fromCharCode(...compressed));
const uri = `data:application/json;enc=gzip;base64,${encoded}`;
// Decompress
const [_, data] = uri.split(",");
const compressed = Uint8Array.from(atob(data), (c) => c.charCodeAt(0));
const json = new TextDecoder().decode(decompress(compressed));
const metadata = JSON.parse(json);2
3
4
5
6
7
8
9
10
11
12
13
Security: Implementation should include zip bomb protection (100KB decompression limit).
Security
8004scan implements the following protections:
Zip Bomb Protection: 100KB decompression size limit
Algorithm Whitelist: Only
zstd,gzip,br,lz4allowedAsync Processing: Decompression handled in Celery workers (non-blocking)
JSON Validation: Strict validation after decompression
Backward Compatibility
- ✅ Compressed:
data:application/json;enc=zstd;base64,... - ✅ Uncompressed:
data:application/json;base64,... - No breaking changes for existing agents
For detailed technical spec and advanced examples, see Data URI Compression Extension.
Onchain Metadata
In addition to AgentURI metadata (offchain), ERC-8004 supports onchain metadata stored as key-value pairs via setMetadata(uint256 agentId, string key, bytes value).
Common Keys
| Key | Type | Description | Example |
|---|---|---|---|
agentWallet | address | Payment wallet address | 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7 |
agentName | string | ENS name or human-readable identifier | "dataanalyst.eth" |
version | string | Agent version | "1.0.0" |
category | string | Classification tag | "developer-tools" |
pricing | string | Pricing tier | "free" |
Relationship to AgentURI
Key Difference:
- AgentURI metadata (offchain): Comprehensive JSON with full agent details
- Onchain metadata (on-chain): Key-value pairs for specific indexed fields
Best Practice: Synchronize both when possible. For example:
- AgentURI:
"endpoints": [{"name": "agentWallet", "endpoint": "eip155:1:0x..."}] - Onchain:
setMetadata(agentId, "agentWallet", 0x...)
Precedence: If both exist, AgentURI metadata is considered the source of truth for display purposes.
Validation Levels
8004scan uses a 5-level validation system to ensure metadata quality while remaining flexible for custom formats.
Level 1: Syntax Validation
Errors (Parse Fails):
- Empty or non-string URI
- Invalid JSON syntax
- Invalid base64 encoding (for base64 URIs)
- Non-dict root type (must be JSON object)
Warnings (Parse Succeeds, Data Issues):
- Missing MIME type in data URI
- URL-encoded plain JSON
- Plain JSON without URI scheme
- base64 URI with plain JSON content
Level 2: Schema Validation
Critical Warnings (Likely to cause display issues):
| Issue | Warning Code | Severity |
|---|---|---|
Missing type field | missing_required_type | High |
Invalid type value | invalid_type_field | High |
Missing name | missing_required_name | High |
Missing description | missing_required_description | High |
Missing image | missing_recommended_image | Medium |
Missing endpoints | missing_endpoints | Medium |
Empty endpoints array | empty_endpoints | Medium |
Standard Warnings:
| Issue | Warning Code |
|---|---|
endpoint instead of endpoints | typo_endpoint_singular |
registration instead of registrations | typo_registration_singular |
Missing registrations | missing_registrations |
Empty registrations | empty_registrations |
registrations[].agentId is null | registration_null_agent_id |
registrations[].agentId mismatch | registration_agent_id_mismatch |
| Invalid CAIP-2 format | invalid_caip2_format |
| Invalid CAIP-10 format | invalid_caip10_format |
Level 3: Endpoint Validation
MCP Endpoint:
- Missing
endpoint:mcp_missing_endpoint - Missing
version:mcp_missing_version - Non-standard version:
mcp_nonstandard_version
A2A Endpoint:
- Missing
endpoint:a2a_missing_endpoint - Missing
version:a2a_missing_version - Non-standard version:
a2a_nonstandard_version - Missing
.well-knownpath:a2a_missing_well_known
OASF Endpoint:
- Missing both
skillsanddomains:oasf_empty - Invalid skill slug:
oasf_invalid_skill - Invalid domain slug:
oasf_invalid_domain - Non-standard version:
oasf_nonstandard_version
agentWallet Endpoint:
- Invalid CAIP-10 format:
wallet_invalid_format - Invalid address checksum:
wallet_invalid_checksum
Level 4: Semantic Validation
Trust Models:
- Unknown trust model:
unknown_trust_model - Empty
supportedTrust:empty_supported_trust
Known values: "reputation", "crypto-economic", "tee-attestation", "social-graph"
Level 5: Status Fields
Status Checks:
active: false:agent_not_active(not production-ready)- Invalid boolean
active:invalid_boolean_active - Invalid boolean
x402support:invalid_boolean_x402
Real-World Patterns
Pattern 1: Agent0 SDK Standard Format
Prevalence: High (most compliant agents)
Source: Official SDK implementation
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "Agent Name",
"description": "Description...",
"image": "ipfs://CID",
"active": true,
"endpoints": [
{
"name": "A2A",
"version": "0.30",
"endpoint": "https://.../.well-known/agent-card.json"
},
{
"name": "agentWallet",
"endpoint": "eip155:11155111:0x..."
}
],
"updatedAt": 1763112328,
"registrations": [
{
"agentId": 696,
"agentRegistry": "eip155:84532:0x..."
}
],
"supportedTrust": [],
"x402support": true
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Storage: IPFS (data URI base64 or ipfs:// URI)
Characteristics: Minimal, standards-compliant, SDK-generated
Pattern 2: Alias AI Star Card Format
Prevalence: Medium (specific community)
Source: Alias AI ecosystem
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "Agent #12345678",
"description": "Alias AI Star Card Agent #12345678 - Digital identity and economy",
"image": "/uploads/avatars/{uid}/avatar_*.jpg",
"endpoints": [
{
"name": "StarCard API",
"version": "1.0.0",
"endpoint": "",
"description": "Retrieve the user's complete star card information"
},
{
"name": "OASF",
"version": "v0.8.0",
"endpoint": "",
"skills": [
"analytical_skills/data_analysis/blockchain_analysis",
"analytical_skills/pattern_recognition/market_trends"
],
"domains": [
"technology/blockchain",
"finance/cryptocurrency"
]
}
],
"attributes": {
"uid": "uuid-v4",
"wallet": "0x...",
"twitter": "@handle",
"mbtiType": "ENFJ",
"zodiacSign": "Libra"
},
"registrations": [...],
"supportedTrust": ["reputation", "crypto-economic", "social-graph"]
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Storage: HTTP(S) API endpoint
Peculiarities:
Empty
endpointfields (template format)Relative image paths
Custom
attributesobjectAdditional trust model:
"social-graph"
Parser Strategy: Accept attributes, ignore empty endpoint fields in validation.
Pattern 3: ChaosChain Studio Format
Prevalence: Low-medium
Source: ChaosChain ecosystem
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "Bob",
"description": "ChaosChain agent deployed at bob.chaoschain-studio.com",
"image": "https://chaoscha.in/agent-avatar.png",
"endpoints": [
{
"name": "agentWallet",
"endpoint": "eip155:11155111:0x..."
}
],
"registrations": [
{
"agentId": 0,
"agentRegistry": "eip155:11155111:0x..."
}
],
"supportedTrust": ["reputation", "crypto-economic"]
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Storage: Data URI (base64) BUT contains plain JSON instead of base64-encoded JSON
Peculiarity: URI says data:application/json;base64,{...} but payload is NOT base64-encoded
Parser Strategy: Detect { or [ at start of "base64" payload, skip base64 decode, parse directly.
Pattern 4: Minimal/Test Agents
Prevalence: Medium (development/testing)
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "Test Agent",
"description": "Minimal test agent",
"image": "https://example.com/test.png",
"endpoints": [],
"registrations": []
}2
3
4
5
6
7
8
9
Issues:
- Empty
endpoints(agent not reachable) - Empty
registrations(no on-chain link)
Parser Strategy: Parse successfully, log warnings.
Migration Guides
Migrating from Custom Format to ERC-8004
If you have existing agent metadata in a custom format, follow this guide to migrate to ERC-8004 standard.
Step 1: Map Existing Fields
Custom Format Example:
{
"agent_name": "MyAgent",
"agent_description": "Does things",
"avatar_url": "https://...",
"api_endpoint": "https://..."
}2
3
4
5
6
Mapping:
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "MyAgent", // ← agent_name
"description": "Does things", // ← agent_description
"image": "https://...", // ← avatar_url
"endpoints": [
{
"name": "MCP",
"endpoint": "https://...", // ← api_endpoint
"version": "2025-06-18"
}
]
}2
3
4
5
6
7
8
9
10
11
12
13
Step 2: Add Required Fields
Ensure all MUST fields are present:
- ✅
type - ✅
name - ✅
description - ✅
image
Step 3: Add Recommended Fields
Endpoints:
{
"endpoints": [
{
"name": "MCP",
"endpoint": "https://api.example.com/mcp",
"version": "2025-06-18"
},
{
"name": "agentWallet",
"endpoint": "eip155:1:0x..."
}
]
}2
3
4
5
6
7
8
9
10
11
12
13
Registrations:
{
"registrations": [
{
"agentId": 123,
"agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847"
}
]
}2
3
4
5
6
7
8
Step 4: Validate
Use 8004scan parser or validation tools:
NOTE
8004scan API is coming soon. The endpoint below is a preview of the planned interface.
curl -X POST https://8004scan.io/api/v1/validate/metadata \
-H "Content-Type: application/json" \
-d @metadata.json2
3
Upgrading Metadata Version
When updating agent metadata, increment updatedAt timestamp:
Before:
{
"name": "MyAgent v1",
"updatedAt": 1763112328
}2
3
4
After:
{
"name": "MyAgent v2",
"updatedAt": 1763200000 // ← New timestamp
}2
3
4
On-Chain Update:
// Update agentURI on ERC-8004 registry
agentRegistry.setAgentURI(agentId, newAgentURI);2
References
Official Specifications
Protocol Documentation
8004scan Resources
Changelog
| Version | Date | Changes |
|---|---|---|
| 0.1 | 2025-12-20 | Initial draft based on 4,725 agent analysis |
Contact
- Documentation Maintainer: 8004scan Development Team
- Review Frequency: Monthly
- Next Review: 2026-01-20
For questions about this standard:
- EIP-8004 Spec → Refer to official specification
- Implementation → Check Agent Metadata Parsing Guide
- Real-world usage → See sources and examples
Version: 0.1
Last Updated: 2025-12-20
Status: Draft