⚠️ Field Name Migration Notice (Jan 2026)
The official EIP-8004 specification has changed the field name from
endpointstoservices.
For backward compatibility, parsers SHOULD support both field names:
services- New official field name (EIP-8004 Jan 2026+)endpoints- Legacy field name (still widely used)Migration Path: New implementations SHOULD use
services. Existing agents usingendpoints
will continue to work. Parsers will emit aWA031warning recommending migration.See Field Name Migration for details.
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 legacy testnet deployments
- ✅ 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.
Intended Audience
- Agent developers registering new agents
- Registry implementers building indexers and explorers
- Tool builders creating SDKs
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 Examples
- Updating Agent Metadata
- Field Name Migration:
endpoints→services🆕
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
{
// ============ SHOULD FIELDS (per official spec) ============
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "myAgentName",
"description": "A natural language description of the Agent",
"image": "https://example.com/agentimage.png",
// Services - fully customizable (per official spec)
// NOTE: EIP-8004 uses "services" (Jan 2026+). Legacy "endpoints" is also supported.
"services": [
{
"name": "web",
"endpoint": "https://web.agentxyz.com/"
},
{
"name": "A2A",
"endpoint": "https://agent.example/.well-known/agent-card.json",
"version": "0.3.0"
},
{
"name": "MCP",
"endpoint": "https://mcp.agent.eth/",
"capabilities": [], // OPTIONAL, as per MCP spec
"version": "2025-06-18"
},
{
"name": "OASF",
"endpoint": "ipfs://{cid}",
"version": "0.8",
"skills": [], // OPTIONAL
"domains": [] // OPTIONAL
},
{
"name": "ENS",
"endpoint": "vitalik.eth",
"version": "v1"
},
{
"name": "email",
"endpoint": "mail@myagent.com"
}
],
// ============ OPTIONAL FIELDS (MAY) ============
"x402Support": false,
"active": true,
"registrations": [
{
"agentId": 22,
"agentRegistry": "eip155:1:0x742..." // {namespace}:{chainId}:{identityRegistry}
}
],
"supportedTrust": ["reputation", "crypto-economic", "tee-attestation"]
}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
52
53
54
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 (Recommended)
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_recommended_descriptionwarning
image (Recommended)
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 (suggestion, not enforced)
- 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
services / endpoints (SHOULD)
Type: array of service/endpoint objects
Purpose: Communication endpoints for interacting with the agent.
Importance: MUST include at least one service if agent is meant to be interacted with.
Field Name Migration (Jan 2026)
The official EIP-8004 specification changed this field from
endpointstoservices.
Parsers SHOULD support both for backward compatibility:
Field Status Usage services✅ Recommended New official name (EIP-8004 Jan 2026+) endpoints⚠️ Legacy Still widely used, supported for compatibility If both fields exist,
servicestakes precedence.
General Structure:
{
"name": "EndpointType",
"endpoint": "url_or_identifier",
"version": "protocol_version"
// ... type-specific fields
}2
3
4
5
6
7
Validation:
- ⚠️ Using
endpoints:WA031warning (recommend migrating toservices) - ❌ Missing:
missing_endpointswarning - ⚠️ Empty array:
empty_endpointswarning (agent not reachable) - ⚠️ Common typo:
endpoint(singular) instead ofendpoints/services(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_registrationsinfo (no on-chain link, discovery-only)ℹ️ Empty array:
empty_registrationsinfo (no on-chain link)ℹ️ Null agentId:
registration_null_agent_idinfo (expected for first-time deployments)⚠️ ID mismatch:
registration_agent_id_mismatchwarning⚠️ Invalid CAIP-10:
invalid_caip10_formatwarning
Note: Missing or null
agentIdis expected during first-time deployments, as the tokenId is only assigned after the on-chain registration transaction confirms. Update the metadata after registration.
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
Version Format: Date-based (YYYY-MM-DD). Examples: 2025-06-18, 2025-11-25, 2026-01-29
Structure:
{
"name": "MCP",
"endpoint": "https://api.example.com/mcp",
"version": "2025-11-25",
"mcpTools": ["analyze_wallet", "detect_anomalies"],
"capabilities": []
}2
3
4
5
6
7
NOTE
v1.1 Change: The capabilities field format changed from object {} to array [] in January 2026.
Fields:
endpoint(string, REQUIRED): MCP server URLversion(string, REQUIRED): MCP protocol version inYYYY-MM-DDdate formatmcpTools(array, OPTIONAL): List of available MCP toolsmcpPrompts(array, OPTIONAL): List of available promptsmcpResources(array, OPTIONAL): List of available resourcescapabilities(array, OPTIONAL): MCP server capabilities
See MCP Protocol Documentation for complete specification.
2. A2A (Agent-to-Agent Protocol)
Purpose: Enables agent-to-agent communication and collaboration.
Specification: A2A Protocol (current version: 0.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"]
}2
3
4
5
6
Fields:
endpoint(string, REQUIRED): URL to agent card (SHOULD use/.well-known/agent-card.jsonpath)version(string, REQUIRED): A2A protocol version (standard:"0.3.0")a2aSkills(array, OPTIONAL): OASF skill slugs for capability discovery
Agent Card: The endpoint URL should resolve to an A2A Agent Card JSON. See A2A Protocol Documentation for the complete Agent Card specification.
3. OASF (Open Agentic Schema Framework)
Purpose: Declares agent capabilities using standardized taxonomies for skills and domains.
Specification: OASF Releases
Schema Browser: https://schema.oasf.outshift.com/
Version Format: Semver with optional 'v' prefix. Examples: 0.8.0, v0.8.0, 0.8.3, 0.7.4
NOTE
OASF maintains multiple version lines (0.7.x, 0.8.x). Both are valid. Use the version that matches your OASF record's taxonomy.
Structure:
{
"name": "OASF",
"endpoint": "https://github.com/agntcy/oasf/",
"version": "0.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 in semver format (e.g.,"0.8.0"or"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
Common Skills (examples from legacy testnet data):
natural_language_processing/natural_language_generation/summarizationtool_interaction/api_schema_understandingmulti_modal/image_processing/text_to_imagenatural_language_processing/information_retrieval_synthesis/searchtool_interaction/workflow_automation
Domain Taxonomy:
OASF domains categorize agent application areas:
industry / sector / specialization
↓ ↓ ↓
finance_and_business / investment_services2
3
Common Domains (examples from legacy testnet data):
technology/blockchainfinance_and_business/financetechnology/software_engineering/apis_integrationtechnology/blockchain/cryptocurrencymedia_and_entertainment/content_creation
Resources:
4. agentWallet
IMPORTANT
agentWallet is a reserved onchain metadata key. The verified wallet is set automatically to the owner during register(...) and can only be updated via setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes signature) (EIP-712 or ERC-1271). Deadline must be ≤ now + 5 minutes. Offchain declarations are for discovery only; the onchain value is authoritative for payments.
Purpose: Payment wallet address for x402 protocol and agent-to-agent transactions.
Format: CAIP-10 (Account ID Specification)
Offchain Structure (for discovery):
{
"name": "agentWallet",
"endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7"
}2
3
4
Onchain Update (v1.1.0):
// Update wallet with cryptographic verification (EIP-712 or ERC-1271)
function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes calldata signature) external2
Key behaviors:
- Callable by owner or approved operators
- Initially set to the registering owner
- Cannot be set via
setMetadata()(reserved key) - Deadline must be current time or sooner than
now + 5 minutes - New wallet must sign the typed data (or pass ERC-1271)
- On transfer, resets to zero address (must be re-verified by new owner)
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:
{
"services": [
{
"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. Human-Facing Endpoints (NEW in v1.1)
NOTE
v1.1 Addition: The January 2026 update added web and email as standard human-facing endpoint types.
Purpose: Contact and information endpoints for human users (not agent-to-agent communication).
Structure:
{
"services": [
{
"name": "web",
"endpoint": "https://myagent.example.com"
},
{
"name": "email",
"endpoint": "support@myagent.example.com"
}
]
}2
3
4
5
6
7
8
9
10
11
12
Fields:
web- Agent's public website or landing pageemail- Contact email for support or inquiries
8. 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
Adoption (from legacy testnet data):
See Sources & References for detailed adoption statistics.
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.
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}
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}
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.
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
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
Data URI Compression Extension (Optional)
8004scan Extension: This is an optional protocol extension designed to reduce on-chain gas costs while maintaining Data URI's perfect immutability guarantees.
Overview
Standard Data URI metadata can be expensive (70,000-340,000 gas for 3KB-20KB data). This compression extension reduces gas costs by 35-67% through data compression while preserving all benefits of on-chain storage.
Format:
data:application/json;enc=<algorithm>[;level=<level>];base64,<compressedData>Supported Algorithms: zstd (recommended), gzip, br (Brotli), lz4
Recommendation: Zstd level 9-15 for optimal balance of compression ratio and speed.
When to Use
| Metadata Size | Recommendation |
|---|---|
| < 1KB | Optional (marginal savings) |
| 1-3KB | Recommended (~24,000-32,000 gas saved) |
| > 3KB | Strongly recommended (~32,000+ gas saved) |
Backward Compatibility
- ✅ Compressed:
data:application/json;enc=zstd;base64,... - ✅ Uncompressed:
data:application/json;base64,... - No breaking changes for existing agents
For detailed protocol specification, security considerations, and implementation 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 (reserved) | 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7 |
agentHash | bytes32 | Metadata content hash (8004scan ext.) | 0x1234...abcd (keccak256) |
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" |
agentHash (8004scan Extension)
8004scan Extension: Optional integrity verification for HTTP/HTTPS agentURI.
For HTTP/HTTPS URIs (which are mutable), owners MAY set agentHash to enable content integrity verification:
// Compute: keccak256(canonicalJSON) where keys are sorted alphabetically
registry.setMetadata(agentId, "agentHash", abi.encodePacked(hash));2
Benefits:
- Indexers can verify fetched content matches owner's intent
- Signals intentional metadata updates when hash changes
- Provides trust signal for mutable URIs
Note: Not needed for IPFS/Arweave (already content-addressed).
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:
"services": [{"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
Implementations SHOULD validate agent metadata at multiple levels to ensure quality while remaining flexible for custom formats.
Recommended Validation Approach
| Level | Focus | Description |
|---|---|---|
| Level 1 | Syntax | URI format, JSON parsing, base64 decoding |
| Level 2 | Schema | Required/recommended fields presence |
| Level 3 | Endpoints | Protocol-specific field validation |
| Level 4 | Semantic | Trust model values, cross-field consistency |
| Level 5 | Status | Production readiness flags |
Validation Severity Levels
Following RFC 2119/8174 terminology:
| Level | RFC Keywords | Description |
|---|---|---|
| Error | MUST, MUST NOT | Critical issues preventing proper functioning |
| Warning | SHOULD, SHOULD NOT | Functional issues but not critical |
| Info | MAY, RECOMMENDED | Best practices, recommendations, or expected states |
Examples by Severity:
- Error: Invalid JSON syntax, unsupported URI format
- Warning: Missing required fields (type, name), invalid CAIP format
- Info: Missing
agentId(first-time deployment), A2A endpoint not using.well-knownpath
Implementation Note: Validators SHOULD collect warnings and info messages without failing on non-critical issues. This allows maximum interoperability while providing feedback to agent developers.
For a detailed implementation guide with specific warning codes and validation logic, see Agent Metadata Parsing Guide.
Real-World Examples
For examples of agent metadata formats observed in production deployments, see Real-World Examples.
Updating Agent Metadata
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 (v1.1.0):
NOTE
setAgentURI() is exposed on the registry; callable by owner or approved operator; emits URIUpdated.
// Update agentURI on ERC-8004 registry (owner or approved)
agentRegistry.setAgentURI(agentId, newAgentURI);2
Function Signature:
function setAgentURI(uint256 agentId, string calldata newAgentURI) external;Requirements:
- Caller MUST be the agent owner or an approved operator
agentIdMUST exist- Emits
URIUpdated(agentId, newAgentURI, updatedBy)
FAQ
Q: How do I deploy and index the same agent across multiple chains?
A: Use CAIP-2 chain IDs and the two-phase registration flow to link agents across chains:
Challenge: Since agentId is assigned at registration time (auto-incrementing NFT token ID), you cannot know all IDs upfront when deploying to multiple chains.
Solution: Use register() without URI first, then update with setAgentURI() after collecting all IDs.
Phase 1 - Register on all chains (without URI):
solidity// On Base Sepolia (chain 84532) uint256 baseAgentId = baseRegistry.register(); // Returns 42 // On Ethereum Sepolia (chain 11155111) uint256 ethAgentId = ethRegistry.register(); // Returns 991
2
3
4
5Phase 2 - Create unified registration file with all collected IDs:
json{ "name": "My Agent", "registrations": [ { "agentId": 42, "agentRegistry": "eip155:84532:0x8004..." }, { "agentId": 99, "agentRegistry": "eip155:11155111:0xAbcd..." } ] }1
2
3
4
5
6
7
8
9
10
11
12
13Phase 3 - Update URI on all chains to point to the same file:
solidity// Upload registration file to IPFS → ipfs://Qm... // Update on Base Sepolia baseRegistry.setAgentURI(42, "ipfs://Qm..."); // Update on Ethereum Sepolia ethRegistry.setAgentURI(99, "ipfs://Qm...");1
2
3
4
5
6
7Indexing: Treat
(agentRegistry, agentId)as unique identifier- Tag feedback/validation records with source chain
- Aggregate scores across all chains for global reputation
- Indexers discover all deployments by parsing the
registrationsarray
References
Official Specifications
Protocol Documentation
8004scan Resources
Field Name Migration: endpoints to services
Background
In January 2026, the official EIP-8004 specification updated the field name from endpoints to services in the Agent Registration File schema. This change aligns with broader industry terminology.
Official EIP-8004 Spec (Jan 2026):
{
"services": [
{ "name": "MCP", "endpoint": "https://..." },
{ "name": "A2A", "endpoint": "https://..." }
]
}2
3
4
5
6
Legacy Format (still supported):
{
"endpoints": [
{ "name": "MCP", "endpoint": "https://..." },
{ "name": "A2A", "endpoint": "https://..." }
]
}2
3
4
5
6
Compatibility Strategy
To ensure backward compatibility, parsers (including 8004scan backend) implement the following:
- Accept both fields:
servicesandendpointsare both valid - Prefer
services: If both exist,servicestakes precedence - Emit migration warning: When
endpointsis used, emitWA031warning message
Migration Steps
For Agent Developers:
- Update your agent metadata to use
servicesinstead ofendpoints - The field structure remains identical—only the array name changes
- No changes needed to individual service objects
Example Migration:
{
"name": "My Agent",
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
- "endpoints": [
+ "services": [
{
"name": "MCP",
"endpoint": "https://mcp.myagent.com",
"version": "2025-06-18"
}
]
}2
3
4
5
6
7
8
9
10
11
12
For Parser Implementers:
# Support both field names with preference for 'services'
services = metadata.get("services") OR metadata.get("endpoints")
IF "endpoints" exists in metadata AND "services" does not exist THEN
# Emit WA031 warning message recommending migration
warnings.append({"code": "WA031", "message": "Using legacy 'endpoints' field..."})
END IF2
3
4
5
6
7
Timeline
| Phase | Date | Status |
|---|---|---|
| Spec Updated | Jan 2026 | ✅ Complete |
| Parser Support | Jan 2026 | ✅ Complete (8004scan v0.2.28+) |
| Migration Period | Jan 2026 - Dec 2026 | 🔄 In Progress |
| Legacy Deprecation | TBD | 📅 Planned |
Note: There is no immediate deprecation timeline for
endpoints. Both field names will be supported for the foreseeable future. TheWA031warning recommends migration but does not prevent usage.
Changelog
| Version | Date | Changes |
|---|---|---|
| 1.3 | 2026-01-27 | Document endpoints → services field name migration per EIP-8004 Jan 2026 update; add WA031 warning code |
| 1.2 | 2026-01-11 | Added 3-level validation severity (error/warning/info); adjusted agentId and A2A path to info level |
| 1.1 | 2026-01-09 | v1.1: agentWallet onchain, MCP array, web/email, setURI |
| 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-02-09
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: 1.3
Last Updated: 2026-01-27
Status: Community Guidelines