--- url: /docs/implementation/validation-best-practices.md description: >- Practical guide for validators responding to validation requests - SPEC SUBJECT TO CHANGE --- > **🚨 CRITICAL NOTICE** > > **This guide is based on an UNSTABLE specification that is PENDING FINALIZATION.** > > The ERC-8004 Validation Registry specification is **still under active development** and **may change significantly** based on ongoing discussions with the TEE/ZK community. The best practices in this document represent current recommendations but **should not be considered final** for production deployment. > > **Key uncertainties**: > > * TEE attestation format and requirements (to be revised) > * Validation data schema (subject to change) > * Response structure and fields (may be updated) > > **Status tracking**: See [official ERC-8004 repository](https://github.com/erc-8004/erc-8004-contracts/) for latest specification updates. > > **For production use**: **Wait for final v1.1 release** before implementing Validation Registry integrations. These best practices will be updated to match the final specification. ## Description Practical guide for validators responding to validation requests **Audience**: Validators, auditors, testing services **Current state**: v1.1-preview based on SpecsJan26Update (Jan 2026). See [Validation Data Profile](../03-validation-standard.md) for the corresponding data specification. ## Overview This guide provides best practices for validators responding to ERC-8004 validation requests, ensuring high-quality validation responses that build trust in the ecosystem. **What You'll Learn**: * βœ… Structure validation responses effectively * βœ… Choose appropriate validation types * βœ… Provide comprehensive evidence * βœ… Use zkSNARK proofs (Groth16, PLONK, STARK) * βœ… Leverage attachment pattern for complex evidence * βœ… Migrate from custom formats to ERC-8004 standard ## Validation Response Principles ### 1. Be Thorough and Evidence-Based **Every validation MUST include**: * Clear result (approved/rejected/conditional) * Detailed reasoning * Supporting evidence * Reproducible test methodology ❌ **Bad**: ```json { "result": "approved" } ``` βœ… **Good**: ```json { "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "security-audit", "result": "approved", "reasoning": "Agent passed security audit with 0 critical findings. Tested 15 attack vectors including reentrancy, integer overflow, and access control. All tests passed.", "attachments": [ { "name": "Security Audit Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "description": "Comprehensive security audit using Slither v0.9.6 + manual review" } ] } ``` ### 2. Match Validation Type to Request Ensure your response addresses the specific validation type requested: | Validation Type | What to Validate | Evidence to Provide | | ------------------ | ------------------------------- | --------------------------------------- | | `security-audit` | Code security, vulnerabilities | Audit report, test results | | `performance-test` | Speed, scalability, uptime | Benchmark data, load test results | | `accuracy-test` | Output correctness, reliability | Test cases, comparison data | | `zkml-proof` | Zero-knowledge ML verification | zkSNARK proof, public signals | | `tee-attestation` | Trusted execution environment | Attestation certificate, enclave report | | `crypto-economic` | Economic stake verification | Stake proof, slashing conditions | ### 3. Use Structured Result Values **Standard Results**: * `approved` - Agent meets validation criteria * `rejected` - Agent fails validation criteria * `conditional` - Agent meets criteria with conditions/warnings **With Confidence Scores**: ```json { "result": "approved", "confidence": 0.95, "reasoning": "95% confidence based on 1000 test cases. 5% margin due to limited edge case coverage." } ``` ## Validation Type Guides ### Security Audit **Checklist**: * \[ ] Smart contract vulnerabilities (if applicable) * \[ ] API endpoint security * \[ ] Access control validation * \[ ] Data privacy compliance * \[ ] Common attack vectors tested **Response Example**: ```json { "validationType": "security-audit", "result": "approved", "reasoning": "Comprehensive security audit completed. Scanned 5 smart contracts and 12 API endpoints. 0 critical findings, 2 low-severity recommendations provided.", "attachments": [ { "name": "Slither Automated Scan", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Automated scan results using Slither v0.9.6. 47 detectors run, 0 critical issues found." }, { "name": "Manual Review Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "description": "Manual code review by certified auditor. Focused on business logic and edge cases. 2 recommendations for optimization." }, { "name": "Penetration Test Results", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "description": "Tested 15 attack vectors including reentrancy, access control bypass, SQL injection. All tests passed." } ], "testMetadata": { "tool": "Slither v0.9.6", "manualReviewHours": 8, "auditor": "Certified Smart Contract Auditor (CSCA)", "date": "2025-12-20" } } ``` ### Performance Test **Metrics to Measure**: * Response time (average, p50, p95, p99) * Throughput (requests per second) * Uptime (percentage over test period) * Resource usage (CPU, memory, network) **Response Example**: ```json { "validationType": "performance-test", "result": "approved", "reasoning": "Agent demonstrated excellent performance under load. Average response time 1.2s, 99.9% uptime over 7-day test period.", "attachments": [ { "name": "Load Test Results", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Results from 10,000 API calls over 7 days. Peak load: 100 concurrent requests." }, { "name": "Performance Graphs", "uri": "ipfs://bafkrei...", "mimeType": "image/png", "description": "Response time distribution and load curve graphs" } ], "metrics": { "avgResponseTime": 1.2, "p50ResponseTime": 0.9, "p95ResponseTime": 2.1, "p99ResponseTime": 3.5, "uptime": 99.9, "throughput": 50, "testDuration": "7 days", "totalRequests": 10000 } } ``` ### Accuracy Test **Test Methodology**: * Ground truth dataset * Comparison with baseline/control * Error rate calculation * Edge case coverage **Response Example**: ```json { "validationType": "accuracy-test", "result": "approved", "reasoning": "Agent achieved 94% accuracy on 1000-sample test dataset. Matches industry benchmark for blockchain analytics agents.", "attachments": [ { "name": "Test Dataset", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "1000 blockchain transactions with ground truth labels" }, { "name": "Accuracy Report", "uri": "ipfs://bafkrei...", "mimeType": "text/csv", "description": "Per-sample results with predicted vs actual labels" }, { "name": "Confusion Matrix", "uri": "ipfs://bafkrei...", "mimeType": "image/png", "description": "Visualization of classification performance" } ], "metrics": { "accuracy": 0.94, "precision": 0.93, "recall": 0.95, "f1Score": 0.94, "testSamples": 1000, "falsePositives": 30, "falseNegatives": 30 } } ``` ### zkML Proof (zkSNARK) **Purpose**: Zero-knowledge proof of ML model inference without revealing model weights or input data. **Supported Proof Systems**: * **Groth16** (most common, 8000+ validations on Base Sepolia) * **PLONK** (universal setup, more flexible) * **STARK** (no trusted setup, transparent) #### Groth16 Proof Example **Current Format** (used by ZyFi and others): ```json { "validationType": "zkml-proof", "result": "approved", "proof": { "pi_a": ["8070450532247928943", "1234567890123456789", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c", "validationRegistryAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "chainId": 84532, "circuit": "zyfi-rebalancing-validation", "version": "1.0", "timestamp": 1766206835991 } ``` **ERC-8004 Standard Format** (recommended for new implementations): ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "result": "approved", "reasoning": "Zero-knowledge proof verified. Agent rebalancing algorithm meets specification.", "proofData": { "proof": { "pi_a": ["...", "...", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "circuit": "zyfi-rebalancing-validation", "verifierAddress": "0x4baf957..." } } ``` **Migration Path**: See [Validation Standard - Migration Guide](../03-validation-standard.md#migration-guides) #### PLONK Proof Example ```json { "validationType": "zkml-proof", "result": "approved", "proofData": { "proof": { "A": ["...", "..."], "B": ["...", "..."], "C": ["...", "..."], "Z": ["...", "..."], "T1": ["...", "..."], "T2": ["...", "..."], "T3": ["...", "..."], "Wxi": ["...", "..."], "Wxiw": ["...", "..."], "protocol": "plonk", "curve": "bn254" }, "publicSignals": [...], "circuit": "ml-inference-verification" } } ``` ### TEE Attestation **Purpose**: Verify agent runs in Trusted Execution Environment (Intel SGX, AMD SEV, AWS Nitro). **Response Example**: ```json { "validationType": "tee-attestation", "result": "approved", "reasoning": "Agent verified to run in Intel SGX enclave. Remote attestation successful.", "attachments": [ { "name": "SGX Quote", "uri": "ipfs://bafkrei...", "mimeType": "application/octet-stream", "description": "Intel SGX remote attestation quote" }, { "name": "Attestation Report", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "IAS (Intel Attestation Service) verification report" } ], "attestationData": { "teeType": "intel-sgx", "mrenclave": "0xabc123...", "mrsigner": "0xdef456...", "isvprodid": 1, "isvsvn": 1, "reportData": "0x...", "verified": true, "timestamp": "2025-12-20T05:00:38Z" } } ``` ### Crypto-Economic Validation **Purpose**: Verify economic stake backing agent behavior. **Response Example**: ```json { "validationType": "crypto-economic", "result": "approved", "reasoning": "Agent has staked 10 ETH with slashing conditions. Economic security verified.", "stakeProof": { "amount": "10000000000000000000", "currency": "ETH", "stakingContract": "0xstaking123...", "slashingConditions": [ "Incorrect predictions >10% error rate", "Downtime >1 hour", "Data privacy breach" ], "lockupPeriod": "30 days", "transactionHash": "0x..." } } ``` ## Attachment Pattern for Complex Evidence ### Use Cases 1. **Multi-file Test Suites**: Upload ZIP with all test files 2. **Video Demonstrations**: Screen recordings of agent behavior 3. **Large Datasets**: Benchmark data, test results 4. **Binary Proofs**: zkSNARK proofs, attestation quotes 5. **Documentation**: Detailed methodology, audit reports ### Example: Comprehensive Security Validation ```json { "validationType": "security-audit", "result": "conditional", "reasoning": "Agent passed automated scans with 2 medium-severity recommendations. Recommend implementing before production deployment.", "attachments": [ { "name": "Automated Scan Results", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "size": 150000, "description": "Slither + MythX automated security scan results. 0 critical, 0 high, 2 medium findings." }, { "name": "Manual Review Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "size": 2048000, "description": "16-page manual code review by certified auditor. Includes recommendations for gas optimization and edge case handling." }, { "name": "Test Suite Results", "uri": "ipfs://bafkrei...", "mimeType": "application/zip", "size": 5000000, "description": "Complete test suite with 250+ unit tests and 50+ integration tests. All tests passing." }, { "name": "Recommendations Document", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "size": 10000, "description": "Actionable recommendations for addressing 2 medium-severity findings. Estimated 4-8 hours implementation time." } ] } ``` ## Response Templates ### Template 1: Approved Validation ```json { "agentRegistry": "eip155:CHAIN_ID:0x...", "agentId": AGENT_ID, "validatorAddress": "eip155:CHAIN_ID:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "VALIDATION_TYPE", "result": "approved", "reasoning": "[Clear explanation of what was tested and why it passed]", "attachments": [ { "name": "PRIMARY_EVIDENCE", "uri": "ipfs://...", "mimeType": "application/TYPE", "description": "[Detailed description of evidence]" } ] } ``` ### Template 2: Rejected Validation ```json { "agentRegistry": "eip155:CHAIN_ID:0x...", "agentId": AGENT_ID, "validatorAddress": "eip155:CHAIN_ID:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "VALIDATION_TYPE", "result": "rejected", "reasoning": "[Specific failures and why they disqualify the agent]", "failureDetails": [ { "category": "FAILURE_CATEGORY", "severity": "critical|high|medium|low", "description": "[Detailed description]" } ], "attachments": [ { "name": "FAILURE_EVIDENCE", "uri": "ipfs://...", "mimeType": "application/TYPE", "description": "[Evidence of failure]" } ], "recommendations": [ "Recommendation 1: [Actionable fix]", "Recommendation 2: [Actionable fix]" ] } ``` ### Template 3: Conditional Approval ```json { "result": "conditional", "reasoning": "Agent meets basic criteria but has limitations that users should be aware of.", "conditions": [ "Only use for datasets <10,000 rows", "Not suitable for real-time applications (response time >5s)", "Requires manual verification for high-stakes decisions" ], "attachments": [...] } ``` ## Validation Tiers and Weights When multiple validators validate the same agent, their validations are weighted differently based on validator tier: | Validator Tier | Weight Multiplier | Example | | -------------- | ------------------ | ---------------------------------- | | **Platform** | +30% per validator | 8004scan official validators | | **Official** | +20% per validator | EIP-8004 reference validators | | **Verified** | +10% per validator | KYC'd validators with track record | | **Community** | +5% per validator | Anonymous but reputable validators | **Best Practice**: If you're a verified or platform validator, clearly indicate this in your validation metadata: ```json { "validatorMetadata": { "tier": "verified", "organization": "SecureAudit Inc.", "certifications": ["CSCA", "ISO27001"], "website": "https://secureaudit.com" } } ``` ## Reproducibility ### Include Test Environment Details ```json { "testEnvironment": { "network": "sepolia", "blockNumber": 18500000, "timestamp": "2025-12-20T05:00:38Z", "toolsUsed": ["Slither v0.9.6", "MythX", "Foundry"], "testDuration": "7 days", "infrastructure": "AWS EC2 t3.large" } } ``` ### Provide Reproducible Test Scripts ```json { "attachments": [ { "name": "Test Automation Script", "uri": "ipfs://bafkrei...", "mimeType": "text/x-shellscript", "description": "Bash script to reproduce our validation tests. Requires Foundry and Node.js 18+." } ] } ``` ## Common Mistakes to Avoid ### Mistake 1: Insufficient Evidence ❌ **Bad**: "Looks good to me" βœ… **Good**: Detailed reasoning + multiple evidence attachments ### Mistake 2: Non-Standard Format ❌ **Bad**: Using custom JSON schema without ERC-8004 envelope βœ… **Good**: Wrap custom proofs in ERC-8004 standard format **Migration Example**: ```json // ❌ OLD (Groth16 standalone) { "proof": {...}, "publicSignals": [...], "verifierAddress": "0x..." } // βœ… NEW (ERC-8004 envelope + Groth16) { "agentRegistry": "eip155:84532:0x...", "agentId": 56, "validatorAddress": "eip155:84532:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "proofData": { "proof": {...}, "publicSignals": [...], "protocol": "groth16" } } ``` ### Mistake 3: Vague Rejection Reasons ❌ **Bad**: "Failed security check" βœ… **Good**: "Failed reentrancy test. Attack vector: Contract allows recursive calls to withdraw() function without proper state updates. See attached exploit proof-of-concept." ### Mistake 4: Missing CAIP Format ❌ **Bad**: Using plain addresses ```json { "agentRegistry": "0x8004...", "validatorAddress": "0x4baf..." } ``` βœ… **Good**: Using CAIP-2 and CAIP-10 ```json { "agentRegistry": "eip155:84532:0x8004...", "validatorAddress": "eip155:84532:0x4baf..." } ``` ## Advanced Patterns ### Multi-Validator Consensus For critical validations, coordinate with multiple validators: ```json { "result": "approved", "reasoning": "Consensus validation by 3 platform-tier validators. All reached same conclusion independently.", "consensusMetadata": { "totalValidators": 3, "approvals": 3, "rejections": 0, "validators": ["eip155:1:0x1234...", "eip155:1:0x5678...", "eip155:1:0x9abc..."] } } ``` ### Time-Bound Validations For validations that expire: ```json { "result": "approved", "reasoning": "Security audit valid for 6 months. Re-validation recommended after major updates.", "validUntil": "2026-06-20T05:00:38Z", "renewalRequired": true } ``` ### Staged Validations For complex multi-stage validations: ```json { "result": "approved", "reasoning": "Passed all 3 validation stages.", "stages": [ { "stage": "automated-scan", "result": "passed", "completedAt": "2025-12-18T10:00:00Z" }, { "stage": "manual-review", "result": "passed", "completedAt": "2025-12-19T15:00:00Z" }, { "stage": "penetration-test", "result": "passed", "completedAt": "2025-12-20T05:00:38Z" } ] } ``` ## Resources * [Validation Standard](../03-validation-standard.md) * [Feedback Best Practices](feedback-best-practices.md) * [Agent Metadata Parsing](agent-metadata-parsing.md) * [Groth16 Proof System](https://eprint.iacr.org/2016/260.pdf) * [PLONK Protocol](https://eprint.iacr.org/2019/953.pdf) * 8004scan Validator Dashboard *(coming soon)* --- --- url: /v1/docs/implementation/validation-best-practices.md description: >- Practical guide for validators responding to validation requests - SPEC SUBJECT TO CHANGE --- > **🚨 CRITICAL NOTICE** > > **This guide is based on an UNSTABLE specification that is PENDING FINALIZATION.** > > The ERC-8004 Validation Registry specification is **still under active development** and **may change significantly** based on ongoing discussions with the TEE/ZK community. The best practices in this document represent current recommendations but **should not be considered final** for production deployment. > > **Key uncertainties**: > > * TEE attestation format and requirements (to be revised) > * Validation data schema (subject to change) > * Response structure and fields (may be updated) > > **Status tracking**: See [official ERC-8004 repository](https://github.com/erc-8004/erc-8004-contracts/) for latest specification updates. > > **For production use**: **Wait for final v1.1 release** before implementing Validation Registry integrations. These best practices will be updated to match the final specification. ## Description Practical guide for validators responding to validation requests **Audience**: Validators, auditors, testing services **Current state**: v1.1-preview based on SpecsJan26Update (Jan 2026). See [Validation Data Profile](../03-validation-standard.md) for the corresponding data specification. ## Overview This guide provides best practices for validators responding to ERC-8004 validation requests, ensuring high-quality validation responses that build trust in the ecosystem. **What You'll Learn**: * βœ… Structure validation responses effectively * βœ… Choose appropriate validation types * βœ… Provide comprehensive evidence * βœ… Use zkSNARK proofs (Groth16, PLONK, STARK) * βœ… Leverage attachment pattern for complex evidence * βœ… Migrate from custom formats to ERC-8004 standard ## Validation Response Principles ### 1. Be Thorough and Evidence-Based **Every validation MUST include**: * Clear result (approved/rejected/conditional) * Detailed reasoning * Supporting evidence * Reproducible test methodology ❌ **Bad**: ```json { "result": "approved" } ``` βœ… **Good**: ```json { "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "security-audit", "result": "approved", "reasoning": "Agent passed security audit with 0 critical findings. Tested 15 attack vectors including reentrancy, integer overflow, and access control. All tests passed.", "attachments": [ { "name": "Security Audit Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "description": "Comprehensive security audit using Slither v0.9.6 + manual review" } ] } ``` ### 2. Match Validation Type to Request Ensure your response addresses the specific validation type requested: | Validation Type | What to Validate | Evidence to Provide | | ------------------ | ------------------------------- | --------------------------------------- | | `security-audit` | Code security, vulnerabilities | Audit report, test results | | `performance-test` | Speed, scalability, uptime | Benchmark data, load test results | | `accuracy-test` | Output correctness, reliability | Test cases, comparison data | | `zkml-proof` | Zero-knowledge ML verification | zkSNARK proof, public signals | | `tee-attestation` | Trusted execution environment | Attestation certificate, enclave report | | `crypto-economic` | Economic stake verification | Stake proof, slashing conditions | ### 3. Use Structured Result Values **Standard Results**: * `approved` - Agent meets validation criteria * `rejected` - Agent fails validation criteria * `conditional` - Agent meets criteria with conditions/warnings **With Confidence Scores**: ```json { "result": "approved", "confidence": 0.95, "reasoning": "95% confidence based on 1000 test cases. 5% margin due to limited edge case coverage." } ``` ## Validation Type Guides ### Security Audit **Checklist**: * \[ ] Smart contract vulnerabilities (if applicable) * \[ ] API endpoint security * \[ ] Access control validation * \[ ] Data privacy compliance * \[ ] Common attack vectors tested **Response Example**: ```json { "validationType": "security-audit", "result": "approved", "reasoning": "Comprehensive security audit completed. Scanned 5 smart contracts and 12 API endpoints. 0 critical findings, 2 low-severity recommendations provided.", "attachments": [ { "name": "Slither Automated Scan", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Automated scan results using Slither v0.9.6. 47 detectors run, 0 critical issues found." }, { "name": "Manual Review Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "description": "Manual code review by certified auditor. Focused on business logic and edge cases. 2 recommendations for optimization." }, { "name": "Penetration Test Results", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "description": "Tested 15 attack vectors including reentrancy, access control bypass, SQL injection. All tests passed." } ], "testMetadata": { "tool": "Slither v0.9.6", "manualReviewHours": 8, "auditor": "Certified Smart Contract Auditor (CSCA)", "date": "2025-12-20" } } ``` ### Performance Test **Metrics to Measure**: * Response time (average, p50, p95, p99) * Throughput (requests per second) * Uptime (percentage over test period) * Resource usage (CPU, memory, network) **Response Example**: ```json { "validationType": "performance-test", "result": "approved", "reasoning": "Agent demonstrated excellent performance under load. Average response time 1.2s, 99.9% uptime over 7-day test period.", "attachments": [ { "name": "Load Test Results", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Results from 10,000 API calls over 7 days. Peak load: 100 concurrent requests." }, { "name": "Performance Graphs", "uri": "ipfs://bafkrei...", "mimeType": "image/png", "description": "Response time distribution and load curve graphs" } ], "metrics": { "avgResponseTime": 1.2, "p50ResponseTime": 0.9, "p95ResponseTime": 2.1, "p99ResponseTime": 3.5, "uptime": 99.9, "throughput": 50, "testDuration": "7 days", "totalRequests": 10000 } } ``` ### Accuracy Test **Test Methodology**: * Ground truth dataset * Comparison with baseline/control * Error rate calculation * Edge case coverage **Response Example**: ```json { "validationType": "accuracy-test", "result": "approved", "reasoning": "Agent achieved 94% accuracy on 1000-sample test dataset. Matches industry benchmark for blockchain analytics agents.", "attachments": [ { "name": "Test Dataset", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "1000 blockchain transactions with ground truth labels" }, { "name": "Accuracy Report", "uri": "ipfs://bafkrei...", "mimeType": "text/csv", "description": "Per-sample results with predicted vs actual labels" }, { "name": "Confusion Matrix", "uri": "ipfs://bafkrei...", "mimeType": "image/png", "description": "Visualization of classification performance" } ], "metrics": { "accuracy": 0.94, "precision": 0.93, "recall": 0.95, "f1Score": 0.94, "testSamples": 1000, "falsePositives": 30, "falseNegatives": 30 } } ``` ### zkML Proof (zkSNARK) **Purpose**: Zero-knowledge proof of ML model inference without revealing model weights or input data. **Supported Proof Systems**: * **Groth16** (most common, 8000+ validations on Base Sepolia) * **PLONK** (universal setup, more flexible) * **STARK** (no trusted setup, transparent) #### Groth16 Proof Example **Current Format** (used by ZyFi and others): ```json { "validationType": "zkml-proof", "result": "approved", "proof": { "pi_a": ["8070450532247928943", "1234567890123456789", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c", "validationRegistryAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "chainId": 84532, "circuit": "zyfi-rebalancing-validation", "version": "1.0", "timestamp": 1766206835991 } ``` **ERC-8004 Standard Format** (recommended for new implementations): ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "result": "approved", "reasoning": "Zero-knowledge proof verified. Agent rebalancing algorithm meets specification.", "proofData": { "proof": { "pi_a": ["...", "...", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "circuit": "zyfi-rebalancing-validation", "verifierAddress": "0x4baf957..." } } ``` **Migration Path**: See [Validation Standard - Migration Guide](../03-validation-standard.md#migration-guides) #### PLONK Proof Example ```json { "validationType": "zkml-proof", "result": "approved", "proofData": { "proof": { "A": ["...", "..."], "B": ["...", "..."], "C": ["...", "..."], "Z": ["...", "..."], "T1": ["...", "..."], "T2": ["...", "..."], "T3": ["...", "..."], "Wxi": ["...", "..."], "Wxiw": ["...", "..."], "protocol": "plonk", "curve": "bn254" }, "publicSignals": [...], "circuit": "ml-inference-verification" } } ``` ### TEE Attestation **Purpose**: Verify agent runs in Trusted Execution Environment (Intel SGX, AMD SEV, AWS Nitro). **Response Example**: ```json { "validationType": "tee-attestation", "result": "approved", "reasoning": "Agent verified to run in Intel SGX enclave. Remote attestation successful.", "attachments": [ { "name": "SGX Quote", "uri": "ipfs://bafkrei...", "mimeType": "application/octet-stream", "description": "Intel SGX remote attestation quote" }, { "name": "Attestation Report", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "IAS (Intel Attestation Service) verification report" } ], "attestationData": { "teeType": "intel-sgx", "mrenclave": "0xabc123...", "mrsigner": "0xdef456...", "isvprodid": 1, "isvsvn": 1, "reportData": "0x...", "verified": true, "timestamp": "2025-12-20T05:00:38Z" } } ``` ### Crypto-Economic Validation **Purpose**: Verify economic stake backing agent behavior. **Response Example**: ```json { "validationType": "crypto-economic", "result": "approved", "reasoning": "Agent has staked 10 ETH with slashing conditions. Economic security verified.", "stakeProof": { "amount": "10000000000000000000", "currency": "ETH", "stakingContract": "0xstaking123...", "slashingConditions": [ "Incorrect predictions >10% error rate", "Downtime >1 hour", "Data privacy breach" ], "lockupPeriod": "30 days", "transactionHash": "0x..." } } ``` ## Attachment Pattern for Complex Evidence ### Use Cases 1. **Multi-file Test Suites**: Upload ZIP with all test files 2. **Video Demonstrations**: Screen recordings of agent behavior 3. **Large Datasets**: Benchmark data, test results 4. **Binary Proofs**: zkSNARK proofs, attestation quotes 5. **Documentation**: Detailed methodology, audit reports ### Example: Comprehensive Security Validation ```json { "validationType": "security-audit", "result": "conditional", "reasoning": "Agent passed automated scans with 2 medium-severity recommendations. Recommend implementing before production deployment.", "attachments": [ { "name": "Automated Scan Results", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "size": 150000, "description": "Slither + MythX automated security scan results. 0 critical, 0 high, 2 medium findings." }, { "name": "Manual Review Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "size": 2048000, "description": "16-page manual code review by certified auditor. Includes recommendations for gas optimization and edge case handling." }, { "name": "Test Suite Results", "uri": "ipfs://bafkrei...", "mimeType": "application/zip", "size": 5000000, "description": "Complete test suite with 250+ unit tests and 50+ integration tests. All tests passing." }, { "name": "Recommendations Document", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "size": 10000, "description": "Actionable recommendations for addressing 2 medium-severity findings. Estimated 4-8 hours implementation time." } ] } ``` ## Response Templates ### Template 1: Approved Validation ```json { "agentRegistry": "eip155:CHAIN_ID:0x...", "agentId": AGENT_ID, "validatorAddress": "eip155:CHAIN_ID:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "VALIDATION_TYPE", "result": "approved", "reasoning": "[Clear explanation of what was tested and why it passed]", "attachments": [ { "name": "PRIMARY_EVIDENCE", "uri": "ipfs://...", "mimeType": "application/TYPE", "description": "[Detailed description of evidence]" } ] } ``` ### Template 2: Rejected Validation ```json { "agentRegistry": "eip155:CHAIN_ID:0x...", "agentId": AGENT_ID, "validatorAddress": "eip155:CHAIN_ID:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "VALIDATION_TYPE", "result": "rejected", "reasoning": "[Specific failures and why they disqualify the agent]", "failureDetails": [ { "category": "FAILURE_CATEGORY", "severity": "critical|high|medium|low", "description": "[Detailed description]" } ], "attachments": [ { "name": "FAILURE_EVIDENCE", "uri": "ipfs://...", "mimeType": "application/TYPE", "description": "[Evidence of failure]" } ], "recommendations": [ "Recommendation 1: [Actionable fix]", "Recommendation 2: [Actionable fix]" ] } ``` ### Template 3: Conditional Approval ```json { "result": "conditional", "reasoning": "Agent meets basic criteria but has limitations that users should be aware of.", "conditions": [ "Only use for datasets <10,000 rows", "Not suitable for real-time applications (response time >5s)", "Requires manual verification for high-stakes decisions" ], "attachments": [...] } ``` ## Validation Tiers and Weights When multiple validators validate the same agent, their validations are weighted differently based on validator tier: | Validator Tier | Weight Multiplier | Example | | -------------- | ------------------ | ---------------------------------- | | **Platform** | +30% per validator | 8004scan official validators | | **Official** | +20% per validator | EIP-8004 reference validators | | **Verified** | +10% per validator | KYC'd validators with track record | | **Community** | +5% per validator | Anonymous but reputable validators | **Best Practice**: If you're a verified or platform validator, clearly indicate this in your validation metadata: ```json { "validatorMetadata": { "tier": "verified", "organization": "SecureAudit Inc.", "certifications": ["CSCA", "ISO27001"], "website": "https://secureaudit.com" } } ``` ## Reproducibility ### Include Test Environment Details ```json { "testEnvironment": { "network": "sepolia", "blockNumber": 18500000, "timestamp": "2025-12-20T05:00:38Z", "toolsUsed": ["Slither v0.9.6", "MythX", "Foundry"], "testDuration": "7 days", "infrastructure": "AWS EC2 t3.large" } } ``` ### Provide Reproducible Test Scripts ```json { "attachments": [ { "name": "Test Automation Script", "uri": "ipfs://bafkrei...", "mimeType": "text/x-shellscript", "description": "Bash script to reproduce our validation tests. Requires Foundry and Node.js 18+." } ] } ``` ## Common Mistakes to Avoid ### Mistake 1: Insufficient Evidence ❌ **Bad**: "Looks good to me" βœ… **Good**: Detailed reasoning + multiple evidence attachments ### Mistake 2: Non-Standard Format ❌ **Bad**: Using custom JSON schema without ERC-8004 envelope βœ… **Good**: Wrap custom proofs in ERC-8004 standard format **Migration Example**: ```json // ❌ OLD (Groth16 standalone) { "proof": {...}, "publicSignals": [...], "verifierAddress": "0x..." } // βœ… NEW (ERC-8004 envelope + Groth16) { "agentRegistry": "eip155:84532:0x...", "agentId": 56, "validatorAddress": "eip155:84532:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "proofData": { "proof": {...}, "publicSignals": [...], "protocol": "groth16" } } ``` ### Mistake 3: Vague Rejection Reasons ❌ **Bad**: "Failed security check" βœ… **Good**: "Failed reentrancy test. Attack vector: Contract allows recursive calls to withdraw() function without proper state updates. See attached exploit proof-of-concept." ### Mistake 4: Missing CAIP Format ❌ **Bad**: Using plain addresses ```json { "agentRegistry": "0x8004...", "validatorAddress": "0x4baf..." } ``` βœ… **Good**: Using CAIP-2 and CAIP-10 ```json { "agentRegistry": "eip155:84532:0x8004...", "validatorAddress": "eip155:84532:0x4baf..." } ``` ## Advanced Patterns ### Multi-Validator Consensus For critical validations, coordinate with multiple validators: ```json { "result": "approved", "reasoning": "Consensus validation by 3 platform-tier validators. All reached same conclusion independently.", "consensusMetadata": { "totalValidators": 3, "approvals": 3, "rejections": 0, "validators": ["eip155:1:0x1234...", "eip155:1:0x5678...", "eip155:1:0x9abc..."] } } ``` ### Time-Bound Validations For validations that expire: ```json { "result": "approved", "reasoning": "Security audit valid for 6 months. Re-validation recommended after major updates.", "validUntil": "2026-06-20T05:00:38Z", "renewalRequired": true } ``` ### Staged Validations For complex multi-stage validations: ```json { "result": "approved", "reasoning": "Passed all 3 validation stages.", "stages": [ { "stage": "automated-scan", "result": "passed", "completedAt": "2025-12-18T10:00:00Z" }, { "stage": "manual-review", "result": "passed", "completedAt": "2025-12-19T15:00:00Z" }, { "stage": "penetration-test", "result": "passed", "completedAt": "2025-12-20T05:00:38Z" } ] } ``` ## Resources * [Validation Standard](../03-validation-standard.md) * [Feedback Best Practices](feedback-best-practices.md) * [Agent Metadata Parsing](agent-metadata-parsing.md) * [Groth16 Proof System](https://eprint.iacr.org/2016/260.pdf) * [PLONK Protocol](https://eprint.iacr.org/2019/953.pdf) * 8004scan Validator Dashboard *(coming soon)* --- --- url: /docs/03-validation-standard.md description: >- Recommended offchain data format for ERC-8004 validation records - SPEC SUBJECT TO CHANGE --- > **🚨 CRITICAL NOTICE** > > **This specification is UNSTABLE and PENDING FINALIZATION.** > > The ERC-8004 Validation Registry specification is **still under active development** and **may change significantly** based on ongoing discussions with the TEE/ZK community. This document represents the current working draft but **should not be considered final** for production deployment. > > **Key uncertainties**: > > * TEE attestation format and requirements (to be revised) > * Full contract ABI and function signatures (preview only) > * Event structure and indexed parameters (may change) > * Off-chain JSON schema (subject to revision) > > **Status tracking**: See [official ERC-8004 repository](https://github.com/erc-8004/erc-8004-contracts/) for latest specification updates and timelines. > > **For production use**: **Wait for final v1.1 release** before implementing Validation Registry integrations. ## Description Recommended offchain data profile for ERC-8004 validation records. This document provides implementation-agnostic guidance for structuring validation request and response data referenced by the `requestURI` and `responseURI` fields in ERC-8004 Validation Registry contracts. **Current state**: v1.1-preview based on SpecsJan26Update (Jan 2026). See [official progress](https://github.com/erc-8004/erc-8004-contracts/) for latest updates. ### Specification Maturity | Component | Status | Ready for Production? | | ----------------------- | ----------- | ------------------------------------------------------------------------------------------------- | | **Identity Registry** | βœ… STABLE | Yes | | **Reputation Registry** | βœ… STABLE | Yes | | **Validation Registry** | ⚠️ UNSTABLE | **No** - Under development (see [official repo](https://github.com/erc-8004/erc-8004-contracts/)) | **Recommendation**: Design your validation architecture but keep data migration paths flexible as the specification evolves. ## Relationship to EIP-8004 This is **not part** of the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification, which only defines: * Smart contract interface (Validation Registry) * Onchain fields: `validatorAddress`, `agentId`, `requestUri`, `responseUri`, `response`, `tag` * URI references to offchain data **This profile** provides recommended offchain JSON structures for better interoperability across ERC-8004 implementations. ## Terminology This document follows conventions defined in [Conventions](00-CONVENTIONS.md). For attachment file patterns, see [Attachment Pattern Standard](extensions/04-attachment-pattern-standard.md). ## Intended Audience * Validators creating validation requests and responses * Indexers and explorers building Validation Registry systems ## Table of Contents 1. [Overview](#overview) 2. [Format Compatibility Approach](#format-compatibility-approach) 3. [Validation Request Profile](#validation-request-profile) 4. [Validation Response Profile](#validation-response-profile) 5. [Known Custom Formats](#known-custom-formats) 6. [Attachment Pattern](#attachment-pattern) 7. [Parse Status Indicators](#parse-status-indicators) 8. [Migration Guide](#migration-guide) 9. [Examples](#examples) ## Overview ### Onchain vs Offchain Data **Stored Onchain**: * `validatorAddress` (address) - Who validates * `agentId` (uint256) - Which agent * `requestHash` (bytes32) - Hash of request data * `response` (uint8) - Validation score (0-100) * `responseHash` (bytes32) - Hash of response data * `tag` (string) - Validation category * `lastUpdate` (uint256) - Unix timestamp **Emitted in Events** (not stored): * `requestURI` - Location of detailed request data * `responseURI` - Location of detailed response data **Indexers**: Use event parameters to fetch offchain URIs and retrieve complete validation data. **Offchain Data** (referenced by URI): * Detailed validation criteria and methodology * Proof data (zkSNARK, TEE attestation, etc.) * Test results and supporting evidence * Resource usage and performance metrics ## Format Compatibility Approach > **Non-normative**: This section describes 8004scan's recommended approach to handling diverse validation formats. ### Level 1: Recommended Profile βœ… **Parse Status**: `success` (no issues) or `warning` (minor suggestions) The community-recommended profile format for maximum interoperability. **When to Use**: * New validation systems * Multi-chain deployments * Public registries requiring interoperability * Integration with multiple ERC-8004 tools **Benefits**: * βœ… Better indexing and searchability * βœ… Frontend displays all metadata * βœ… Compatible with standard tooling * βœ… Easier integration across platforms ### Level 2: Known Custom Formats 🟑 **Parse Status**: `known_custom` Recognized specialized formats that don't conform to ERC-8004 but are widely used. **Supported Formats**: * **Groth16 zkSNARK Proof** - Complete zero-knowledge proofs * **PLONK Proof** - (Future support planned) * **STARK Proof** - (Future support planned) * **Halo2 Proof** - (Future support planned) **When to Use**: * Existing production systems (e.g., ZyFi protocol) * Specialized proof requirements * Migration period from custom to standard **Limitations**: * ⚠️ Limited metadata extraction * ⚠️ Manual format interpretation required * ⚠️ May not appear in some filtered views ### Level 3: Unknown Formats ⚠️ **Parse Status**: `unknown` Valid JSON that doesn't match any recognized pattern. **Handling**: * Data stored as-is in `offchain_request_data` / `offchain_response_data` * Displayed as raw JSON in UI * No automatic metadata extraction **Recommendation**: Consider migrating to Level 1 (Recommended Profile) for better interoperability, or contact the community to add Level 2 support for your format. ## Validation Request Profile ### Schema ```json { // Required "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", // Recommended "reasoning": "Request validation for agent rebalancing logic", "deadline": "2025-12-21T05:00:38Z", // Optional: Type-specific payloads "job": { /* Crypto-economic validation */ }, "teeRequest": { /* TEE attestation validation */ }, "zkmlRequest": { /* zkML proof validation */ }, "bounty": { /* Incentive structure */ }, "attachments": [ /* Supporting evidence */ ] } ``` ### Recommended Schema (Level 1) ```json { // ============ REQUIRED FIELDS ============ "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", // ============ RECOMMENDED FIELDS ============ "reasoning": "Request validation for agent rebalancing logic", "deadline": "2025-12-21T05:00:38Z", // ============ OPTIONAL: VALIDATION TYPE PAYLOADS ============ // For crypto-economic validations "job": { "taskDescription": "Validate portfolio rebalancing logic", "expectedOutputFormat": "JSON schema with rebalancing recommendations", "testDataUri": "ipfs://Qm...", "successCriteria": "Optimal allocation within 2% of benchmark" }, // For TEE attestation validations "teeRequest": { "attestationType": "sgx", "requiredEnclave": "ProductID:1,SecurityVersion:2", "measurementHash": "0x..." }, // For zkML proof validations "zkmlRequest": { "circuit": "zyfi-rebalancing-validation", "publicInputs": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c" }, // ============ OPTIONAL: BOUNTY ============ "bounty": { "amount": "1000000000000000000", "token": "eip155:84532:0x...", "conditions": "Paid upon successful validation within 24 hours" }, // ============ OPTIONAL: ATTACHMENTS ============ "attachments": [ { "name": "Test Dataset", "uri": "ipfs://Qmxxx...", "mimeType": "application/json", "size": 50000, "description": "Sample portfolio data for rebalancing validation", "uploadedAt": "2025-12-20T05:00:00Z" } ] } ``` ### Required Fields | Field | Type | Format | Description | | ------------------ | ------ | -------- | ------------------------------------------------------------------- | | `agentRegistry` | string | CAIP-10 | Agent's identity registry address (e.g., `eip155:84532:0x8004C...`) | | `agentId` | number | uint256 | Agent token ID | | `validatorAddress` | string | CAIP-10 | Validator's wallet address (e.g., `eip155:84532:0x4baf...`) | | `createdAt` | string | ISO 8601 | Request creation timestamp | | `validationType` | string | enum | One of: `crypto-economic`, `tee-attestation`, `zkml-proof` | ### Recommended Fields | Field | Type | Description | | ----------- | ----------------- | --------------------------------------- | | `reasoning` | string | Explanation of why validation is needed | | `deadline` | string (ISO 8601) | Expected response deadline | ### Optional Fields by Validation Type **Crypto-Economic** (`job` object): * `taskDescription` - What the agent should do * `expectedOutputFormat` - Format specification * `testDataUri` - Test data location * `successCriteria` - How success is measured **TEE Attestation** (`teeRequest` object): * `attestationType` - TEE type (e.g., "sgx", "sev", "tdx") * `requiredEnclave` - Enclave requirements * `measurementHash` - Expected measurement **zkML Proof** (`zkmlRequest` object): * `circuit` - Circuit identifier * `publicInputs` - Public inputs array * `verifierAddress` - Verifier contract address ## Validation Response Profile ### Recommended Schema (Level 1) ```json { // ============ REQUIRED FIELDS ============ "requestHash": "0x5c1a08c66c0489030f05990a83534280ee08da7cd944dc353bf4b661c5c96657", "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "agentId": 56, "response": 100, "createdAt": "2025-12-20T06:00:00Z", // ============ RECOMMENDED FIELDS ============ "result": "passed", "reasoning": "Agent successfully passed all validation tests", "confidence": 0.95, // ============ OPTIONAL: VALIDATION TYPE PROOFS ============ // For crypto-economic validations "executionProof": { "outputUri": "ipfs://Qmyyy...", "executionTime": "2.5s", "resourceUsage": { "cpu": "0.8 cores", "memory": "512MB", "network": "10MB" } }, // For TEE attestation validations "teeAttestation": { "quote": "0x...", "quoteSignature": "0x...", "reportData": "0x...", "timestamp": "2025-12-20T05:30:00Z" }, // For zkML proof validations "zkmlProof": { "proof": { "pi_a": ["...", "...", "1"], "pi_b": [[...], [...], ["1", "0"]], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifiedAt": "2025-12-20T05:45:00Z" }, // ============ OPTIONAL: ATTACHMENTS ============ "attachments": [ { "name": "Validation Report", "uri": "ipfs://Qmzzz...", "mimeType": "application/pdf", "size": 2048000, "description": "Comprehensive validation report with test results", "uploadedAt": "2025-12-20T05:50:00Z" } ] } ``` ### Required Fields | Field | Type | Format | Description | | ------------------ | ------ | --------------------- | --------------------------------------------------------------------- | | `requestHash` | string | bytes32 hex | Hash of the validation request (from on-chain contract) | | `validatorAddress` | string | CAIP-10 | Validator's wallet address (e.g., `eip155:84532:0x4baf...`) | | `agentId` | number | uint256 | Agent token ID | | `response` | number | 0-100 (uint8 onchain) | Validation score | | `createdAt` | string | ISO 8601 | Response creation timestamp | | `tag` | string | - | Validation category (e.g., `security-audit`, `tee-attestation`, etc.) | ### Recommended Fields | Field | Type | Values | Description | | ------------ | ------ | ----------------------------- | ------------------------------ | | `result` | string | `passed`, `failed`, `partial` | Validation result | | `reasoning` | string | - | Explanation of the result | | `confidence` | number | 0.0-1.0 | Confidence level in the result | ## Known Custom Formats ### Groth16 zkSNARK Proof **Format Type**: `groth16_zksnark` **Parse Status**: `known_custom` **Use Case**: Zero-knowledge proof validation (e.g., ZyFi rebalancing) ```json { // ============ PROOF STRUCTURE ============ "proof": { "pi_a": ["8070450532247928943", "1234567890123456789", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, // ============ PUBLIC SIGNALS ============ "publicSignals": ["4190804445", "1"], // ============ VERIFICATION INFO ============ "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c", "validationRegistryAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", // ============ METADATA ============ "chainId": 84532, "circuit": "zyfi-rebalancing-validation", "version": "1.0", "timestamp": 1734675235991 } ``` **Known Usage**: * **ZyFi Protocol**: 8,000+ validations on Base Sepolia * **Circuit**: `zyfi-rebalancing-validation` * **Verifier**: `0x4baf957830423f36978039e32d95ee958aa0560c` **Detection Criteria**: * Has `proof` object with `pi_a`, `pi_b`, `pi_c` fields * Has `publicSignals` array * Has `verifierAddress` or `validationRegistryAddress` ## Attachment Pattern ### Overview The attachment pattern allows adding multiple evidence files to validation requests or responses. **For complete attachment schema and guidelines**, see [Attachment Pattern Guidelines](extensions/04-attachment-pattern-standard.md). ### Quick Reference ```typescript interface AttachmentFile { name: string; // Display name (required) uri: string; // File location (required) mimeType: string; // MIME type (required) size: number; // File size in bytes (required) description?: string; // Optional context uploadedAt?: string; // Optional timestamp (ISO 8601 UTC) } ``` ### Common Use Cases for Validation * **Test Results**: Automated test output, benchmark data * **Audit Reports**: Security audits, code reviews * **TEE Attestations**: Remote attestation documents * **Performance Metrics**: Load test results, uptime reports **Supported File Types**: PDFs, images, videos, JSON, CSV, text files, and more. See [Attachment Pattern Guidelines](extensions/04-attachment-pattern-standard.md) for detailed specifications and examples. ## Parse Status Indicators When querying validation data via the 8004scan API, each record includes a `parse_status` field indicating format compliance. | Status | Meaning | UI Display | Action Required | | -------------- | ---------------------------------------- | --------------------- | ------------------ | | `success` | ERC-8004 compliant, no warnings | βœ… Green checkmark | None | | `warning` | ERC-8004 compliant, minor suggestions | 🟑 Yellow warning | Review suggestions | | `known_custom` | Recognized custom format (e.g., Groth16) | 🟑 Custom badge | Consider migrating | | `unknown` | Unrecognized format | ⚠️ Grey question mark | Update to standard | | `error` | Parse/fetch failure | ❌ Red error | Fix URI/data | ## Migration Guide ### From Groth16 to ERC-8004 Standard **Minimal Upgrade** (wrap existing proof): ```json { "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "zkmlProof": { "proof": { "pi_a": [...], "pi_b": [...], "pi_c": [...], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "circuit": "zyfi-rebalancing-validation" } } ``` **Full Upgrade** (use attachments): ```json { "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "reasoning": "Agent rebalancing validated via zkSNARK", "attachments": [ { "name": "Groth16 Proof", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "ZyFi rebalancing validation proof" } ] } ``` ## Examples ### Example 1: zkML Validation Request ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "reasoning": "Validate agent's portfolio rebalancing algorithm", "deadline": "2025-12-21T05:00:38Z", "zkmlRequest": { "circuit": "zyfi-rebalancing-validation", "publicInputs": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c" } } ``` ### Example 2: Validation Response with Groth16 Proof ```json { "requestHash": "0x5c1a08c66c0489030f05990a83534280ee08da7cd944dc353bf4b661c5c96657", "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "agentId": 56, "response": 100, "createdAt": "2025-12-20T06:00:00Z", "tag": "zkml-proof", "result": "passed", "reasoning": "Agent rebalancing logic validated. All test cases passed.", "confidence": 0.95, "zkmlProof": { "proof": { "pi_a": [...], "pi_b": [...], "pi_c": [...], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifiedAt": "2025-12-20T05:45:00Z" } } ``` ## FAQ ### Q: How are Validation Registry contracts upgraded (v1.1 and beyond)? **A**: ERC-8004 uses the UUPS (Universal Upgradeable Proxy Standard) pattern for safe upgrades: ```solidity // Current deployment (v1.1) address proxyAddress = 0x...; // Permanent address address implV1 = 0x...; // v1.1 implementation // When upgrading to v1.1+ address implV2 = 0x...; // New implementation // Owner calls: proxy.upgradeTo(implV2) // Users continue using same proxy address (0x...) ``` **Key guarantees**: 1. **Permanent address**: The proxy address never changes * All validation records reference fixed registry address * Off-chain indexers continue working without migration 2. **Storage layout preservation**: Upgrades MUST NOT change field order * Existing validation records remain valid * New fields added at end only 3. **Event compatibility**: New events additive only * Old indexers continue processing events * New indexers see full history 4. **Backwards compatibility**: Function signatures stable * `recordValidation()` signature guaranteed across upgrades * New features added via new functions **For indexers**: * Continue listening to same contract address * New validation types appear in events * Old validation records accessible via historical queries * No need to re-index on upgrade **For validators**: * URI format (`requestUri`, `responseUri`) is stable * Off-chain data format guidelines (this document) apply across versions * Submit validation responses to same contract address always *** ## See Also * [Feedback Standard](02-feedback-standard.md) - Reputation Registry offchain data format * [Agent Metadata Standard](01-agent-metadata-standard.md) - AgentURI metadata format * [Validation Best Practices](implementation/validation-best-practices.md) - Implementation guide * [Sources & References](reference/sources.md) - Methodology and data sources --- --- url: /v1/docs/03-validation-standard.md description: >- Recommended offchain data format for ERC-8004 validation records - SPEC SUBJECT TO CHANGE --- > **🚨 CRITICAL NOTICE** > > **This specification is UNSTABLE and PENDING FINALIZATION.** > > The ERC-8004 Validation Registry specification is **still under active development** and **may change significantly** based on ongoing discussions with the TEE/ZK community. This document represents the current working draft but **should not be considered final** for production deployment. > > **Key uncertainties**: > > * TEE attestation format and requirements (to be revised) > * Full contract ABI and function signatures (preview only) > * Event structure and indexed parameters (may change) > * Off-chain JSON schema (subject to revision) > > **Status tracking**: See [official ERC-8004 repository](https://github.com/erc-8004/erc-8004-contracts/) for latest specification updates and timelines. > > **For production use**: **Wait for final v1.1 release** before implementing Validation Registry integrations. ## Description Recommended offchain data profile for ERC-8004 validation records. This document provides implementation-agnostic guidance for structuring validation request and response data referenced by the `requestURI` and `responseURI` fields in ERC-8004 Validation Registry contracts. **Current state**: v1.1-preview based on SpecsJan26Update (Jan 2026). See [official progress](https://github.com/erc-8004/erc-8004-contracts/) for latest updates. ### Specification Maturity | Component | Status | Ready for Production? | | ----------------------- | ----------- | ------------------------------------------------------------------------------------------------- | | **Identity Registry** | βœ… STABLE | Yes | | **Reputation Registry** | βœ… STABLE | Yes | | **Validation Registry** | ⚠️ UNSTABLE | **No** - Under development (see [official repo](https://github.com/erc-8004/erc-8004-contracts/)) | **Recommendation**: Design your validation architecture but keep data migration paths flexible as the specification evolves. ## Relationship to EIP-8004 This is **not part** of the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification, which only defines: * Smart contract interface (Validation Registry) * Onchain fields: `validatorAddress`, `agentId`, `requestUri`, `responseUri`, `response`, `tag` * URI references to offchain data **This profile** provides recommended offchain JSON structures for better interoperability across ERC-8004 implementations. ## Terminology This document follows conventions defined in [Conventions](00-CONVENTIONS.md). For attachment file patterns, see [Attachment Pattern Standard](extensions/04-attachment-pattern-standard.md). ## Intended Audience * Validators creating validation requests and responses * Indexers and explorers building Validation Registry systems ## Table of Contents 1. [Overview](#overview) 2. [Format Compatibility Approach](#format-compatibility-approach) 3. [Validation Request Profile](#validation-request-profile) 4. [Validation Response Profile](#validation-response-profile) 5. [Known Custom Formats](#known-custom-formats) 6. [Attachment Pattern](#attachment-pattern) 7. [Parse Status Indicators](#parse-status-indicators) 8. [Migration Guide](#migration-guide) 9. [Examples](#examples) ## Overview ### Onchain vs Offchain Data **Stored Onchain**: * `validatorAddress` (address) - Who validates * `agentId` (uint256) - Which agent * `requestHash` (bytes32) - Hash of request data * `response` (uint8) - Validation score (0-100) * `responseHash` (bytes32) - Hash of response data * `tag` (string) - Validation category * `lastUpdate` (uint256) - Unix timestamp **Emitted in Events** (not stored): * `requestURI` - Location of detailed request data * `responseURI` - Location of detailed response data **Indexers**: Use event parameters to fetch offchain URIs and retrieve complete validation data. **Offchain Data** (referenced by URI): * Detailed validation criteria and methodology * Proof data (zkSNARK, TEE attestation, etc.) * Test results and supporting evidence * Resource usage and performance metrics ## Format Compatibility Approach > **Non-normative**: This section describes 8004scan's recommended approach to handling diverse validation formats. ### Level 1: Recommended Profile βœ… **Parse Status**: `success` (no issues) or `warning` (minor suggestions) The community-recommended profile format for maximum interoperability. **When to Use**: * New validation systems * Multi-chain deployments * Public registries requiring interoperability * Integration with multiple ERC-8004 tools **Benefits**: * βœ… Better indexing and searchability * βœ… Frontend displays all metadata * βœ… Compatible with standard tooling * βœ… Easier integration across platforms ### Level 2: Known Custom Formats 🟑 **Parse Status**: `known_custom` Recognized specialized formats that don't conform to ERC-8004 but are widely used. **Supported Formats**: * **Groth16 zkSNARK Proof** - Complete zero-knowledge proofs * **PLONK Proof** - (Future support planned) * **STARK Proof** - (Future support planned) * **Halo2 Proof** - (Future support planned) **When to Use**: * Existing production systems (e.g., ZyFi protocol) * Specialized proof requirements * Migration period from custom to standard **Limitations**: * ⚠️ Limited metadata extraction * ⚠️ Manual format interpretation required * ⚠️ May not appear in some filtered views ### Level 3: Unknown Formats ⚠️ **Parse Status**: `unknown` Valid JSON that doesn't match any recognized pattern. **Handling**: * Data stored as-is in `offchain_request_data` / `offchain_response_data` * Displayed as raw JSON in UI * No automatic metadata extraction **Recommendation**: Consider migrating to Level 1 (Recommended Profile) for better interoperability, or contact the community to add Level 2 support for your format. ## Validation Request Profile ### Schema ```json { // Required "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", // Recommended "reasoning": "Request validation for agent rebalancing logic", "deadline": "2025-12-21T05:00:38Z", // Optional: Type-specific payloads "job": { /* Crypto-economic validation */ }, "teeRequest": { /* TEE attestation validation */ }, "zkmlRequest": { /* zkML proof validation */ }, "bounty": { /* Incentive structure */ }, "attachments": [ /* Supporting evidence */ ] } ``` ### Recommended Schema (Level 1) ```json { // ============ REQUIRED FIELDS ============ "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", // ============ RECOMMENDED FIELDS ============ "reasoning": "Request validation for agent rebalancing logic", "deadline": "2025-12-21T05:00:38Z", // ============ OPTIONAL: VALIDATION TYPE PAYLOADS ============ // For crypto-economic validations "job": { "taskDescription": "Validate portfolio rebalancing logic", "expectedOutputFormat": "JSON schema with rebalancing recommendations", "testDataUri": "ipfs://Qm...", "successCriteria": "Optimal allocation within 2% of benchmark" }, // For TEE attestation validations "teeRequest": { "attestationType": "sgx", "requiredEnclave": "ProductID:1,SecurityVersion:2", "measurementHash": "0x..." }, // For zkML proof validations "zkmlRequest": { "circuit": "zyfi-rebalancing-validation", "publicInputs": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c" }, // ============ OPTIONAL: BOUNTY ============ "bounty": { "amount": "1000000000000000000", "token": "eip155:84532:0x...", "conditions": "Paid upon successful validation within 24 hours" }, // ============ OPTIONAL: ATTACHMENTS ============ "attachments": [ { "name": "Test Dataset", "uri": "ipfs://Qmxxx...", "mimeType": "application/json", "size": 50000, "description": "Sample portfolio data for rebalancing validation", "uploadedAt": "2025-12-20T05:00:00Z" } ] } ``` ### Required Fields | Field | Type | Format | Description | | ------------------ | ------ | -------- | ------------------------------------------------------------------- | | `agentRegistry` | string | CAIP-10 | Agent's identity registry address (e.g., `eip155:84532:0x8004C...`) | | `agentId` | number | uint256 | Agent token ID | | `validatorAddress` | string | CAIP-10 | Validator's wallet address (e.g., `eip155:84532:0x4baf...`) | | `createdAt` | string | ISO 8601 | Request creation timestamp | | `validationType` | string | enum | One of: `crypto-economic`, `tee-attestation`, `zkml-proof` | ### Recommended Fields | Field | Type | Description | | ----------- | ----------------- | --------------------------------------- | | `reasoning` | string | Explanation of why validation is needed | | `deadline` | string (ISO 8601) | Expected response deadline | ### Optional Fields by Validation Type **Crypto-Economic** (`job` object): * `taskDescription` - What the agent should do * `expectedOutputFormat` - Format specification * `testDataUri` - Test data location * `successCriteria` - How success is measured **TEE Attestation** (`teeRequest` object): * `attestationType` - TEE type (e.g., "sgx", "sev", "tdx") * `requiredEnclave` - Enclave requirements * `measurementHash` - Expected measurement **zkML Proof** (`zkmlRequest` object): * `circuit` - Circuit identifier * `publicInputs` - Public inputs array * `verifierAddress` - Verifier contract address ## Validation Response Profile ### Recommended Schema (Level 1) ```json { // ============ REQUIRED FIELDS ============ "requestHash": "0x5c1a08c66c0489030f05990a83534280ee08da7cd944dc353bf4b661c5c96657", "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "agentId": 56, "response": 100, "createdAt": "2025-12-20T06:00:00Z", // ============ RECOMMENDED FIELDS ============ "result": "passed", "reasoning": "Agent successfully passed all validation tests", "confidence": 0.95, // ============ OPTIONAL: VALIDATION TYPE PROOFS ============ // For crypto-economic validations "executionProof": { "outputUri": "ipfs://Qmyyy...", "executionTime": "2.5s", "resourceUsage": { "cpu": "0.8 cores", "memory": "512MB", "network": "10MB" } }, // For TEE attestation validations "teeAttestation": { "quote": "0x...", "quoteSignature": "0x...", "reportData": "0x...", "timestamp": "2025-12-20T05:30:00Z" }, // For zkML proof validations "zkmlProof": { "proof": { "pi_a": ["...", "...", "1"], "pi_b": [[...], [...], ["1", "0"]], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifiedAt": "2025-12-20T05:45:00Z" }, // ============ OPTIONAL: ATTACHMENTS ============ "attachments": [ { "name": "Validation Report", "uri": "ipfs://Qmzzz...", "mimeType": "application/pdf", "size": 2048000, "description": "Comprehensive validation report with test results", "uploadedAt": "2025-12-20T05:50:00Z" } ] } ``` ### Required Fields | Field | Type | Format | Description | | ------------------ | ------ | --------------------- | --------------------------------------------------------------------- | | `requestHash` | string | bytes32 hex | Hash of the validation request (from on-chain contract) | | `validatorAddress` | string | CAIP-10 | Validator's wallet address (e.g., `eip155:84532:0x4baf...`) | | `agentId` | number | uint256 | Agent token ID | | `response` | number | 0-100 (uint8 onchain) | Validation score | | `createdAt` | string | ISO 8601 | Response creation timestamp | | `tag` | string | - | Validation category (e.g., `security-audit`, `tee-attestation`, etc.) | ### Recommended Fields | Field | Type | Values | Description | | ------------ | ------ | ----------------------------- | ------------------------------ | | `result` | string | `passed`, `failed`, `partial` | Validation result | | `reasoning` | string | - | Explanation of the result | | `confidence` | number | 0.0-1.0 | Confidence level in the result | ## Known Custom Formats ### Groth16 zkSNARK Proof **Format Type**: `groth16_zksnark` **Parse Status**: `known_custom` **Use Case**: Zero-knowledge proof validation (e.g., ZyFi rebalancing) ```json { // ============ PROOF STRUCTURE ============ "proof": { "pi_a": ["8070450532247928943", "1234567890123456789", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, // ============ PUBLIC SIGNALS ============ "publicSignals": ["4190804445", "1"], // ============ VERIFICATION INFO ============ "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c", "validationRegistryAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", // ============ METADATA ============ "chainId": 84532, "circuit": "zyfi-rebalancing-validation", "version": "1.0", "timestamp": 1734675235991 } ``` **Known Usage**: * **ZyFi Protocol**: 8,000+ validations on Base Sepolia * **Circuit**: `zyfi-rebalancing-validation` * **Verifier**: `0x4baf957830423f36978039e32d95ee958aa0560c` **Detection Criteria**: * Has `proof` object with `pi_a`, `pi_b`, `pi_c` fields * Has `publicSignals` array * Has `verifierAddress` or `validationRegistryAddress` ## Attachment Pattern ### Overview The attachment pattern allows adding multiple evidence files to validation requests or responses. **For complete attachment schema and guidelines**, see [Attachment Pattern Guidelines](extensions/04-attachment-pattern-standard.md). ### Quick Reference ```typescript interface AttachmentFile { name: string; // Display name (required) uri: string; // File location (required) mimeType: string; // MIME type (required) size: number; // File size in bytes (required) description?: string; // Optional context uploadedAt?: string; // Optional timestamp (ISO 8601 UTC) } ``` ### Common Use Cases for Validation * **Test Results**: Automated test output, benchmark data * **Audit Reports**: Security audits, code reviews * **TEE Attestations**: Remote attestation documents * **Performance Metrics**: Load test results, uptime reports **Supported File Types**: PDFs, images, videos, JSON, CSV, text files, and more. See [Attachment Pattern Guidelines](extensions/04-attachment-pattern-standard.md) for detailed specifications and examples. ## Parse Status Indicators When querying validation data via the 8004scan API, each record includes a `parse_status` field indicating format compliance. | Status | Meaning | UI Display | Action Required | | -------------- | ---------------------------------------- | --------------------- | ------------------ | | `success` | ERC-8004 compliant, no warnings | βœ… Green checkmark | None | | `warning` | ERC-8004 compliant, minor suggestions | 🟑 Yellow warning | Review suggestions | | `known_custom` | Recognized custom format (e.g., Groth16) | 🟑 Custom badge | Consider migrating | | `unknown` | Unrecognized format | ⚠️ Grey question mark | Update to standard | | `error` | Parse/fetch failure | ❌ Red error | Fix URI/data | ## Migration Guide ### From Groth16 to ERC-8004 Standard **Minimal Upgrade** (wrap existing proof): ```json { "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "zkmlProof": { "proof": { "pi_a": [...], "pi_b": [...], "pi_c": [...], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "circuit": "zyfi-rebalancing-validation" } } ``` **Full Upgrade** (use attachments): ```json { "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "reasoning": "Agent rebalancing validated via zkSNARK", "attachments": [ { "name": "Groth16 Proof", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "ZyFi rebalancing validation proof" } ] } ``` ## Examples ### Example 1: zkML Validation Request ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "reasoning": "Validate agent's portfolio rebalancing algorithm", "deadline": "2025-12-21T05:00:38Z", "zkmlRequest": { "circuit": "zyfi-rebalancing-validation", "publicInputs": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c" } } ``` ### Example 2: Validation Response with Groth16 Proof ```json { "requestHash": "0x5c1a08c66c0489030f05990a83534280ee08da7cd944dc353bf4b661c5c96657", "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "agentId": 56, "response": 100, "createdAt": "2025-12-20T06:00:00Z", "tag": "zkml-proof", "result": "passed", "reasoning": "Agent rebalancing logic validated. All test cases passed.", "confidence": 0.95, "zkmlProof": { "proof": { "pi_a": [...], "pi_b": [...], "pi_c": [...], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifiedAt": "2025-12-20T05:45:00Z" } } ``` ## FAQ ### Q: How are Validation Registry contracts upgraded (v1.1 and beyond)? **A**: ERC-8004 uses the UUPS (Universal Upgradeable Proxy Standard) pattern for safe upgrades: ```solidity // Current deployment (v1.1) address proxyAddress = 0x...; // Permanent address address implV1 = 0x...; // v1.1 implementation // When upgrading to v1.1+ address implV2 = 0x...; // New implementation // Owner calls: proxy.upgradeTo(implV2) // Users continue using same proxy address (0x...) ``` **Key guarantees**: 1. **Permanent address**: The proxy address never changes * All validation records reference fixed registry address * Off-chain indexers continue working without migration 2. **Storage layout preservation**: Upgrades MUST NOT change field order * Existing validation records remain valid * New fields added at end only 3. **Event compatibility**: New events additive only * Old indexers continue processing events * New indexers see full history 4. **Backwards compatibility**: Function signatures stable * `recordValidation()` signature guaranteed across upgrades * New features added via new functions **For indexers**: * Continue listening to same contract address * New validation types appear in events * Old validation records accessible via historical queries * No need to re-index on upgrade **For validators**: * URI format (`requestUri`, `responseUri`) is stable * Off-chain data format guidelines (this document) apply across versions * Submit validation responses to same contract address always *** ## See Also * [Feedback Standard](02-feedback-standard.md) - Reputation Registry offchain data format * [Agent Metadata Standard](01-agent-metadata-standard.md) - AgentURI metadata format * [Validation Best Practices](implementation/validation-best-practices.md) - Implementation guide * [Sources & References](reference/sources.md) - Methodology and data sources --- --- url: /docs/implementation/agent-metadata-parsing.md description: Practical guide for parsing ERC-8004 agent metadata --- ## Description Practical guide for parsing ERC-8004 agent metadata **Audience**: Backend developers, indexer authors, explorer builders ## Overview This guide provides practical instructions for implementing a robust ERC-8004 agent metadata parser that handles real-world data patterns. **What You'll Learn**: * βœ… Parse 7 URI formats (IPFS, HTTP, Data URI variants) * βœ… Handle malformed metadata gracefully * βœ… Extract structured data (services, OASF skills, wallets) * βœ… Validate against ERC-8004 standard * βœ… Generate helpful warnings for developers ## Parser Architecture ### High-Level Flow ```text Input: agentURI string ↓ 1. URI Format Detection β”œβ”€ Data URI (base64) β†’ decode base64 β†’ parse JSON β”œβ”€ Data URI (plain) β†’ URL decode β†’ parse JSON β”œβ”€ IPFS URI β†’ fetch from gateway β†’ parse JSON β”œβ”€ HTTP(S) URL β†’ fetch β†’ parse JSON └─ Plain JSON β†’ parse directly ↓ 2. JSON Parsing & Validation β”œβ”€ Check required fields (type, name, description, image) β”œβ”€ Validate services array structure └─ Collect warnings for non-critical issues ↓ 3. Structured Data Extraction β”œβ”€ Extract service URLs by type (MCP, A2A, OASF, wallet) β”œβ”€ Parse OASF skills and domains └─ Extract metadata for storage ↓ Output: { metadata, warnings[], status } ``` ### 5-Level Validation System ```text Level 1: Syntax β†’ Can we parse the URI and JSON? Level 2: Schema β†’ Does it have required fields? Level 3: Service β†’ Are services valid and reachable? Level 4: Semantic β†’ Do values make sense (CAIP formats, versions)? Level 5: Status β†’ Is the agent active and operational? ``` ## URI Format Parsers ### 1. Data URI (Base64) **Format**: `data:application/json;base64,` **Logic**: ```plaintext IF uri starts with "data:application/json;base64," THEN encoded ← extract data (remove "data:application/json;base64," prefix) // Edge case: ChaosChain pattern (claimed base64 but plain JSON) IF encoded starts with "{" THEN ADD_WARNING("base64_uri_with_plain_json") RETURN parse JSON from encoded END IF decoded ← base64 decode(encoded) RETURN parse JSON from decoded END IF ``` **Production Stats** (8004scan, Dec 2025): * **18%** of agents use base64 data URIs * **~5%** have the ChaosChain pattern (claimed base64 but plain JSON) ### 2. Data URI (Plain) **Format**: `data:application/json,` **Logic**: ```plaintext IF uri starts with "data:application/json," THEN data ← extract data (remove "data:application/json," prefix) // Some URIs are URL-encoded IF data contains "%" THEN data ← URL decode(data) ADD_WARNING("url_encoded_json") END IF RETURN parse JSON from data END IF ``` ### 3. IPFS URIs **Format**: `ipfs://` or `ipfs:///path` **Logic**: ```plaintext CONSTANTS: GATEWAYS ← [ "https://ipfs.io/ipfs/{}", "https://cloudflare-ipfs.com/ipfs/{}", "https://gateway.pinata.cloud/ipfs/{}" ] ALGORITHM: FetchIPFS(uri) INPUT: uri - IPFS URI string OUTPUT: JSON object or NULL BEGIN cid ← extract CID from uri (remove "ipfs://" prefix) FOR EACH gateway IN GATEWAYS DO url ← format gateway with cid TRY response ← HTTP GET(url, timeout: 5 seconds) IF response is successful THEN RETURN parse JSON from response END IF CATCH network error CONTINUE to next gateway END TRY END FOR ADD_ERROR("ipfs_fetch_failed") RETURN NULL END ``` **Production Stats**: * **51%** of agents use IPFS URIs * Gateway fallback is essential (success rate: ~95%) ### 4. HTTP/HTTPS URLs **Logic**: ```plaintext ALGORITHM: FetchHTTP(uri) INPUT: uri - HTTP(S) URL string OUTPUT: JSON object or NULL BEGIN IF uri starts with "http://" THEN ADD_WARNING("http_not_https") // Security warning END IF TRY response ← HTTP GET(uri, timeout: 5 seconds) IF response is successful THEN RETURN parse JSON from response ELSE ADD_ERROR("http_status_" + response.status_code) RETURN NULL END IF CATCH timeout error ADD_ERROR("http_timeout") RETURN NULL CATCH network error ADD_ERROR("http_error") RETURN NULL END TRY END ``` **Production Stats**: * **22%** of agents use HTTP(S) URLs * Timeout issues: ~8% of HTTP URIs ### 5. Plain JSON Fallback **Logic**: ```plaintext IF uri starts with "{" THEN ADD_WARNING("plain_json_without_uri_scheme") RETURN parse JSON from uri END IF ``` ## Schema Validation ### Required Fields ```plaintext CONSTANTS: REQUIRED ← {"type", "name", "description", "image"} ALGORITHM: ValidateRequired(metadata) INPUT: metadata - JSON object OUTPUT: warnings list BEGIN warnings ← empty list missing ← REQUIRED fields not present in metadata FOR EACH field IN missing DO ADD warnings("missing_required_" + field) END FOR IF metadata.type β‰  "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" THEN ADD warnings("invalid_type_field") END IF RETURN warnings END ``` ### Services Validation ```plaintext ALGORITHM: ValidateServices(metadata) INPUT: metadata - JSON object OUTPUT: warnings list BEGIN warnings ← empty list // Support both "services" (new) and "endpoints" (legacy) services ← get "services" from metadata OR get "endpoints" from metadata // Emit warning if using legacy field name IF metadata contains "endpoints" AND metadata does not contain "services" THEN ADD warnings("WA031: using legacy 'endpoints' field") END IF // Common typo: "endpoint" (singular) IF metadata contains "endpoint" AND services is null THEN ADD warnings("typo_endpoint_singular") RETURN warnings END IF IF services is null THEN ADD warnings("missing_services") ELSE IF services is not an array THEN ADD warnings("services_not_array") ELSE IF services is empty THEN ADD warnings("empty_services") // Agent not reachable ELSE FOR EACH service IN services DO warnings ← warnings + ValidateService(service) END FOR END IF RETURN warnings END ``` ### Service-Specific Validation ```plaintext ALGORITHM: ValidateService(service) INPUT: service - JSON object OUTPUT: warnings list BEGIN warnings ← empty list name ← service.name CASE name OF "MCP": IF service.endpoint is empty THEN ADD warnings("mcp_missing_endpoint") END IF IF service.version β‰  "2025-06-18" THEN ADD warnings("mcp_nonstandard_version") END IF "A2A": IF service.endpoint is empty THEN ADD warnings("a2a_missing_endpoint") END IF IF service.version NOT IN ["0.3.0", "0.30"] THEN ADD info("a2a_nonstandard_version") // SHOULD, not MUST per spec END IF IF service.endpoint does not contain ".well-known/agent-card.json" THEN ADD info("a2a_missing_well_known") // Recommended path, not required END IF "OASF": IF service.skills is empty AND service.domains is empty THEN ADD warnings("oasf_empty") END IF warnings ← warnings + ValidateOASFSkills(service.skills) warnings ← warnings + ValidateOASFDomains(service.domains) "agentWallet": IF NOT IsValidCAIP10(service.endpoint) THEN ADD warnings("wallet_invalid_format") END IF END CASE RETURN warnings END ``` ### CAIP Format Validation ```plaintext ALGORITHM: IsValidCAIP2(value) INPUT: value - string to validate OUTPUT: boolean (true if valid, false otherwise) BEGIN // Format: namespace:chainId:0xAddress pattern ← "^[a-z][-a-z0-9]{0,31}:[0-9]+:0x[a-fA-F0-9]{40}$" RETURN value matches pattern END ALGORITHM: IsValidCAIP10(value) INPUT: value - string to validate OUTPUT: boolean BEGIN // Format: namespace:chainId:accountAddress (same as CAIP-2) RETURN IsValidCAIP2(value) END Examples: βœ“ "eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847" βœ— "eip155:0x8004..." (missing chainId) βœ— "0x8004..." (missing namespace) ``` ## Data Extraction ### Structured Data Extraction ```plaintext ALGORITHM: ExtractAgentData(metadata) INPUT: metadata - validated JSON object OUTPUT: structured data record BEGIN data ← new record // Basic fields data.name ← metadata.name data.description ← metadata.description data.image_url ← metadata.image data.active ← metadata.active OR false (if not present) data.x402_support ← metadata.x402Support OR false (if not present) data.updated_at ← metadata.updatedAt // Services (find by name in services array) data.mcp_server ← FindService(metadata.services, "MCP").endpoint data.a2a_endpoint ← FindService(metadata.services, "A2A").endpoint data.agent_wallet ← FindService(metadata.services, "agentWallet").endpoint data.ens ← FindService(metadata.services, "ENS").endpoint data.did ← FindService(metadata.services, "DID").endpoint // OASF data oasfService ← FindService(metadata.services, "OASF") data.oasf_skills ← oasfService.skills OR empty list data.oasf_domains ← oasfService.domains OR empty list // Full metadata for backup data.metadata_json ← metadata RETURN data END ``` ## Complete Parser Implementation ### Core Parser Algorithm ```plaintext ALGORITHM: ParseAgentMetadata(uri) INPUT: uri - string containing agent metadata URI OUTPUT: (metadata, warnings[], status) or NULL BEGIN errors ← empty list warnings ← empty list // Step 1: Parse URI to JSON metadata ← ParseURI(uri) IF metadata = NULL THEN RETURN NULL END IF // Step 2: Validate schema warnings ← warnings + ValidateRequired(metadata) warnings ← warnings + ValidateServices(metadata) // Step 3: Determine status IF errors is not empty THEN status ← "error" ELSE IF warnings is not empty THEN status ← "warning" ELSE status ← "success" END IF RETURN (metadata, warnings, status) END ALGORITHM: ParseURI(uri) INPUT: uri - string OUTPUT: JSON object or NULL BEGIN // Try formats in order of frequency // Data URIs (36% of agents) - fastest to parse IF uri starts with "data:" THEN metadata ← TryDataURI(uri) IF metadata β‰  NULL THEN RETURN metadata END IF END IF // IPFS (51% of agents) - requires network fetch IF uri starts with "ipfs://" THEN metadata ← FetchIPFS(uri) IF metadata β‰  NULL THEN RETURN metadata END IF END IF // HTTP(S) (22% of agents) - requires network fetch IF uri starts with "http" THEN metadata ← FetchHTTP(uri) IF metadata β‰  NULL THEN RETURN metadata END IF END IF // Plain JSON fallback (edge case) IF uri starts with "{" THEN ADD_WARNING("plain_json_without_uri_scheme") RETURN ParseJSON(uri) END IF ADD_ERROR("unsupported_uri_format") RETURN NULL END ALGORITHM: ValidateRequired(metadata) INPUT: metadata - JSON object OUTPUT: warnings list BEGIN warnings ← empty list required ← {"type", "name", "description", "image"} FOR EACH field IN required DO IF field not in metadata THEN ADD warnings("missing_required_" + field) END IF END FOR IF metadata.type β‰  "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" THEN ADD warnings("invalid_type_field") END IF RETURN warnings END ``` ### Usage Pattern ```plaintext MAIN Program: // Parse agent metadata uri ← GetAgentURI(agentId) result ← ParseAgentMetadata(uri) IF result β‰  NULL THEN (metadata, warnings, status) ← result // Extract structured data agentData ← ExtractAgentData(metadata) agentData.parse_status ← status agentData.parse_warnings ← warnings // Store in database StoreAgent(agentData) OUTPUT "Success: " + status ELSE OUTPUT "Parse failed" END IF END ``` ## Performance Optimization ### Caching Strategy ```text 1. Data URI Caching (in-memory LRU) - Data URIs are immutable β†’ safe to cache forever - Use LRU cache with 1000 entry limit - Cache hit rate: ~40% in production 2. IPFS Caching (Redis, 1 hour TTL) - Cache key: sha256(ipfs_uri) - Reduces gateway load by 85% - TTL: 3600s (content rarely changes) 3. HTTP Caching (Redis, 5 minute TTL) - Cache key: sha256(http_url) - Respects Cache-Control headers - TTL: 300s (content may update) ``` ### Batch Processing ```plaintext ALGORITHM: ParseAgentBatch(uris) INPUT: uris - list of URI strings OUTPUT: list of parse results BEGIN results ← empty list // Process URIs in parallel FOR EACH uri IN uris (in parallel) DO result ← ParseAgentMetadata(uri) ADD result to results END FOR RETURN results END Note: Typical throughput: 100-200 agents/second (with caching) ``` ## Common Issues & Solutions ### Issue 1: Empty Services Array **Pattern**: `{"services": []}` (or legacy `{"endpoints": []}`) **Impact**: Agent not reachable, but metadata is valid **Solution**: Warn but don't fail validation ```plaintext IF services is empty THEN ADD_WARNING("empty_services") // Still store agent, may be pre-registration END IF ``` **Production Stats**: ~15% of agents have empty services ### Issue 2: Null agentId in Registrations **Pattern**: `{"registrations": [{"agentId": null}]}` **Context**: Common during registration flow (agentId assigned after transaction) **Solution**: Accept and log as info (not warning) ```plaintext IF registration.agentId is null THEN ADD_INFO("registration_null_agent_id") // Expected for first-time deployments; will be updated after transaction confirms END IF ``` **Rationale**: This is expected behavior, not a problem. First-time deployments don't know their tokenId until the on-chain transaction confirms. **Production Stats**: ~30% of initial registrations have null agentId ### Issue 3: Version Number Variations **Pattern**: A2A version `"0.30"` instead of `"0.3.0"` **Solution**: Accept both formats ```plaintext CONSTANTS: VALID_A2A_VERSIONS ← ["0.3.0", "0.30"] IF endpoint.version IN VALID_A2A_VERSIONS THEN IF endpoint.version = "0.30" THEN ADD_WARNING("a2a_version_typo") // Inform but accept END IF END IF ``` ## Validation Error Codes > **8004scan-specific**: The following error codes are used by 8004scan's validation system. Other implementations MAY use different codes. ### Severity Levels 8004scan uses three severity levels following RFC 2119/8174: | Level | Description | Action | | ----------- | ------------------------------------------------ | -------------- | | **Error** | Critical issues preventing proper functioning | Parse fails | | **Warning** | Functional issues but not critical | Parse succeeds | | **Info** | Recommendations, expected states, best practices | Advisory only | ### Level 1: Syntax Validation **Errors** (Parse Fails): | Issue | Error Code | | ------------------- | ------------------- | | Empty URI | `empty_uri` | | Invalid JSON syntax | `invalid_json` | | Invalid base64 | `invalid_base64` | | Non-dict root | `invalid_root_type` | **Warnings** (Parse Succeeds): | Issue | Warning Code | | -------------------------- | ------------------------------- | | Plain JSON without scheme | `plain_json_without_uri_scheme` | | base64 URI with plain JSON | `base64_uri_with_plain_json` | | URL-encoded JSON | `url_encoded_json` | ### Level 2: Schema Validation **Critical Warnings** (Likely to cause display issues): | Issue | Warning Code | Severity | | --------------------- | ------------------------------ | -------- | | Missing `type` | `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 | | Empty `services` | `empty_services` | Medium | **Standard Warnings**: | Issue | Warning Code | | ----------------------------------------- | -------------------------------- | | `endpoint` instead of `services` | `typo_endpoint_singular` | | `registration` instead of `registrations` | `typo_registration_singular` | | `registrations[].agentId` mismatch | `registration_agent_id_mismatch` | | Invalid CAIP-2 format | `invalid_caip2_format` | | Invalid CAIP-10 format | `invalid_caip10_format` | **Info Messages** (Expected states, recommendations): | Issue | Info Code | | ----------------------------------- | ---------------------------- | | `registrations[].agentId` is `null` | `registration_null_agent_id` | | Missing `registrations` array | `missing_registrations` | | Empty `registrations` array | `empty_registrations` | ### Level 3: Service Validation **MCP Service**: | Issue | Code | Severity | | -------------------- | ------------------------- | -------- | | Missing `endpoint` | `mcp_missing_endpoint` | Warning | | Missing `version` | `mcp_missing_version` | Info | | Non-standard version | `mcp_nonstandard_version` | Info | > **Note**: Per ERC-8004 spec: "The version field in services is a SHOULD, not a MUST." **A2A Service**: | Issue | Code | Severity | | -------------------------- | ------------------------- | -------- | | Missing `endpoint` | `a2a_missing_endpoint` | Warning | | Missing `version` | `a2a_missing_version` | Info | | Non-standard version | `a2a_nonstandard_version` | Info | | Missing `.well-known` path | `a2a_missing_well_known` | Info | > **Note**: A2A `.well-known/agent-card.json` path is shown as an example in ERC-8004, not a requirement. Other paths are valid. **OASF Service**: | Issue | Warning Code | | ----------------------------------- | -------------------------- | | Missing both `skills` and `domains` | `oasf_empty` | | Invalid skill slug | `oasf_invalid_skill` | | Invalid domain slug | `oasf_invalid_domain` | | Non-standard version | `oasf_nonstandard_version` | **agentWallet Service**: | Issue | Warning Code | | ---------------------- | ------------------------- | | Invalid CAIP-10 format | `wallet_invalid_format` | | Invalid checksum | `wallet_invalid_checksum` | ### Level 4: Semantic Validation **Trust Models**: | Issue | Warning Code | | ---------------------- | ----------------------- | | Unknown trust model | `unknown_trust_model` | | Empty `supportedTrust` | `empty_supported_trust` | **Known trust models**: `"reputation"`, `"crypto-economic"`, `"tee-attestation"`, `"social-graph"` **agentHash Verification** (8004scan Extension): | Issue | Warning Code | Severity | | ----------------------------------- | ---------------------- | -------- | | Hash mismatch (onchain vs computed) | `agent_hash_mismatch` | Warning | | HTTP/HTTPS URI without agentHash | `agent_uri_not_hashed` | Info | > **Note**: `agentHash` verification only applies to HTTP/HTTPS URIs. IPFS/Arweave are content-addressed. ### Level 5: Status Fields | Issue | Warning Code | | ---------------------- | ------------------------ | | `active: false` | `agent_not_active` | | Invalid boolean values | `invalid_boolean_active` | ## Production Statistics **Data Source**: 8004scan Production (Base Sepolia), December 2025, 4,725 agents ### URI Format Distribution * **IPFS**: 51% (`ipfs://CID`) * **HTTP(S)**: 22% (`https://...`) * **Data URI (base64)**: 18% (`data:application/json;base64,...`) * **Other**: 9% (plain JSON, Arweave, etc.) ### Service Adoption * **A2A**: 85% of agents * **MCP**: 75% of agents * **OASF**: 60% of agents * **agentWallet**: 45% of agents ### Parse Success Rates * **Perfect (no warnings)**: 58.1% * **Success with warnings**: 11.8% * **Total success**: 69.9% * **Common issues**: Empty services (~15%), null agentId (~30%) ### Top OASF Skills 1. `communication_skills/content_creation` (18%) 2. `analytical_skills/data_analysis` (15%) 3. `technical_skills/software_development` (12%) 4. `problem_solving/strategic_thinking` (10%) 5. `specialized_skills/blockchain_expertise` (8%) ## Resources * [Agent Metadata Standard](../01-agent-metadata-standard.md) - Full schema specification * [CAIP-2 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) - Blockchain ID format * [CAIP-10 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) - Account address format * [OASF Taxonomy](https://github.com/agntcy/oasf/) - Skills and domains reference --- --- url: /legacy-pre-v1/docs/implementation/agent-metadata-parsing.md description: Practical guide for parsing ERC-8004 agent metadata --- ## Description Practical guide for parsing ERC-8004 agent metadata **Audience**: Backend developers, indexer authors, explorer builders ## Overview This guide provides practical instructions for implementing a robust ERC-8004 agent metadata parser that handles real-world data patterns. **What You'll Learn**: * βœ… Parse 7 URI formats (IPFS, HTTP, Data URI variants) * βœ… Handle malformed metadata gracefully * βœ… Extract structured data (endpoints, OASF skills, wallets) * βœ… Validate against ERC-8004 standard * βœ… Generate helpful warnings for developers ## Quick Start ### Minimal Parser (5 Steps) ```python import json import base64 from urllib.parse import unquote def parse_metadata(uri: str) -> dict | None: """Minimal ERC-8004 metadata parser""" # Step 1: Try Data URI (base64) if uri.startswith("data:application/json;base64,"): encoded = uri.replace("data:application/json;base64,", "") # Handle edge case: claimed base64 but plain JSON if encoded.startswith("{"): return json.loads(encoded) decoded = base64.b64decode(encoded).decode("utf-8") return json.loads(decoded) # Step 2: Try Data URI (plain) if uri.startswith("data:application/json,"): data = uri.replace("data:application/json,", "") data = unquote(data) # Handle URL encoding return json.loads(data) # Step 3: Try plain JSON (fallback) if uri.startswith("{"): return json.loads(uri) # Step 4: Fetch from IPFS/HTTP (not shown, use requests/httpx) # ... return None ``` **Usage**: ```python metadata = parse_metadata(agent_uri) if metadata: name = metadata.get("name") endpoints = metadata.get("endpoints", []) ``` ## URI Format Parsers ### 1. Data URI (Base64) **Format**: `data:application/json;base64,` **Implementation**: ```python def parse_data_uri_base64(uri: str) -> tuple[dict | None, list[str]]: """Parse base64 data URI with error collection""" warnings = [] if not uri.startswith("data:application/json;base64,"): return None, warnings encoded_data = uri.replace("data:application/json;base64,", "") # Edge case: ChaosChain pattern (claimed base64 but plain JSON) if encoded_data.startswith("{") or encoded_data.startswith("["): warnings.append("base64_uri_with_plain_json") return json.loads(encoded_data), warnings try: decoded_bytes = base64.b64decode(encoded_data) decoded_str = decoded_bytes.decode("utf-8") metadata = json.loads(decoded_str) return metadata, warnings except base64.binascii.Error: warnings.append("invalid_base64_encoding") return None, warnings except UnicodeDecodeError: warnings.append("base64_decode_utf8_error") return None, warnings except json.JSONDecodeError: warnings.append("base64_invalid_json") return None, warnings ``` **Real-World Example**: ```python # Standard base64 uri1 = "data:application/json;base64,eyJ0eXBlIjoiaHR0cHM6Ly9laXBzLmV0aGVyZXVtLm9yZy9FSVBTL2VpcC04MDA0I3JlZ2lzdHJhdGlvbi12MSIsIm5hbWUiOiJBZ2VudCJ9" metadata, warnings = parse_data_uri_base64(uri1) # Returns: {"type": "https://...", "name": "Agent"}, [] # Edge case: claimed base64 but plain JSON uri2 = 'data:application/json;base64,{"type":"https://...","name":"Agent"}' metadata, warnings = parse_data_uri_base64(uri2) # Returns: {"type": "https://...", "name": "Agent"}, ["base64_uri_with_plain_json"] ``` ### 2. Data URI (Plain) **Format**: `data:application/json,` **Implementation**: ```python def parse_data_uri_plain(uri: str) -> tuple[dict | None, list[str]]: """Parse plain data URI with URL decoding""" warnings = [] if not uri.startswith("data:application/json,"): return None, warnings data = uri.replace("data:application/json,", "") # Try URL decoding (some URIs are URL-encoded) try: decoded = unquote(data) if decoded != data: warnings.append("url_decoded_plain_uri") data = decoded except Exception: pass try: metadata = json.loads(data) return metadata, warnings except json.JSONDecodeError: warnings.append("plain_uri_invalid_json") return None, warnings ``` **Real-World Example**: ```python # Standard plain uri1 = 'data:application/json,{"type":"https://...","name":"Agent"}' metadata, warnings = parse_data_uri_plain(uri1) # Returns: {"type": "https://...", "name": "Agent"}, [] # URL-encoded plain uri2 = 'data:application/json,%7B%22type%22%3A%22https%3A%2F%2F...%22%7D' metadata, warnings = parse_data_uri_plain(uri2) # Returns: {"type": "https://..."}, ["url_decoded_plain_uri"] ``` ### 3. IPFS URIs **Format**: `ipfs://CID` or `ipfs://CID/path` **Implementation**: ```python import httpx IPFS_GATEWAYS = [ "https://ipfs.io/ipfs/{}", "https://cloudflare-ipfs.com/ipfs/{}", "https://gateway.pinata.cloud/ipfs/{}", ] async def fetch_ipfs(uri: str, timeout: int = 5) -> tuple[dict | None, list[str]]: """Fetch IPFS content with gateway fallback""" warnings = [] if not uri.startswith("ipfs://"): return None, warnings cid_with_path = uri.replace("ipfs://", "") async with httpx.AsyncClient(timeout=timeout) as client: for gateway_template in IPFS_GATEWAYS: gateway_url = gateway_template.format(cid_with_path) try: response = await client.get(gateway_url) if response.status_code == 200: metadata = response.json() return metadata, warnings except Exception: continue warnings.append("ipfs_fetch_failed") return None, warnings ``` **Real-World Example**: ```python uri = "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4" metadata, warnings = await fetch_ipfs(uri) # Returns: {metadata dict}, [] or [], ["ipfs_fetch_failed"] ``` ### 4. HTTP/HTTPS URLs **Implementation**: ```python async def fetch_http(uri: str, timeout: int = 5) -> tuple[dict | None, list[str]]: """Fetch HTTP(S) content""" warnings = [] if not (uri.startswith("http://") or uri.startswith("https://")): return None, warnings if uri.startswith("http://"): warnings.append("http_not_https") async with httpx.AsyncClient(timeout=timeout) as client: try: response = await client.get(uri) if response.status_code == 200: metadata = response.json() return metadata, warnings else: warnings.append(f"http_status_{response.status_code}") return None, warnings except httpx.TimeoutException: warnings.append("http_timeout") return None, warnings except Exception as e: warnings.append(f"http_error_{type(e).__name__}") return None, warnings ``` ## Schema Validation ### Required Fields Checker ```python REQUIRED_FIELDS = {"type", "name", "description", "image"} def validate_required_fields(metadata: dict) -> list[str]: """Check for missing required fields""" warnings = [] missing = REQUIRED_FIELDS - set(metadata.keys()) if missing: for field in sorted(missing): warnings.append(f"missing_required_{field}") # Validate type field value expected_type = "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" if metadata.get("type") != expected_type: warnings.append("invalid_type_field") return warnings ``` ### Endpoint Validation ```python def validate_endpoints(metadata: dict) -> list[str]: """Validate endpoints array structure and contents""" warnings = [] # Check for common typo if "endpoint" in metadata and "endpoints" not in metadata: warnings.append("typo_endpoint_singular") return warnings endpoints = metadata.get("endpoints") if endpoints is None: warnings.append("missing_endpoints") return warnings if not isinstance(endpoints, list): warnings.append("endpoints_not_array") return warnings if len(endpoints) == 0: warnings.append("empty_endpoints") return warnings # Validate each endpoint for i, endpoint in enumerate(endpoints): name = endpoint.get("name") if name == "MCP": warnings.extend(validate_mcp_endpoint(endpoint, i)) elif name == "A2A": warnings.extend(validate_a2a_endpoint(endpoint, i)) elif name == "OASF": warnings.extend(validate_oasf_endpoint(endpoint, i)) elif name == "agentWallet": warnings.extend(validate_wallet_endpoint(endpoint, i)) return warnings ``` ### MCP Endpoint Validation ```python def validate_mcp_endpoint(endpoint: dict, index: int) -> list[str]: """Validate MCP endpoint structure""" warnings = [] if "endpoint" not in endpoint: warnings.append(f"mcp_missing_endpoint_at_{index}") elif not endpoint["endpoint"]: warnings.append(f"mcp_empty_endpoint_at_{index}") if "version" not in endpoint: warnings.append(f"mcp_missing_version_at_{index}") elif endpoint["version"] != "2025-06-18": warnings.append(f"mcp_nonstandard_version_at_{index}") return warnings ``` ### A2A Endpoint Validation ```python def validate_a2a_endpoint(endpoint: dict, index: int) -> list[str]: """Validate A2A endpoint structure""" warnings = [] if "endpoint" not in endpoint: warnings.append(f"a2a_missing_endpoint_at_{index}") elif not endpoint["endpoint"]: warnings.append(f"a2a_empty_endpoint_at_{index}") if "version" not in endpoint: warnings.append(f"a2a_missing_version_at_{index}") elif endpoint["version"] not in ["0.3.0", "0.30"]: # Allow common typo warnings.append(f"a2a_nonstandard_version_at_{index}") # Check for .well-known path endpoint_url = endpoint.get("endpoint", "") if endpoint_url and ".well-known/agent-card.json" not in endpoint_url: warnings.append(f"a2a_missing_well_known_at_{index}") return warnings ``` ### CAIP Format Validation ```python import re def validate_caip2(value: str) -> bool: """Validate CAIP-2 format: namespace:chainId:reference""" pattern = r'^[a-z][-a-z0-9]{0,31}:[0-9]+:0x[a-fA-F0-9]{40}$' return bool(re.match(pattern, value)) def validate_caip10(value: str) -> bool: """Validate CAIP-10 format: namespace:chainId:accountAddress""" pattern = r'^[a-z][-a-z0-9]{0,31}:[0-9]+:0x[a-fA-F0-9]{40}$' return bool(re.match(pattern, value)) def validate_wallet_endpoint(endpoint: dict, index: int) -> list[str]: """Validate agentWallet endpoint""" warnings = [] wallet_address = endpoint.get("endpoint", "") if not validate_caip10(wallet_address): warnings.append(f"wallet_invalid_format_at_{index}") return warnings ``` **Examples**: ```python validate_caip2("eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847") # True validate_caip2("eip155:0x8004...") # False (missing chainId) validate_caip10("eip155:11155111:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7") # True ``` ## Field Extraction ### Extract Structured Data ```python def extract_agent_data(metadata: dict) -> dict: """Extract structured data for database storage""" # Basic fields data = { "name": metadata.get("name"), "description": metadata.get("description"), "image_url": metadata.get("image"), "active": metadata.get("active", False), "x402_support": metadata.get("x402support", False), "updated_at": metadata.get("updatedAt"), } # Extract endpoints endpoints = metadata.get("endpoints", []) data["mcp_server"] = extract_endpoint_value(endpoints, "MCP") data["a2a_endpoint"] = extract_endpoint_value(endpoints, "A2A") data["agent_wallet"] = extract_endpoint_value(endpoints, "agentWallet") data["ens"] = extract_endpoint_value(endpoints, "ENS") data["did"] = extract_endpoint_value(endpoints, "DID") # Extract OASF data oasf_endpoint = next((e for e in endpoints if e.get("name") == "OASF"), None) if oasf_endpoint: data["oasf_skills"] = oasf_endpoint.get("skills", []) data["oasf_domains"] = oasf_endpoint.get("domains", []) # Store full metadata data["metadata_json"] = metadata return data def extract_endpoint_value(endpoints: list, name: str) -> str | None: """Extract endpoint URL by name""" endpoint = next((e for e in endpoints if e.get("name") == name), None) return endpoint.get("endpoint") if endpoint else None ``` **Usage**: ```python metadata = parse_metadata(uri) agent_data = extract_agent_data(metadata) # Store in database await db.execute( """ INSERT INTO agents (name, description, image_url, mcp_server, ...) VALUES (:name, :description, :image_url, :mcp_server, ...) """, agent_data ) ``` ## Complete Parser Example ```python class AgentMetadataParser: """Complete ERC-8004 agent metadata parser""" def __init__(self): self.errors = [] self.warnings = [] async def parse(self, uri: str) -> dict | None: """Parse agent metadata from URI""" self.errors = [] self.warnings = [] # Try data URI formats first (fastest) metadata = self._try_data_uris(uri) # Fetch from remote if needed if metadata is None: metadata = await self._try_remote_fetch(uri) # Validate if parsed successfully if metadata: self._validate(metadata) return metadata def _try_data_uris(self, uri: str) -> dict | None: """Try all data URI formats""" # Base64 metadata, warnings = parse_data_uri_base64(uri) self.warnings.extend(warnings) if metadata: return metadata # Plain metadata, warnings = parse_data_uri_plain(uri) self.warnings.extend(warnings) if metadata: return metadata # Plain JSON fallback if uri.startswith("{"): try: metadata = json.loads(uri) self.warnings.append("plain_json_without_uri_scheme") return metadata except json.JSONDecodeError: pass return None async def _try_remote_fetch(self, uri: str) -> dict | None: """Fetch from IPFS/HTTP/Arweave""" # IPFS if uri.startswith("ipfs://"): metadata, warnings = await fetch_ipfs(uri) self.warnings.extend(warnings) return metadata # HTTP(S) if uri.startswith("http://") or uri.startswith("https://"): metadata, warnings = await fetch_http(uri) self.warnings.extend(warnings) return metadata # Arweave if uri.startswith("ar://"): # Similar to IPFS pass self.errors.append("unsupported_uri_format") return None def _validate(self, metadata: dict): """Validate metadata and collect warnings""" self.warnings.extend(validate_required_fields(metadata)) self.warnings.extend(validate_endpoints(metadata)) # ... other validations def get_status(self) -> str: """Get parse status""" if self.errors: return "error" elif self.warnings: return "warning" else: return "success" ``` **Usage**: ```python parser = AgentMetadataParser() metadata = await parser.parse(agent_uri) if metadata: agent_data = extract_agent_data(metadata) agent_data["parse_status"] = parser.get_status() agent_data["parse_warnings"] = parser.warnings # Store in database else: print(f"Parse failed: {parser.errors}") ``` ## Testing ### Unit Tests ```python import pytest @pytest.mark.asyncio async def test_parse_base64_data_uri(): """Test base64 data URI parsing""" uri = "data:application/json;base64,eyJ0eXBlIjoiaHR0cHM6Ly9laXBzLmV0aGVyZXVtLm9yZy9FSVBTL2VpcC04MDA0I3JlZ2lzdHJhdGlvbi12MSIsIm5hbWUiOiJUZXN0In0=" parser = AgentMetadataParser() metadata = await parser.parse(uri) assert metadata is not None assert metadata["type"] == "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" assert metadata["name"] == "Test" assert parser.get_status() == "warning" # Missing description, image @pytest.mark.asyncio async def test_parse_chaoschain_edge_case(): """Test ChaosChain pattern (claimed base64 but plain JSON)""" uri = 'data:application/json;base64,{"type":"https://eips.ethereum.org/EIPS/eip-8004#registration-v1","name":"Bob"}' parser = AgentMetadataParser() metadata = await parser.parse(uri) assert metadata is not None assert metadata["name"] == "Bob" assert "base64_uri_with_plain_json" in parser.warnings ``` ## Performance Optimization ### Caching ```python from functools import lru_cache import hashlib @lru_cache(maxsize=1000) def parse_data_uri_cached(uri: str) -> tuple[dict | None, tuple]: """Cache parsed data URIs (immutable)""" metadata, warnings = parse_data_uri_base64(uri) if metadata is None: metadata, warnings = parse_data_uri_plain(uri) return metadata, tuple(warnings) async def fetch_ipfs_cached(uri: str) -> dict | None: """Cache IPFS fetches using Redis""" cache_key = f"ipfs:{hashlib.sha256(uri.encode()).hexdigest()}" # Try cache cached = await redis.get(cache_key) if cached: return json.loads(cached) # Fetch and cache metadata, _ = await fetch_ipfs(uri) if metadata: await redis.setex(cache_key, 3600, json.dumps(metadata)) return metadata ``` ## Common Issues ### Issue 1: Empty Endpoints Array **Pattern**: ```json { "endpoints": [] } ``` **Fix**: Warn but don't fail ```python if len(endpoints) == 0: warnings.append("empty_endpoints") # Agent not reachable, but metadata is valid ``` ### Issue 2: Null agentId in Registrations **Pattern**: ```json { "registrations": [{ "agentId": null, "agentRegistry": "eip155:..." }] } ``` **Context**: Common during registration flow (agentId assigned after) **Fix**: Warn but store ```python if registration.get("agentId") is None: warnings.append("registration_null_agent_id") # Still store, will be updated later ``` ### Issue 3: Version Number Variations **Pattern**: ```json { "name": "A2A", "version": "0.30" } // Should be "0.3.0" ``` **Fix**: Accept both, prefer standard ```python if endpoint["version"] in ["0.3.0", "0.30"]: # Accept both if endpoint["version"] == "0.30": warnings.append("a2a_version_typo") ``` ## Resources * [Agent Metadata Standard](../01-agent-metadata-standard.md) * [CAIP-2 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) * [CAIP-10 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) --- --- url: /v1/docs/implementation/agent-metadata-parsing.md description: Practical guide for parsing ERC-8004 agent metadata --- ## Description Practical guide for parsing ERC-8004 agent metadata **Audience**: Backend developers, indexer authors, explorer builders ## Overview This guide provides practical instructions for implementing a robust ERC-8004 agent metadata parser that handles real-world data patterns. **What You'll Learn**: * βœ… Parse 7 URI formats (IPFS, HTTP, Data URI variants) * βœ… Handle malformed metadata gracefully * βœ… Extract structured data (endpoints, OASF skills, wallets) * βœ… Validate against ERC-8004 standard * βœ… Generate helpful warnings for developers ## Parser Architecture ### High-Level Flow ```text Input: agentURI string ↓ 1. URI Format Detection β”œβ”€ Data URI (base64) β†’ decode base64 β†’ parse JSON β”œβ”€ Data URI (plain) β†’ URL decode β†’ parse JSON β”œβ”€ IPFS URI β†’ fetch from gateway β†’ parse JSON β”œβ”€ HTTP(S) URL β†’ fetch β†’ parse JSON └─ Plain JSON β†’ parse directly ↓ 2. JSON Parsing & Validation β”œβ”€ Check required fields (type, name, description, image) β”œβ”€ Validate endpoints array structure └─ Collect warnings for non-critical issues ↓ 3. Structured Data Extraction β”œβ”€ Extract endpoint URLs by type (MCP, A2A, OASF, wallet) β”œβ”€ Parse OASF skills and domains └─ Extract metadata for storage ↓ Output: { metadata, warnings[], status } ``` ### 5-Level Validation System ```text Level 1: Syntax β†’ Can we parse the URI and JSON? Level 2: Schema β†’ Does it have required fields? Level 3: Endpoint β†’ Are endpoints valid and reachable? Level 4: Semantic β†’ Do values make sense (CAIP formats, versions)? Level 5: Status β†’ Is the agent active and operational? ``` ## URI Format Parsers ### 1. Data URI (Base64) **Format**: `data:application/json;base64,` **Logic**: ```plaintext IF uri starts with "data:application/json;base64," THEN encoded ← extract data (remove "data:application/json;base64," prefix) // Edge case: ChaosChain pattern (claimed base64 but plain JSON) IF encoded starts with "{" THEN ADD_WARNING("base64_uri_with_plain_json") RETURN parse JSON from encoded END IF decoded ← base64 decode(encoded) RETURN parse JSON from decoded END IF ``` **Production Stats** (8004scan, Dec 2025): * **18%** of agents use base64 data URIs * **~5%** have the ChaosChain pattern (claimed base64 but plain JSON) ### 2. Data URI (Plain) **Format**: `data:application/json,` **Logic**: ```plaintext IF uri starts with "data:application/json," THEN data ← extract data (remove "data:application/json," prefix) // Some URIs are URL-encoded IF data contains "%" THEN data ← URL decode(data) ADD_WARNING("url_encoded_json") END IF RETURN parse JSON from data END IF ``` ### 3. IPFS URIs **Format**: `ipfs://` or `ipfs:///path` **Logic**: ```plaintext CONSTANTS: GATEWAYS ← [ "https://ipfs.io/ipfs/{}", "https://cloudflare-ipfs.com/ipfs/{}", "https://gateway.pinata.cloud/ipfs/{}" ] ALGORITHM: FetchIPFS(uri) INPUT: uri - IPFS URI string OUTPUT: JSON object or NULL BEGIN cid ← extract CID from uri (remove "ipfs://" prefix) FOR EACH gateway IN GATEWAYS DO url ← format gateway with cid TRY response ← HTTP GET(url, timeout: 5 seconds) IF response is successful THEN RETURN parse JSON from response END IF CATCH network error CONTINUE to next gateway END TRY END FOR ADD_ERROR("ipfs_fetch_failed") RETURN NULL END ``` **Production Stats**: * **51%** of agents use IPFS URIs * Gateway fallback is essential (success rate: ~95%) ### 4. HTTP/HTTPS URLs **Logic**: ```plaintext ALGORITHM: FetchHTTP(uri) INPUT: uri - HTTP(S) URL string OUTPUT: JSON object or NULL BEGIN IF uri starts with "http://" THEN ADD_WARNING("http_not_https") // Security warning END IF TRY response ← HTTP GET(uri, timeout: 5 seconds) IF response is successful THEN RETURN parse JSON from response ELSE ADD_ERROR("http_status_" + response.status_code) RETURN NULL END IF CATCH timeout error ADD_ERROR("http_timeout") RETURN NULL CATCH network error ADD_ERROR("http_error") RETURN NULL END TRY END ``` **Production Stats**: * **22%** of agents use HTTP(S) URLs * Timeout issues: ~8% of HTTP URIs ### 5. Plain JSON Fallback **Logic**: ```plaintext IF uri starts with "{" THEN ADD_WARNING("plain_json_without_uri_scheme") RETURN parse JSON from uri END IF ``` ## Schema Validation ### Required Fields ```plaintext CONSTANTS: REQUIRED ← {"type", "name", "description", "image"} ALGORITHM: ValidateRequired(metadata) INPUT: metadata - JSON object OUTPUT: warnings list BEGIN warnings ← empty list missing ← REQUIRED fields not present in metadata FOR EACH field IN missing DO ADD warnings("missing_required_" + field) END FOR IF metadata.type β‰  "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" THEN ADD warnings("invalid_type_field") END IF RETURN warnings END ``` ### Endpoints Validation ```plaintext ALGORITHM: ValidateEndpoints(metadata) INPUT: metadata - JSON object OUTPUT: warnings list BEGIN warnings ← empty list // Common typo: "endpoint" (singular) IF metadata contains "endpoint" AND metadata does not contain "endpoints" THEN ADD warnings("typo_endpoint_singular") RETURN warnings END IF endpoints ← get "endpoints" from metadata IF endpoints is null THEN ADD warnings("missing_endpoints") ELSE IF endpoints is not an array THEN ADD warnings("endpoints_not_array") ELSE IF endpoints is empty THEN ADD warnings("empty_endpoints") // Agent not reachable ELSE FOR EACH endpoint IN endpoints DO warnings ← warnings + ValidateEndpoint(endpoint) END FOR END IF RETURN warnings END ``` ### Endpoint-Specific Validation ```plaintext ALGORITHM: ValidateEndpoint(endpoint) INPUT: endpoint - JSON object OUTPUT: warnings list BEGIN warnings ← empty list name ← endpoint.name CASE name OF "MCP": IF endpoint.endpoint is empty THEN ADD warnings("mcp_missing_endpoint") END IF IF endpoint.version β‰  "2025-06-18" THEN ADD warnings("mcp_nonstandard_version") END IF "A2A": IF endpoint.endpoint is empty THEN ADD warnings("a2a_missing_endpoint") END IF IF endpoint.version NOT IN ["0.3.0", "0.30"] THEN ADD info("a2a_nonstandard_version") // SHOULD, not MUST per spec END IF IF endpoint.endpoint does not contain ".well-known/agent-card.json" THEN ADD info("a2a_missing_well_known") // Recommended path, not required END IF "OASF": IF endpoint.skills is empty AND endpoint.domains is empty THEN ADD warnings("oasf_empty") END IF warnings ← warnings + ValidateOASFSkills(endpoint.skills) warnings ← warnings + ValidateOASFDomains(endpoint.domains) "agentWallet": IF NOT IsValidCAIP10(endpoint.endpoint) THEN ADD warnings("wallet_invalid_format") END IF END CASE RETURN warnings END ``` ### CAIP Format Validation ```plaintext ALGORITHM: IsValidCAIP2(value) INPUT: value - string to validate OUTPUT: boolean (true if valid, false otherwise) BEGIN // Format: namespace:chainId:0xAddress pattern ← "^[a-z][-a-z0-9]{0,31}:[0-9]+:0x[a-fA-F0-9]{40}$" RETURN value matches pattern END ALGORITHM: IsValidCAIP10(value) INPUT: value - string to validate OUTPUT: boolean BEGIN // Format: namespace:chainId:accountAddress (same as CAIP-2) RETURN IsValidCAIP2(value) END Examples: βœ“ "eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847" βœ— "eip155:0x8004..." (missing chainId) βœ— "0x8004..." (missing namespace) ``` ## Data Extraction ### Structured Data Extraction ```plaintext ALGORITHM: ExtractAgentData(metadata) INPUT: metadata - validated JSON object OUTPUT: structured data record BEGIN data ← new record // Basic fields data.name ← metadata.name data.description ← metadata.description data.image_url ← metadata.image data.active ← metadata.active OR false (if not present) data.x402_support ← metadata.x402Support OR false (if not present) data.updated_at ← metadata.updatedAt // Endpoints (find by name in endpoints array) data.mcp_server ← FindEndpoint(metadata.endpoints, "MCP").endpoint data.a2a_endpoint ← FindEndpoint(metadata.endpoints, "A2A").endpoint data.agent_wallet ← FindEndpoint(metadata.endpoints, "agentWallet").endpoint data.ens ← FindEndpoint(metadata.endpoints, "ENS").endpoint data.did ← FindEndpoint(metadata.endpoints, "DID").endpoint // OASF data oasfEndpoint ← FindEndpoint(metadata.endpoints, "OASF") data.oasf_skills ← oasfEndpoint.skills OR empty list data.oasf_domains ← oasfEndpoint.domains OR empty list // Full metadata for backup data.metadata_json ← metadata RETURN data END ``` ## Complete Parser Implementation ### Core Parser Algorithm ```plaintext ALGORITHM: ParseAgentMetadata(uri) INPUT: uri - string containing agent metadata URI OUTPUT: (metadata, warnings[], status) or NULL BEGIN errors ← empty list warnings ← empty list // Step 1: Parse URI to JSON metadata ← ParseURI(uri) IF metadata = NULL THEN RETURN NULL END IF // Step 2: Validate schema warnings ← warnings + ValidateRequired(metadata) warnings ← warnings + ValidateEndpoints(metadata) // Step 3: Determine status IF errors is not empty THEN status ← "error" ELSE IF warnings is not empty THEN status ← "warning" ELSE status ← "success" END IF RETURN (metadata, warnings, status) END ALGORITHM: ParseURI(uri) INPUT: uri - string OUTPUT: JSON object or NULL BEGIN // Try formats in order of frequency // Data URIs (36% of agents) - fastest to parse IF uri starts with "data:" THEN metadata ← TryDataURI(uri) IF metadata β‰  NULL THEN RETURN metadata END IF END IF // IPFS (51% of agents) - requires network fetch IF uri starts with "ipfs://" THEN metadata ← FetchIPFS(uri) IF metadata β‰  NULL THEN RETURN metadata END IF END IF // HTTP(S) (22% of agents) - requires network fetch IF uri starts with "http" THEN metadata ← FetchHTTP(uri) IF metadata β‰  NULL THEN RETURN metadata END IF END IF // Plain JSON fallback (edge case) IF uri starts with "{" THEN ADD_WARNING("plain_json_without_uri_scheme") RETURN ParseJSON(uri) END IF ADD_ERROR("unsupported_uri_format") RETURN NULL END ALGORITHM: ValidateRequired(metadata) INPUT: metadata - JSON object OUTPUT: warnings list BEGIN warnings ← empty list required ← {"type", "name", "description", "image"} FOR EACH field IN required DO IF field not in metadata THEN ADD warnings("missing_required_" + field) END IF END FOR IF metadata.type β‰  "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" THEN ADD warnings("invalid_type_field") END IF RETURN warnings END ``` ### Usage Pattern ```plaintext MAIN Program: // Parse agent metadata uri ← GetAgentURI(agentId) result ← ParseAgentMetadata(uri) IF result β‰  NULL THEN (metadata, warnings, status) ← result // Extract structured data agentData ← ExtractAgentData(metadata) agentData.parse_status ← status agentData.parse_warnings ← warnings // Store in database StoreAgent(agentData) OUTPUT "Success: " + status ELSE OUTPUT "Parse failed" END IF END ``` ## Performance Optimization ### Caching Strategy ```text 1. Data URI Caching (in-memory LRU) - Data URIs are immutable β†’ safe to cache forever - Use LRU cache with 1000 entry limit - Cache hit rate: ~40% in production 2. IPFS Caching (Redis, 1 hour TTL) - Cache key: sha256(ipfs_uri) - Reduces gateway load by 85% - TTL: 3600s (content rarely changes) 3. HTTP Caching (Redis, 5 minute TTL) - Cache key: sha256(http_url) - Respects Cache-Control headers - TTL: 300s (content may update) ``` ### Batch Processing ```plaintext ALGORITHM: ParseAgentBatch(uris) INPUT: uris - list of URI strings OUTPUT: list of parse results BEGIN results ← empty list // Process URIs in parallel FOR EACH uri IN uris (in parallel) DO result ← ParseAgentMetadata(uri) ADD result to results END FOR RETURN results END Note: Typical throughput: 100-200 agents/second (with caching) ``` ## Common Issues & Solutions ### Issue 1: Empty Endpoints Array **Pattern**: `{"endpoints": []}` **Impact**: Agent not reachable, but metadata is valid **Solution**: Warn but don't fail validation ```plaintext IF endpoints is empty THEN ADD_WARNING("empty_endpoints") // Still store agent, may be pre-registration END IF ``` **Production Stats**: ~15% of agents have empty endpoints ### Issue 2: Null agentId in Registrations **Pattern**: `{"registrations": [{"agentId": null}]}` **Context**: Common during registration flow (agentId assigned after transaction) **Solution**: Accept and log as info (not warning) ```plaintext IF registration.agentId is null THEN ADD_INFO("registration_null_agent_id") // Expected for first-time deployments; will be updated after transaction confirms END IF ``` **Rationale**: This is expected behavior, not a problem. First-time deployments don't know their tokenId until the on-chain transaction confirms. **Production Stats**: ~30% of initial registrations have null agentId ### Issue 3: Version Number Variations **Pattern**: A2A version `"0.30"` instead of `"0.3.0"` **Solution**: Accept both formats ```plaintext CONSTANTS: VALID_A2A_VERSIONS ← ["0.3.0", "0.30"] IF endpoint.version IN VALID_A2A_VERSIONS THEN IF endpoint.version = "0.30" THEN ADD_WARNING("a2a_version_typo") // Inform but accept END IF END IF ``` ## Validation Error Codes > **8004scan-specific**: The following error codes are used by 8004scan's validation system. Other implementations MAY use different codes. ### Severity Levels 8004scan uses three severity levels following RFC 2119/8174: | Level | Description | Action | | ----------- | ------------------------------------------------ | -------------- | | **Error** | Critical issues preventing proper functioning | Parse fails | | **Warning** | Functional issues but not critical | Parse succeeds | | **Info** | Recommendations, expected states, best practices | Advisory only | ### Level 1: Syntax Validation **Errors** (Parse Fails): | Issue | Error Code | | ------------------- | ------------------- | | Empty URI | `empty_uri` | | Invalid JSON syntax | `invalid_json` | | Invalid base64 | `invalid_base64` | | Non-dict root | `invalid_root_type` | **Warnings** (Parse Succeeds): | Issue | Warning Code | | -------------------------- | ------------------------------- | | Plain JSON without scheme | `plain_json_without_uri_scheme` | | base64 URI with plain JSON | `base64_uri_with_plain_json` | | URL-encoded JSON | `url_encoded_json` | ### Level 2: Schema Validation **Critical Warnings** (Likely to cause display issues): | Issue | Warning Code | Severity | | --------------------- | ------------------------------ | -------- | | Missing `type` | `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 | | Empty `endpoints` | `empty_endpoints` | Medium | **Standard Warnings**: | Issue | Warning Code | | ----------------------------------------- | -------------------------------- | | `endpoint` instead of `endpoints` | `typo_endpoint_singular` | | `registration` instead of `registrations` | `typo_registration_singular` | | `registrations[].agentId` mismatch | `registration_agent_id_mismatch` | | Invalid CAIP-2 format | `invalid_caip2_format` | | Invalid CAIP-10 format | `invalid_caip10_format` | **Info Messages** (Expected states, recommendations): | Issue | Info Code | | ----------------------------------- | ---------------------------- | | `registrations[].agentId` is `null` | `registration_null_agent_id` | | Missing `registrations` array | `missing_registrations` | | Empty `registrations` array | `empty_registrations` | ### Level 3: Endpoint Validation **MCP Endpoint**: | Issue | Code | Severity | | -------------------- | ------------------------- | -------- | | Missing `endpoint` | `mcp_missing_endpoint` | Warning | | Missing `version` | `mcp_missing_version` | Info | | Non-standard version | `mcp_nonstandard_version` | Info | > **Note**: Per ERC-8004 spec: "The version field in endpoints is a SHOULD, not a MUST." **A2A Endpoint**: | Issue | Code | Severity | | -------------------------- | ------------------------- | -------- | | Missing `endpoint` | `a2a_missing_endpoint` | Warning | | Missing `version` | `a2a_missing_version` | Info | | Non-standard version | `a2a_nonstandard_version` | Info | | Missing `.well-known` path | `a2a_missing_well_known` | Info | > **Note**: A2A `.well-known/agent-card.json` path is shown as an example in ERC-8004, not a requirement. Other paths are valid. **OASF Endpoint**: | Issue | Warning Code | | ----------------------------------- | -------------------------- | | Missing both `skills` and `domains` | `oasf_empty` | | Invalid skill slug | `oasf_invalid_skill` | | Invalid domain slug | `oasf_invalid_domain` | | Non-standard version | `oasf_nonstandard_version` | **agentWallet Endpoint**: | Issue | Warning Code | | ---------------------- | ------------------------- | | Invalid CAIP-10 format | `wallet_invalid_format` | | Invalid checksum | `wallet_invalid_checksum` | ### Level 4: Semantic Validation **Trust Models**: | Issue | Warning Code | | ---------------------- | ----------------------- | | Unknown trust model | `unknown_trust_model` | | Empty `supportedTrust` | `empty_supported_trust` | **Known trust models**: `"reputation"`, `"crypto-economic"`, `"tee-attestation"`, `"social-graph"` **agentHash Verification** (8004scan Extension): | Issue | Warning Code | Severity | | ----------------------------------- | ---------------------- | -------- | | Hash mismatch (onchain vs computed) | `agent_hash_mismatch` | Warning | | HTTP/HTTPS URI without agentHash | `agent_uri_not_hashed` | Info | > **Note**: `agentHash` verification only applies to HTTP/HTTPS URIs. IPFS/Arweave are content-addressed. ### Level 5: Status Fields | Issue | Warning Code | | ---------------------- | ------------------------ | | `active: false` | `agent_not_active` | | Invalid boolean values | `invalid_boolean_active` | ## Production Statistics **Data Source**: 8004scan Production (Base Sepolia), December 2025, 4,725 agents ### URI Format Distribution * **IPFS**: 51% (`ipfs://CID`) * **HTTP(S)**: 22% (`https://...`) * **Data URI (base64)**: 18% (`data:application/json;base64,...`) * **Other**: 9% (plain JSON, Arweave, etc.) ### Endpoint Adoption * **A2A**: 85% of agents * **MCP**: 75% of agents * **OASF**: 60% of agents * **agentWallet**: 45% of agents ### Parse Success Rates * **Perfect (no warnings)**: 58.1% * **Success with warnings**: 11.8% * **Total success**: 69.9% * **Common issues**: Empty endpoints (~15%), null agentId (~30%) ### Top OASF Skills 1. `communication_skills/content_creation` (18%) 2. `analytical_skills/data_analysis` (15%) 3. `technical_skills/software_development` (12%) 4. `problem_solving/strategic_thinking` (10%) 5. `specialized_skills/blockchain_expertise` (8%) ## Resources * [Agent Metadata Standard](../01-agent-metadata-standard.md) - Full schema specification * [CAIP-2 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) - Blockchain ID format * [CAIP-10 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) - Account address format * [OASF Taxonomy](https://github.com/agntcy/oasf/) - Skills and domains reference --- --- url: /docs/01-agent-metadata-standard.md description: Recommended offchain data format for ERC-8004 agent registration --- > **⚠️ Field Name Migration Notice (Jan 2026)** > > The official EIP-8004 specification has changed the field name from `endpoints` to `services`. > 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 using `endpoints` > will continue to work. Parsers will emit a `WA031` warning recommending migration. > > See [Field Name Migration](#field-name-migration-endpoints-to-services) 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](reference/sources.md) * βœ… **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](https://eips.ethereum.org/EIPS/eip-8004) specification. **Official EIP-8004** defines: * Smart contract interfaces for Identity Registry * The `agentURI` field 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](00-CONVENTIONS.md). ## Intended Audience * Agent developers registering new agents * Registry implementers building indexers and explorers * Tool builders creating SDKs ## Table of Contents 1. [Overview](#overview) 2. [AgentURI Metadata Format](#agenturi-metadata-format) 3. [Recommended Fields](#recommended-fields) 4. [Service Types](#service-types) 5. [Optional Fields](#optional-fields) 6. [URI Format Standards](#uri-format-standards) 7. [Data URI Compression Extension (Optional)](#data-uri-compression-extension-optional) ⭐ 8. [Onchain Metadata](#onchain-metadata) 9. [Validation Levels](#validation-levels) 10. [Real-World Examples](#real-world-examples) 11. [Updating Agent Metadata](#updating-agent-metadata) 12. [Field Name Migration: `endpoints` β†’ `services`](#field-name-migration-endpoints-to-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 services. **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 ```text β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 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β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## AgentURI Metadata Format ### Complete Schema ```jsonc { // ============ 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"] } ``` ## 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**: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" } ``` **Validation**: * ⚠️ Missing: `missing_required_type` warning (reduces interoperability) * ⚠️ Non-standard value: `invalid_type_field` warning ### 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**: ```json { "name": "DataAnalyst Pro" } ``` **Validation**: * ⚠️ Missing: `missing_required_name` warning * ⚠️ Empty string: validation warning > **Note**: While the official EIP-8004 lists `name` as 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**: ```json { "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." } ``` **Validation**: * ⚠️ Missing: `missing_recommended_description` warning ### 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 hash * `ar://` - Arweave transaction ID * `data: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**: ```json { "image": "https://cdn.example.com/agents/dataanalyst-pro.png" } ``` ```json { "image": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4" } ``` **Validation**: * ⚠️ Missing: `missing_recommended_image` warning * ⚠️ Relative path: validation warning (should be absolute URI) ## Additional Recommended Fields ### services (SHOULD) **Type**: `array` of service objects **Purpose**: Communication services 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 `endpoints` to `services`. > 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, `services` takes precedence. **General Structure**: ```json { "name": "EndpointType", "endpoint": "url_or_identifier", "version": "protocol_version" // ... type-specific fields } ``` **Validation**: * ⚠️ Using `endpoints`: `WA031` warning (recommend migrating to `services`) * ❌ Missing: `missing_services` warning * ⚠️ Empty array: `empty_services` warning (agent not reachable) * ⚠️ Common typo: `endpoint` (singular) instead of `services` (plural) **See [Service Types](#service-types) section for detailed specifications.** ### registrations (SHOULD) **Type**: `array` of registration objects **Purpose**: Links to on-chain NFT identity, creating cryptographic bidirectional verification. **Structure**: ```json { "registrations": [ { "agentId": 241, "agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847" } ] } ``` **Fields**: * `agentId` (number): Token ID from ERC-721 registry * `agentRegistry` (string): CAIP-10 format `namespace:chainId:contractAddress` **CAIP-10 Format**: ```text namespace : chainId : reference ↓ ↓ ↓ eip155 : 1 : 0x8004a6090Cd10A7288092483047B097295Fb8847 ``` **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_registrations` info (no on-chain link, discovery-only) * ℹ️ Empty array: `empty_registrations` info (no on-chain link) * ℹ️ Null agentId: `registration_null_agent_id` info (expected for first-time deployments) * ⚠️ ID mismatch: `registration_agent_id_mismatch` warning * ⚠️ Invalid CAIP-10: `invalid_caip10_format` warning > **Note**: Missing or null `agentId` is 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**: ```text NFT (on-chain) ↓ agentURI points to Metadata (offchain) ↓ registrations[0] points back to NFT (on-chain) βœ… verified ``` ## Service Types ### 1. MCP (Model Context Protocol) **Purpose**: Standard protocol for AI agents to expose tools, prompts, and resources. **Specification**: [MCP Protocol](https://modelcontextprotocol.io/) **Version Format**: Date-based (`YYYY-MM-DD`). Examples: `2025-06-18`, `2025-11-25`, `2026-01-29` **Structure**: ```json { "name": "MCP", "endpoint": "https://api.example.com/mcp", "version": "2025-11-25", "mcpTools": ["analyze_wallet", "detect_anomalies"], "capabilities": [] } ``` > \[!NOTE] > **v1.1 Change**: The `capabilities` field format changed from object `{}` to array `[]` in January 2026. **Fields**: * `endpoint` (string, REQUIRED): MCP server URL * `version` (string, REQUIRED): MCP protocol version in `YYYY-MM-DD` date format * `mcpTools` (array, OPTIONAL): List of available MCP tools * `mcpPrompts` (array, OPTIONAL): List of available prompts * `mcpResources` (array, OPTIONAL): List of available resources * `capabilities` (array, OPTIONAL): MCP server capabilities See [MCP Protocol Documentation](https://modelcontextprotocol.io/) for complete specification. ### 2. A2A (Agent-to-Agent Protocol) **Purpose**: Enables agent-to-agent communication and collaboration. **Specification**: [A2A Protocol](https://a2a.to/) (current version: `0.3.0`) **Structure**: ```json { "name": "A2A", "endpoint": "https://agent.example/.well-known/agent-card.json", "version": "0.3.0", "a2aSkills": ["analytical_skills/coding_skills/text_to_code"] } ``` **Fields**: * `endpoint` (string, REQUIRED): URL to agent card (SHOULD use `/.well-known/agent-card.json` path) * `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](https://a2a.to/) 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](https://github.com/agntcy/oasf/releases) **Schema Browser**: **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**: ```json { "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" ] } ``` **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 of `skills` or `domains` required) * `domains` (array, REQUIRED): OASF domain slugs (at least one of `skills` or `domains` required) **Skill Taxonomy**: OASF skills follow a hierarchical structure: ```text category / subcategory / specific_skill ↓ ↓ ↓ analytical_skills / data_analysis / blockchain_analysis ``` **Common Skills** (examples from [legacy testnet data](reference/sources.md#8-production-agent-metadata)): * `natural_language_processing/natural_language_generation/summarization` * `tool_interaction/api_schema_understanding` * `multi_modal/image_processing/text_to_image` * `natural_language_processing/information_retrieval_synthesis/search` * `tool_interaction/workflow_automation` **Domain Taxonomy**: OASF domains categorize agent application areas: ```text industry / sector / specialization ↓ ↓ ↓ finance_and_business / investment_services ``` **Common Domains** (examples from [legacy testnet data](reference/sources.md#8-production-agent-metadata)): * `technology/blockchain` * `finance_and_business/finance` * `technology/software_engineering/apis_integration` * `technology/blockchain/cryptocurrency` * `media_and_entertainment/content_creation` **Resources**: * [OASF Schema Browser](https://schema.oasf.outshift.com/0.8.0) * [Complete skill list](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * [Complete domain list](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 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): ```json { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ``` **Onchain Update** (v1.1.0): ```solidity // Update wallet with cryptographic verification (EIP-712 or ERC-1271) function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes calldata signature) external ``` **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**: ```text namespace : chainId : accountAddress ↓ ↓ ↓ eip155 : 1 : 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7 ``` **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_format` warning * ⚠️ Invalid checksum: `wallet_invalid_checksum` warning **Multiple Wallets**: Agents can have wallets on multiple chains: ```json { "services": [ { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" }, { "name": "agentWallet", "endpoint": "eip155:8453:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ] } ``` ### 5. ENS Name **Purpose**: Human-readable Ethereum Name Service identifier. **Structure**: ```json { "name": "ENS", "endpoint": "dataanalyst.eth", "version": "v1" } ``` **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**: ```json { "name": "DID", "endpoint": "did:ethr:0x1234567890abcdef1234567890abcdef12345678", "version": "v1" } ``` **Supported DID Methods**: * `did:ethr:...` - Ethereum DID * `did:web:...` - Web DID * `did:key:...` - Key DID **Fields**: * `endpoint` (string, REQUIRED): DID identifier * `version` (string, OPTIONAL): DID version ### 7. Human-Facing Services (NEW in v1.1) > \[!NOTE] > **v1.1 Addition**: The January 2026 update added `web` and `email` as standard human-facing service types. **Purpose**: Contact and information services for human users (not agent-to-agent communication). **Structure**: ```json { "services": [ { "name": "web", "endpoint": "https://myagent.example.com" }, { "name": "email", "endpoint": "support@myagent.example.com" } ] } ``` **Fields**: * `web` - Agent's public website or landing page * `email` - Contact email for support or inquiries ### 8. Custom Services The ERC-8004 spec allows arbitrary service types for protocol-specific needs. **Example 1: Custom API**: ```json { "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" } ``` **Example 2: Custom Protocol**: ```json { "name": "wallet", "endpoint": "eip155:11155111:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ``` **Guidelines**: * Use descriptive `name` field * Include `description` for custom services * 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**: ```json { "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"] } ``` **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_model` warning * ⚠️ Empty array: `empty_supported_trust` warning **Adoption** (from [legacy testnet data](reference/sources.md#8-production-agent-metadata)): See [Sources & References](reference/sources.md) for detailed adoption statistics. ### active (MAY) **Type**: `boolean` **Purpose**: Production readiness flag. **Structure**: ```json { "active": true } ``` **Values**: * `true` - Agent is production-ready and actively accepting requests * `false` - Agent is in development, testing, or inactive **Default**: `false` or `undefined` (inactive) **Validation**: * ⚠️ `active: false`: `agent_not_active` warning (not production-ready) * ⚠️ Non-boolean: `invalid_boolean_active` warning ### x402Support (MAY) **Type**: `boolean` **Purpose**: Indicates support for x402 payment protocol (HTTP 402 Payment Required). **Structure**: ```json { "x402Support": true } ``` **Values**: * `true` - Agent accepts x402 payment requests * `false` - Agent does not support x402 **Requirements**: If `x402Support: true`, agent SHOULD have an `agentWallet` endpoint defined. **Validation**: * ⚠️ Non-boolean: `invalid_boolean_x402` warning ### updatedAt (MAY) **Type**: `number` (Unix timestamp) **Purpose**: Last update timestamp for metadata freshness tracking. **Structure**: ```json { "updatedAt": 1763112328 } ``` **Format**: Unix timestamp (seconds since epoch) **Usage**: * Helps explorers show "last updated" time * Can be used for ranking/sorting by freshness **Example**: ```javascript // Generate current timestamp const updatedAt = Math.floor(Date.now() / 1000); ``` ## 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**: 1. **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 2. **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 3. **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**: ```text data:application/json;base64, ``` **Plain Format**: ```text data:application/json, ``` **Example (Base64)**: ```text data:application/json;base64,ewogICJ0eXBlIjogImh0dHBzOi8vZWlwcy5ldGhlcmV1bS5vcmcvRUlQUy9laXAtODAwNCNyZWdpc3RyYXRpb24tdjEiLAogICJuYW1lIjogIkFnZW50IE5hbWUiCn0= ``` **Example (Plain)**: ```text 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**: ```text ipfs://CID ipfs://CID/path/to/file.json ``` **Examples**: ```text ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4 ipfs://QmXXX/metadata.json ``` **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: 1. `https://ipfs.io/ipfs/{CID}` 2. `https://cloudflare-ipfs.com/ipfs/{CID}` 3. `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**: ```text ar://TX_ID ar://TX_ID/path ``` **Examples**: ```text ar://a1b2c3d4e5f6 ``` **Benefits**: * βœ… 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**: ```text https://example.com/metadata.json http://example.com/api/agent/123 ``` **Examples**: ```text https://cdn.example.com/agents/dataanalyst-pro.json https://api.example.com/v1/agents/241/metadata ``` **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**: ```text data:text/plain;base64, data:;base64, data:application/json;charset=utf-8;base64, ``` **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**: ```json { "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**: ```text data:application/json;enc=[;level=];base64, ``` **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](extensions/data-uri-compression.md). ## 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: ```solidity // Compute: keccak256(canonicalJSON) where keys are sorted alphabetically registry.setMetadata(agentId, "agentHash", abi.encodePacked(hash)); ``` **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-known` path **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](implementation/agent-metadata-parsing.md#validation-error-codes). ## Real-World Examples For examples of agent metadata formats observed in production deployments, see [Real-World Examples](reference/real-world-examples.md). ## Updating Agent Metadata ### Upgrading Metadata Version When updating agent metadata, increment `updatedAt` timestamp: **Before**: ```json { "name": "MyAgent v1", "updatedAt": 1763112328 } ``` **After**: ```json { "name": "MyAgent v2", "updatedAt": 1763200000 // ← New timestamp } ``` **On-Chain Update** (v1.1.0): > \[!NOTE] > `setAgentURI()` is exposed on the registry; callable by owner or approved operator; emits `URIUpdated`. ```solidity // Update agentURI on ERC-8004 registry (owner or approved) agentRegistry.setAgentURI(agentId, newAgentURI); ``` **Function Signature**: ```solidity function setAgentURI(uint256 agentId, string calldata newAgentURI) external; ``` **Requirements**: * Caller MUST be the agent owner or an approved operator * `agentId` MUST 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. 1. **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 99 ``` 2. **Phase 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..." }, { "agentId": 7, "agentRegistry": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:8oo48pya1SZD23ZhzoNMhxR2UGb8BRa41Su4qP9EuaWm" } ] } ``` 3. **Phase 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..."); ``` 4. **Indexing**: 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 `registrations` array *** ## References ### Official Specifications * [EIP-8004: Trustless Agents](https://eips.ethereum.org/EIPS/eip-8004) * [CAIP-2: Chain ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) * [CAIP-10: Account ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) ### Protocol Documentation * [MCP Protocol](https://modelcontextprotocol.io/) * [A2A Protocol v0.3.0](https://a2a.to/) * [OASF v0.8.0 Taxonomy](https://github.com/agntcy/oasf/tree/v0.8.0) * [Schema Browser](https://schema.oasf.outshift.com/0.8.0) * [All Skills](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * [All Domains](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 8004scan Resources * [Agent Metadata Parsing Guide](implementation/agent-metadata-parsing.md) * [Feedback Standard](02-feedback-standard.md) * [Validation Standard](03-validation-standard.md) * [Sources & References](reference/sources.md) ## 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)**: ```jsonc { "services": [ { "name": "MCP", "endpoint": "https://..." }, { "name": "A2A", "endpoint": "https://..." } ] } ``` **Legacy Format (still supported)**: ```jsonc { "endpoints": [ { "name": "MCP", "endpoint": "https://..." }, { "name": "A2A", "endpoint": "https://..." } ] } ``` ### Compatibility Strategy To ensure backward compatibility, parsers (including 8004scan backend) implement the following: 1. **Accept both fields**: `services` and `endpoints` are both valid 2. **Prefer `services`**: If both exist, `services` takes precedence 3. **Emit migration warning**: When `endpoints` is used, emit `WA031` warning message ### Migration Steps **For Agent Developers**: 1. Update your agent metadata to use `services` instead of `endpoints` 2. The field structure remains identicalβ€”only the array name changes 3. No changes needed to individual service objects **Example Migration**: ```diff { "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" } ] } ``` **For Parser Implementers**: ```plaintext # 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 IF ``` ### 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. The `WA031` warning 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](implementation/agent-metadata-parsing.md) * **Real-world usage** β†’ See [sources and examples](reference/sources.md) *** **Version**: 1.3 **Last Updated**: 2026-01-27 **Status**: Community Guidelines --- --- url: /legacy-pre-v1/docs/01-agent-metadata-standard.md description: Recommended offchain data format for ERC-8004 agent registration --- ## 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](https://eips.ethereum.org/EIPS/eip-8004) specification. **Official EIP-8004** defines: * Smart contract interfaces for Identity Registry * The `agentURI` field 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](00-CONVENTIONS.md), including: * **RFC 2119 keywords**: MUST, SHOULD, MAY (see [Conventions - RFC 2119](00-CONVENTIONS.md#rfc-2119-key-words)) * **Field types**: string, number, boolean, object, array (see [Conventions - Field Type System](00-CONVENTIONS.md#field-type-system)) * **CAIP formats**: CAIP-2 for blockchain IDs, CAIP-10 for addresses (see [Conventions - Address Formats](00-CONVENTIONS.md#address-and-chain-identifiers)) * **Timestamps**: ISO 8601 format in UTC (see [Conventions - Timestamp Format](00-CONVENTIONS.md#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 1. [Overview](#overview) 2. [AgentURI Metadata Format](#agenturi-metadata-format) 3. [Recommended Fields](#recommended-fields) 4. [Endpoint Types](#endpoint-types) 5. [Optional Fields](#optional-fields) 6. [URI Format Standards](#uri-format-standards) 7. [Data URI Compression Extension (Optional)](#data-uri-compression-extension-optional) ⭐ 8. [Onchain Metadata](#onchain-metadata) 9. [Validation Levels](#validation-levels) 10. [Real-World Patterns](#real-world-patterns) 11. [Migration Guides](#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 ```text β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 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β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## AgentURI Metadata Format ### Complete Schema ```json { // ============ 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 } ``` ## 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**: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" } ``` **Validation**: * ⚠️ Missing: `missing_required_type` warning (reduces interoperability) * ⚠️ Non-standard value: `invalid_type_field` warning ### 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**: ```json { "name": "DataAnalyst Pro" } ``` **Validation**: * ⚠️ Missing: `missing_required_name` warning * ⚠️ Empty string: validation warning > **Note**: While the official EIP-8004 lists `name` as 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**: ```json { "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." } ``` **Validation**: * ❌ Missing: `missing_required_description` warning ### 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 hash * `ar://` - Arweave transaction ID * `data: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**: ```json { "image": "https://cdn.example.com/agents/dataanalyst-pro.png" } ``` ```json { "image": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4" } ``` **Validation**: * ❌ Missing: `missing_recommended_image` warning * ⚠️ 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**: ```json { "name": "EndpointType", "endpoint": "url_or_identifier", "version": "protocol_version" // ... type-specific fields } ``` **Validation**: * ❌ Missing: `missing_endpoints` warning * ⚠️ Empty array: `empty_endpoints` warning (agent not reachable) * ⚠️ Common typo: `endpoint` (singular) instead of `endpoints` (plural) **See [Endpoint Types](#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**: ```json { "registrations": [ { "agentId": 241, "agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847" } ] } ``` **Fields**: * `agentId` (number): Token ID from ERC-721 registry * `agentRegistry` (string): CAIP-10 format `namespace:chainId:contractAddress` **CAIP-10 Format**: ```text namespace : chainId : reference ↓ ↓ ↓ eip155 : 1 : 0x8004a6090Cd10A7288092483047B097295Fb8847 ``` **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_registrations` warning * ⚠️ Empty array: `empty_registrations` warning * ⚠️ Null agentId: `registration_null_agent_id` warning * ⚠️ ID mismatch: `registration_agent_id_mismatch` warning * ⚠️ Invalid CAIP-10: `invalid_caip10_format` warning **Circular Verification**: ```text NFT (on-chain) ↓ agentURI points to Metadata (offchain) ↓ registrations[0] points back to NFT (on-chain) βœ… verified ``` ## Endpoint Types ### 1. MCP (Model Context Protocol) **Purpose**: Standard protocol for AI agents to expose tools, prompts, and resources. **Specification**: [MCP Protocol Docs](https://modelcontextprotocol.io/) **Structure**: ```json { "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": {} } } ``` **Fields**: * `endpoint` (string, REQUIRED): MCP server URL * `version` (string, REQUIRED): MCP protocol version (standard: `"2025-06-18"`) * `mcpTools` (array, OPTIONAL): List of available MCP tools * `mcpPrompts` (array, OPTIONAL): List of available prompts * `mcpResources` (array, OPTIONAL): List of available resources * `capabilities` (object, OPTIONAL): MCP server capabilities per spec **Validation**: * ❌ Missing `endpoint`: `mcp_missing_endpoint` warning * ❌ Missing `version`: `mcp_missing_version` warning * ⚠️ Non-standard version: `mcp_nonstandard_version` warning **Example Usage**: ```typescript // 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. A2A (Agent-to-Agent Protocol) **Purpose**: Enables agent-to-agent communication and collaboration. **Specification**: [A2A Protocol v0.3.0](https://a2a.to/) **Structure**: ```json { "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" ] } ``` **Fields**: * `endpoint` (string, REQUIRED): URL to agent card (SHOULD use `/.well-known/agent-card.json` path) * `version` (string,dard: `"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: ```json { "name": "DataAnalyst Pro", "description": "...", "skills": ["analytical_skills/data_analysis/blockchain_analysis"], "url": "https://agent.example", "contact": "support@example.com" } ``` **Validation**: * ❌ Missing `endpoint`: `a2a_missing_endpoint` warning * ❌ Missing `version`: `a2a_missing_version` warning * ⚠️ Non-standard version: `a2a_nonstandard_version` warning * ⚠️ Missing `.well-known` path: `a2a_missing_well_known` warning **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](https://github.com/agntcy/oasf/tree/v0.8.0) **Schema Browser**: **Structure**: ```json { "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" ] } ``` **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 of `skills` or `domains` required) * `domains` (array, REQUIRED): OASF domain slugs (at least one of `skills` or `domains` required) **Skill Taxonomy**: OASF skills follow a hierarchical structure: ```text category / subcategory / specific_skill ↓ ↓ ↓ analytical_skills / data_analysis / blockchain_analysis ``` **Top 5 Skills** (by usage in production): 1. `natural_language_processing/natural_language_generation/summarization` (40%) 2. `tool_interaction/api_schema_understanding` (35%) 3. `multi_modal/image_processing/text_to_image` (30%) 4. `natural_language_processing/information_retrieval_synthesis/search` (28%) 5. `tool_interaction/workflow_automation` (25%) **Domain Taxonomy**: OASF domains categorize agent application areas: ```text industry / sector / specialization ↓ ↓ ↓ finance_and_business / investment_services ``` **Top 5 Domains** (by usage in production): 1. `technology/blockchain` (45%) 2. `finance_and_business/finance` (35%) 3. `technology/software_engineering/apis_integration` (30%) 4. `technology/blockchain/cryptocurrency` (28%) 5. `media_and_entertainment/content_creation` (25%) **Validation**: * ❌ Missing both `skills` and `domains`: `oasf_empty` warning * ⚠️ Invalid skill slug: `oasf_invalid_skill` warning * ⚠️ Invalid domain slug: `oasf_invalid_domain` warning * ⚠️ Non-standard version: `oasf_nonstandard_version` warning **Resources**: * Complete skill list: [all\_skills.json](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * Complete domain list: [all\_domains.json](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 4. agentWallet **Purpose**: Payment wallet address for x402 protocol and agent-to-agent transactions. **Format**: CAIP-10 (Account ID Specification) **Structure**: ```json { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ``` **CAIP-10 Format**: ```text namespace : chainId : accountAddress ↓ ↓ ↓ eip155 : 1 : 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7 ``` **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_format` warning * ⚠️ Invalid checksum: `wallet_invalid_checksum` warning **Multiple Wallets**: Agents can have wallets on multiple chains: ```json { "endpoints": [ { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" }, { "name": "agentWallet", "endpoint": "eip155:8453:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ] } ``` ### 5. ENS Name **Purpose**: Human-readable Ethereum Name Service identifier. **Structure**: ```json { "name": "ENS", "endpoint": "dataanalyst.eth", "version": "v1" } ``` **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**: ```json { "name": "DID", "endpoint": "did:ethr:0x1234567890abcdef1234567890abcdef12345678", "version": "v1" } ``` **Supported DID Methods**: * `did:ethr:...` - Ethereum DID * `did:web:...` - Web DID * `did:key:...` - Key DID **Fields**: * `endpoint` (string, REQUIRED): DID identifier * `version` (string, OPTIONAL): DID version ### 7. Custom Endpoints The ERC-8004 spec allows arbitrary endpoint types for protocol-specific needs. **Example 1: Custom API**: ```json { "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" } ``` **Example 2: Custom Protocol**: ```json { "name": "wallet", "endpoint": "eip155:11155111:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ``` **Guidelines**: * Use descriptive `name` field * Include `description` for 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**: ```json { "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"] } ``` **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_model` warning * ⚠️ Empty array: `empty_supported_trust` warning **Usage in Production**: * `reputation`: 80% of agents * `crypto-economic`: 50% of agents * `tee-attestation`: 20% of agents ### active (MAY) **Type**: `boolean` **Purpose**: Production readiness flag. **Structure**: ```json { "active": true } ``` **Values**: * `true` - Agent is production-ready and actively accepting requests * `false` - Agent is in development, testing, or inactive **Default**: `false` or `undefined` (inactive) **Validation**: * ⚠️ `active: false`: `agent_not_active` warning (not production-ready) * ⚠️ Non-boolean: `invalid_boolean_active` warning ### x402support (MAY) **Type**: `boolean` **Purpose**: Indicates support for x402 payment protocol (HTTP 402 Payment Required). **Structure**: ```json { "x402support": true } ``` **Values**: * `true` - Agent accepts x402 payment requests * `false` - Agent does not support x402 **Requirements**: If `x402support: true`, agent SHOULD have an `agentWallet` endpoint defined. **Validation**: * ⚠️ Non-boolean: `invalid_boolean_x402` warning ### updatedAt (MAY) **Type**: `number` (Unix timestamp) **Purpose**: Last update timestamp for metadata freshness tracking. **Structure**: ```json { "updatedAt": 1763112328 } ``` **Format**: Unix timestamp (seconds since epoch) **Usage**: * Helps explorers show "last updated" time * Can be used for ranking/sorting by freshness **Example**: ```javascript // Generate current timestamp const updatedAt = Math.floor(Date.now() / 1000); ``` ## 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**: 1. **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 2. **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 3. **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**: ```text data:application/json;base64, ``` **Plain Format**: ```text data:application/json, ``` **Example (Base64)**: ```text data:application/json;base64,ewogICJ0eXBlIjogImh0dHBzOi8vZWlwcy5ldGhlcmV1bS5vcmcvRUlQUy9laXAtODAwNCNyZWdpc3RyYXRpb24tdjEiLAogICJuYW1lIjogIkFnZW50IE5hbWUiCn0= ``` **Example (Plain)**: ```text 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**: ```text ipfs://CID ipfs://CID/path/to/file.json ``` **Examples**: ```text ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4 ipfs://QmXXX/metadata.json ``` **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: 1. `https://ipfs.io/ipfs/{CID}` 2. `https://cloudflare-ipfs.com/ipfs/{CID}` 3. `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**: ```text ar://TX_ID ar://TX_ID/path ``` **Examples**: ```text ar://a1b2c3d4e5f6 ``` **Benefits**: * βœ… 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**: ```text https://example.com/metadata.json http://example.com/api/agent/123 ``` **Examples**: ```text https://cdn.example.com/agents/dataanalyst-pro.json https://api.example.com/v1/agents/241/metadata ``` **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**: ```text data:text/plain;base64, data:;base64, data:application/json;charset=utf-8;base64, ``` **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**: ```json { "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=` 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 ```text data:application/json;enc=[;level=];base64, ``` **Parameters**: * `enc`: Compression algorithm (`zstd` | `gzip` | `br` | `lz4`) * `level`: Compression level (optional, algorithm-specific defaults apply) **Examples**: ```text 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… ``` ### 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**: ```text Gas = data_size_bytes Γ— 16 + 21,000 ``` **Key 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): ```python 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) ``` **TypeScript**: ```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); ``` **Security**: Implementation should include zip bomb protection (100KB decompression limit). ### Security **8004scan implements the following protections**: 1. **Zip Bomb Protection**: 100KB decompression size limit 2. **Algorithm Whitelist**: Only `zstd`, `gzip`, `br`, `lz4` allowed 3. **Async Processing**: Decompression handled in Celery workers (non-blocking) 4. **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](extensions/data-uri-compression.md). ## 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-known` path: `a2a_missing_well_known` **OASF Endpoint**: * Missing both `skills` and `domains`: `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 ```json { "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 } ``` **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 ```json { "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"] } ``` **Storage**: HTTP(S) API endpoint **Peculiarities**: * Empty `endpoint` fields (template format) * Relative image paths * Custom `attributes` object * Additional 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 ```json { "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"] } ``` **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) ```json { "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": [] } ``` **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**: ```json { "agent_name": "MyAgent", "agent_description": "Does things", "avatar_url": "https://...", "api_endpoint": "https://..." } ``` **Mapping**: ```json { "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" } ] } ``` #### Step 2: Add Required Fields Ensure all MUST fields are present: * βœ… `type` * βœ… `name` * βœ… `description` * βœ… `image` #### Step 3: Add Recommended Fields **Endpoints**: ```json { "endpoints": [ { "name": "MCP", "endpoint": "https://api.example.com/mcp", "version": "2025-06-18" }, { "name": "agentWallet", "endpoint": "eip155:1:0x..." } ] } ``` **Registrations**: ```json { "registrations": [ { "agentId": 123, "agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847" } ] } ``` #### 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. ```bash curl -X POST https://8004scan.io/api/v1/validate/metadata \ -H "Content-Type: application/json" \ -d @metadata.json ``` ### Upgrading Metadata Version When updating agent metadata, increment `updatedAt` timestamp: **Before**: ```json { "name": "MyAgent v1", "updatedAt": 1763112328 } ``` **After**: ```json { "name": "MyAgent v2", "updatedAt": 1763200000 // ← New timestamp } ``` **On-Chain Update**: ```solidity // Update agentURI on ERC-8004 registry agentRegistry.setAgentURI(agentId, newAgentURI); ``` ## References ### Official Specifications * [EIP-8004: Trustless Agents](https://eips.ethereum.org/EIPS/eip-8004) * [CAIP-2: Chain ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) * [CAIP-10: Account ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) ### Protocol Documentation * [MCP Protocol](https://modelcontextprotocol.io/) * [A2A Protocol v0.3.0](https://a2a.to/) * [OASF v0.8.0 Taxonomy](https://github.com/agntcy/oasf/tree/v0.8.0) * [Schema Browser](https://schema.oasf.outshift.com/0.8.0) * [All Skills](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * [All Domains](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 8004scan Resources * [Agent Metadata Parsing Guide](implementation/agent-metadata-parsing.md) * [Feedback Standard](02-feedback-standard.md) * [Validation Standard](03-validation-standard.md) * [Sources & References](reference/sources.md) ## 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](implementation/agent-metadata-parsing.md) * **Real-world usage** β†’ See [sources and examples](reference/sources.md) *** **Version**: 0.1 **Last Updated**: 2025-12-20 **Status**: Draft --- --- url: /v1/docs/01-agent-metadata-standard.md description: Recommended offchain data format for ERC-8004 agent registration --- ## 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](reference/sources.md) * βœ… **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](https://eips.ethereum.org/EIPS/eip-8004) specification. **Official EIP-8004** defines: * Smart contract interfaces for Identity Registry * The `agentURI` field 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](00-CONVENTIONS.md). ## Intended Audience * Agent developers registering new agents * Registry implementers building indexers and explorers * Tool builders creating SDKs ## Table of Contents 1. [Overview](#overview) 2. [AgentURI Metadata Format](#agenturi-metadata-format) 3. [Recommended Fields](#recommended-fields) 4. [Endpoint Types](#endpoint-types) 5. [Optional Fields](#optional-fields) 6. [URI Format Standards](#uri-format-standards) 7. [Data URI Compression Extension (Optional)](#data-uri-compression-extension-optional) ⭐ 8. [Onchain Metadata](#onchain-metadata) 9. [Validation Levels](#validation-levels) 10. [Real-World Examples](#real-world-examples) 11. [Updating Agent Metadata](#updating-agent-metadata) ## 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 ```text β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ 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β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## AgentURI Metadata Format ### Complete Schema ```jsonc { // ============ 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", // Endpoints - fully customizable (per official spec) "endpoints": [ { "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"] } ``` ## 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**: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" } ``` **Validation**: * ⚠️ Missing: `missing_required_type` warning (reduces interoperability) * ⚠️ Non-standard value: `invalid_type_field` warning ### 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**: ```json { "name": "DataAnalyst Pro" } ``` **Validation**: * ⚠️ Missing: `missing_required_name` warning * ⚠️ Empty string: validation warning > **Note**: While the official EIP-8004 lists `name` as 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**: ```json { "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." } ``` **Validation**: * ⚠️ Missing: `missing_recommended_description` warning ### 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 hash * `ar://` - Arweave transaction ID * `data: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**: ```json { "image": "https://cdn.example.com/agents/dataanalyst-pro.png" } ``` ```json { "image": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4" } ``` **Validation**: * ⚠️ Missing: `missing_recommended_image` warning * ⚠️ 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**: ```json { "name": "EndpointType", "endpoint": "url_or_identifier", "version": "protocol_version" // ... type-specific fields } ``` **Validation**: * ❌ Missing: `missing_endpoints` warning * ⚠️ Empty array: `empty_endpoints` warning (agent not reachable) * ⚠️ Common typo: `endpoint` (singular) instead of `endpoints` (plural) **See [Endpoint Types](#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**: ```json { "registrations": [ { "agentId": 241, "agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847" } ] } ``` **Fields**: * `agentId` (number): Token ID from ERC-721 registry * `agentRegistry` (string): CAIP-10 format `namespace:chainId:contractAddress` **CAIP-10 Format**: ```text namespace : chainId : reference ↓ ↓ ↓ eip155 : 1 : 0x8004a6090Cd10A7288092483047B097295Fb8847 ``` **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_registrations` info (no on-chain link, discovery-only) * ℹ️ Empty array: `empty_registrations` info (no on-chain link) * ℹ️ Null agentId: `registration_null_agent_id` info (expected for first-time deployments) * ⚠️ ID mismatch: `registration_agent_id_mismatch` warning * ⚠️ Invalid CAIP-10: `invalid_caip10_format` warning > **Note**: Missing or null `agentId` is 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**: ```text NFT (on-chain) ↓ agentURI points to Metadata (offchain) ↓ registrations[0] points back to NFT (on-chain) βœ… verified ``` ## Endpoint Types ### 1. MCP (Model Context Protocol) **Purpose**: Standard protocol for AI agents to expose tools, prompts, and resources. **Specification**: [MCP Protocol](https://modelcontextprotocol.io/) **Version Format**: Date-based (`YYYY-MM-DD`). Examples: `2025-06-18`, `2025-11-25`, `2026-01-29` **Structure**: ```json { "name": "MCP", "endpoint": "https://api.example.com/mcp", "version": "2025-11-25", "mcpTools": ["analyze_wallet", "detect_anomalies"], "capabilities": [] } ``` > \[!NOTE] > **v1.1 Change**: The `capabilities` field format changed from object `{}` to array `[]` in January 2026. **Fields**: * `endpoint` (string, REQUIRED): MCP server URL * `version` (string, REQUIRED): MCP protocol version in `YYYY-MM-DD` date format * `mcpTools` (array, OPTIONAL): List of available MCP tools * `mcpPrompts` (array, OPTIONAL): List of available prompts * `mcpResources` (array, OPTIONAL): List of available resources * `capabilities` (array, OPTIONAL): MCP server capabilities See [MCP Protocol Documentation](https://modelcontextprotocol.io/) for complete specification. ### 2. A2A (Agent-to-Agent Protocol) **Purpose**: Enables agent-to-agent communication and collaboration. **Specification**: [A2A Protocol](https://a2a.to/) (current version: `0.3.0`) **Structure**: ```json { "name": "A2A", "endpoint": "https://agent.example/.well-known/agent-card.json", "version": "0.3.0", "a2aSkills": ["analytical_skills/coding_skills/text_to_code"] } ``` **Fields**: * `endpoint` (string, REQUIRED): URL to agent card (SHOULD use `/.well-known/agent-card.json` path) * `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](https://a2a.to/) 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](https://github.com/agntcy/oasf/releases) **Schema Browser**: **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**: ```json { "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" ] } ``` **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 of `skills` or `domains` required) * `domains` (array, REQUIRED): OASF domain slugs (at least one of `skills` or `domains` required) **Skill Taxonomy**: OASF skills follow a hierarchical structure: ```text category / subcategory / specific_skill ↓ ↓ ↓ analytical_skills / data_analysis / blockchain_analysis ``` **Common Skills** (examples from [legacy testnet data](reference/sources.md#8-production-agent-metadata)): * `natural_language_processing/natural_language_generation/summarization` * `tool_interaction/api_schema_understanding` * `multi_modal/image_processing/text_to_image` * `natural_language_processing/information_retrieval_synthesis/search` * `tool_interaction/workflow_automation` **Domain Taxonomy**: OASF domains categorize agent application areas: ```text industry / sector / specialization ↓ ↓ ↓ finance_and_business / investment_services ``` **Common Domains** (examples from [legacy testnet data](reference/sources.md#8-production-agent-metadata)): * `technology/blockchain` * `finance_and_business/finance` * `technology/software_engineering/apis_integration` * `technology/blockchain/cryptocurrency` * `media_and_entertainment/content_creation` **Resources**: * [OASF Schema Browser](https://schema.oasf.outshift.com/0.8.0) * [Complete skill list](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * [Complete domain list](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 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): ```json { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ``` **Onchain Update** (v1.1.0): ```solidity // Update wallet with cryptographic verification (EIP-712 or ERC-1271) function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes calldata signature) external ``` **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**: ```text namespace : chainId : accountAddress ↓ ↓ ↓ eip155 : 1 : 0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7 ``` **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_format` warning * ⚠️ Invalid checksum: `wallet_invalid_checksum` warning **Multiple Wallets**: Agents can have wallets on multiple chains: ```json { "endpoints": [ { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" }, { "name": "agentWallet", "endpoint": "eip155:8453:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ] } ``` ### 5. ENS Name **Purpose**: Human-readable Ethereum Name Service identifier. **Structure**: ```json { "name": "ENS", "endpoint": "dataanalyst.eth", "version": "v1" } ``` **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**: ```json { "name": "DID", "endpoint": "did:ethr:0x1234567890abcdef1234567890abcdef12345678", "version": "v1" } ``` **Supported DID Methods**: * `did:ethr:...` - Ethereum DID * `did:web:...` - Web DID * `did:key:...` - Key DID **Fields**: * `endpoint` (string, REQUIRED): DID identifier * `version` (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**: ```json { "endpoints": [ { "name": "web", "endpoint": "https://myagent.example.com" }, { "name": "email", "endpoint": "support@myagent.example.com" } ] } ``` **Fields**: * `web` - Agent's public website or landing page * `email` - 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**: ```json { "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" } ``` **Example 2: Custom Protocol**: ```json { "name": "wallet", "endpoint": "eip155:11155111:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ``` **Guidelines**: * Use descriptive `name` field * Include `description` for 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**: ```json { "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"] } ``` **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_model` warning * ⚠️ Empty array: `empty_supported_trust` warning **Adoption** (from [legacy testnet data](reference/sources.md#8-production-agent-metadata)): See [Sources & References](reference/sources.md) for detailed adoption statistics. ### active (MAY) **Type**: `boolean` **Purpose**: Production readiness flag. **Structure**: ```json { "active": true } ``` **Values**: * `true` - Agent is production-ready and actively accepting requests * `false` - Agent is in development, testing, or inactive **Default**: `false` or `undefined` (inactive) **Validation**: * ⚠️ `active: false`: `agent_not_active` warning (not production-ready) * ⚠️ Non-boolean: `invalid_boolean_active` warning ### x402Support (MAY) **Type**: `boolean` **Purpose**: Indicates support for x402 payment protocol (HTTP 402 Payment Required). **Structure**: ```json { "x402Support": true } ``` **Values**: * `true` - Agent accepts x402 payment requests * `false` - Agent does not support x402 **Requirements**: If `x402Support: true`, agent SHOULD have an `agentWallet` endpoint defined. **Validation**: * ⚠️ Non-boolean: `invalid_boolean_x402` warning ### updatedAt (MAY) **Type**: `number` (Unix timestamp) **Purpose**: Last update timestamp for metadata freshness tracking. **Structure**: ```json { "updatedAt": 1763112328 } ``` **Format**: Unix timestamp (seconds since epoch) **Usage**: * Helps explorers show "last updated" time * Can be used for ranking/sorting by freshness **Example**: ```javascript // Generate current timestamp const updatedAt = Math.floor(Date.now() / 1000); ``` ## 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**: 1. **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 2. **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 3. **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**: ```text data:application/json;base64, ``` **Plain Format**: ```text data:application/json, ``` **Example (Base64)**: ```text data:application/json;base64,ewogICJ0eXBlIjogImh0dHBzOi8vZWlwcy5ldGhlcmV1bS5vcmcvRUlQUy9laXAtODAwNCNyZWdpc3RyYXRpb24tdjEiLAogICJuYW1lIjogIkFnZW50IE5hbWUiCn0= ``` **Example (Plain)**: ```text 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**: ```text ipfs://CID ipfs://CID/path/to/file.json ``` **Examples**: ```text ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4 ipfs://QmXXX/metadata.json ``` **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: 1. `https://ipfs.io/ipfs/{CID}` 2. `https://cloudflare-ipfs.com/ipfs/{CID}` 3. `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**: ```text ar://TX_ID ar://TX_ID/path ``` **Examples**: ```text ar://a1b2c3d4e5f6 ``` **Benefits**: * βœ… 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**: ```text https://example.com/metadata.json http://example.com/api/agent/123 ``` **Examples**: ```text https://cdn.example.com/agents/dataanalyst-pro.json https://api.example.com/v1/agents/241/metadata ``` **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**: ```text data:text/plain;base64, data:;base64, data:application/json;charset=utf-8;base64, ``` **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**: ```json { "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**: ```text data:application/json;enc=[;level=];base64, ``` **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](extensions/data-uri-compression.md). ## 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: ```solidity // Compute: keccak256(canonicalJSON) where keys are sorted alphabetically registry.setMetadata(agentId, "agentHash", abi.encodePacked(hash)); ``` **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: `"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 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-known` path **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](implementation/agent-metadata-parsing.md#validation-error-codes). ## Real-World Examples For examples of agent metadata formats observed in production deployments, see [Real-World Examples](reference/real-world-examples.md). ## Updating Agent Metadata ### Upgrading Metadata Version When updating agent metadata, increment `updatedAt` timestamp: **Before**: ```json { "name": "MyAgent v1", "updatedAt": 1763112328 } ``` **After**: ```json { "name": "MyAgent v2", "updatedAt": 1763200000 // ← New timestamp } ``` **On-Chain Update** (v1.1.0): > \[!NOTE] > `setAgentURI()` is exposed on the registry; callable by owner or approved operator; emits `URIUpdated`. ```solidity // Update agentURI on ERC-8004 registry (owner or approved) agentRegistry.setAgentURI(agentId, newAgentURI); ``` **Function Signature**: ```solidity function setAgentURI(uint256 agentId, string calldata newAgentURI) external; ``` **Requirements**: * Caller MUST be the agent owner or an approved operator * `agentId` MUST 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. 1. **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 99 ``` 2. **Phase 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..." } ] } ``` 3. **Phase 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..."); ``` 4. **Indexing**: 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 `registrations` array *** ## References ### Official Specifications * [EIP-8004: Trustless Agents](https://eips.ethereum.org/EIPS/eip-8004) * [CAIP-2: Chain ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) * [CAIP-10: Account ID Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) ### Protocol Documentation * [MCP Protocol](https://modelcontextprotocol.io/) * [A2A Protocol v0.3.0](https://a2a.to/) * [OASF v0.8.0 Taxonomy](https://github.com/agntcy/oasf/tree/v0.8.0) * [Schema Browser](https://schema.oasf.outshift.com/0.8.0) * [All Skills](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * [All Domains](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 8004scan Resources * [Agent Metadata Parsing Guide](implementation/agent-metadata-parsing.md) * [Feedback Standard](02-feedback-standard.md) * [Validation Standard](03-validation-standard.md) * [Sources & References](reference/sources.md) ## Changelog | Version | Date | Changes | | ------- | ---------- | --------------------------------------------------------------------------------------------------- | | **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](implementation/agent-metadata-parsing.md) * **Real-world usage** β†’ See [sources and examples](reference/sources.md) *** **Version**: 1.2 **Last Updated**: 2026-01-11 **Status**: Community Guidelines --- --- url: /docs/extensions/04-attachment-pattern-standard.md description: Reusable attachment schema for evidence and supporting documents --- ## Description Reusable attachment schema for evidence and supporting documents in ERC-8004 offchain data ## Document Purpose This document defines a **reusable attachment pattern** for including evidence files, receipts, and supporting documents in ERC-8004 offchain data structures. This pattern is shared across: * **Feedback Records** (Reputation Registry) * **Validation Requests** (Validation Registry) * **Validation Responses** (Validation Registry) **Terminology**: This document follows conventions defined in [Conventions](../00-CONVENTIONS.md). ## Table of Contents 1. [Overview](#overview) 2. [Attachment Object Schema](#attachment-object-schema) 3. [Field Reference](#field-reference) 4. [Implementation Requirements](#implementation-requirements) 5. [Use Cases and Examples](#use-cases-and-examples) 6. [Best Practices](#best-practices) 7. [Security Considerations](#security-considerations) ## Overview ### Purpose The Attachment Pattern provides a standardized way to reference external files in offchain data, enabling: * **Evidence Collection**: Supporting documents for feedback or validation claims * **Transparency**: Providing verifiable proof of service delivery or test results * **Rich Context**: Adding detailed information beyond JSON fields * **Flexibility**: Supporting any file type without schema changes ### Design Goals 1. **Simplicity**: Minimal required fields for easy adoption 2. **Extensibility**: Optional fields for rich metadata 3. **Interoperability**: Standard MIME types and URI schemes 4. **Backward Compatibility**: Unknown fields preserved for future extensions ### Inspiration This pattern was **inspired by the v1 frontend design** of 8004scan, which proved successful in production for feedback evidence collection. ## Attachment Object Schema ### Minimal Example (Required Fields Only) ```json { "name": "Service Receipt", "uri": "ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco", "mimeType": "application/pdf", "size": 245760 } ``` ### Full Example (All Fields) ```json { "name": "Portfolio Analysis Report", "uri": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4", "mimeType": "application/pdf", "size": 1536000, "description": "Detailed analysis report with recommendations for portfolio optimization", "uploadedAt": "2025-12-21T14:30:00Z" } ``` ### TypeScript Interface (Informative) ```typescript /** * Attachment file metadata for evidence and supporting documents * @see https://docs.8004scan.io/standards/attachment-pattern (coming soon) */ interface AttachmentFile { /** Display name of the file */ name: string; /** URI to the file content (IPFS, HTTPS, Arweave, Data URI) */ uri: string; /** IANA MIME type of the file */ mimeType: string; /** File size in bytes */ size: number; /** Optional context or explanation of the file's purpose */ description?: string; /** Optional timestamp when file was uploaded (ISO 8601 UTC) */ uploadedAt?: string; } ``` ## Field Reference ### Required Fields | Field | Type | Constraints | Description | | ---------- | -------- | ------------------- | ------------------------------------------------------------------------------------------------------------------ | | `name` | `string` | Length: 1–200 chars | Display name for the file. SHOULD be descriptive and human-readable. | | `uri` | `string` | Valid URI | Location of the file content. MUST use supported URI scheme (see [Conventions](../00-CONVENTIONS.md#uri-schemes)). | | `mimeType` | `string` | IANA MIME type | File type identifier. MUST be a valid MIME type (see [Conventions](../00-CONVENTIONS.md#mime-types)). | | `size` | `number` | `uint`, `β‰₯ 0` | File size in bytes. SHOULD be accurate to enable size validation and UI display. | ### Optional Fields | Field | Type | Constraints | Description | | ------------- | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `description` | `string` | Length: 0–1000 chars | Human-readable explanation of the file's purpose, context, or contents. | | `uploadedAt` | `string` | ISO 8601 UTC | Timestamp when the file was uploaded or created. MUST follow ISO 8601 format in UTC (see [Conventions](../00-CONVENTIONS.md#timestamp-format)). | ## Implementation Requirements ### For Data Producers (Clients, Validators) Implementations that **create** attachment data MUST: 1. βœ… **Include all required fields** (`name`, `uri`, `mimeType`, `size`) 2. βœ… **Use valid URI schemes** (see [Conventions](../00-CONVENTIONS.md#uri-schemes)) 3. βœ… **Provide accurate MIME types** (see [Conventions](../00-CONVENTIONS.md#mime-types)) 4. βœ… **Report correct file sizes** in bytes Implementations SHOULD: 1. 🟑 **Include `description`** for context and transparency 2. 🟑 **Include `uploadedAt`** for audit trails 3. 🟑 **Validate file accessibility** before submitting URIs 4. 🟑 **Use decentralized storage** (IPFS, Arweave) for permanence ### For Data Consumers (Explorers, Indexers, Clients) Implementations that **parse** attachment data MUST: 1. βœ… **Support all required fields** (`name`, `uri`, `mimeType`, `size`) 2. βœ… **Gracefully handle missing optional fields** 3. βœ… **Preserve unknown fields** for forward compatibility Implementations SHOULD: 1. 🟑 **Display optional fields** when present (`description`, `uploadedAt`) 2. 🟑 **Validate file sizes** against `size` field before download 3. 🟑 **Support multiple URI schemes** (at minimum: `https://`, `ipfs://`) 4. 🟑 **Provide MIME type icons** for visual file type identification 5. 🟑 **Warn users** about large files before download Implementations MAY: 1. βšͺ **Cache file metadata** for performance 2. βšͺ **Verify file integrity** using content hashes 3. βšͺ **Scan for malware** before displaying downloads 4. βšͺ **Generate thumbnails** for image/video files ## Use Cases and Examples ### Use Case 1: Service Receipt (Feedback) A client provides proof of service completion with their feedback. ```json { "attachments": [ { "name": "Service Receipt - Portfolio Analysis", "uri": "ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco", "mimeType": "application/pdf", "size": 245760, "description": "Invoice and deliverables for portfolio analysis service completed on 2025-12-20", "uploadedAt": "2025-12-20T15:00:00Z" } ] } ``` **Context**: Used in Feedback Standard's `attachments` array. ### Use Case 2: Chat Transcript (Feedback) A client provides communication logs as evidence of responsiveness. ```json { "attachments": [ { "name": "Chat Transcript", "uri": "https://storage.example.com/transcripts/session-abc123.txt", "mimeType": "text/plain", "size": 15360, "description": "Full conversation transcript showing agent responsiveness and professionalism" } ] } ``` **Context**: Used in Feedback Standard's `attachments` array. ### Use Case 3: Test Dataset (Validation Request) A client provides test data for the validator to use. ```json { "attachments": [ { "name": "Test Dataset - Portfolio Scenarios", "uri": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4", "mimeType": "application/json", "size": 50000, "description": "Sample portfolio data for testing rebalancing logic. Contains 10 realistic scenarios.", "uploadedAt": "2025-12-21T10:00:00Z" }, { "name": "Expected Outputs", "uri": "ipfs://bafkreib234...", "mimeType": "application/json", "size": 25000, "description": "Expected rebalancing recommendations for each test scenario" } ] } ``` **Context**: Used in Validation Request's `attachments` array. ### Use Case 4: Validation Proof (Validation Response) A validator provides test results and proof of validation. ```json { "attachments": [ { "name": "Test Results Summary", "uri": "https://validator.example.com/results/abc123.pdf", "mimeType": "application/pdf", "size": 512000, "description": "Comprehensive test report with pass/fail results for all scenarios" }, { "name": "Execution Logs", "uri": "ipfs://QmYyy...", "mimeType": "text/plain", "size": 102400, "description": "Raw execution logs from validation test runs" } ] } ``` **Context**: Used in Validation Response's `attachments` array. ### Use Case 5: zkSNARK Proof Circuit (Validation) A validator provides the proof circuit definition and public inputs. ```json { "attachments": [ { "name": "Circuit Definition", "uri": "ipfs://Qmcircuit...", "mimeType": "application/json", "size": 8192, "description": "ZyFi rebalancing validation circuit (Groth16 format)" }, { "name": "Public Inputs", "uri": "data:application/json;base64,eyJpbnB1dHMiOlsiNDE5MDgwNDQ0NSIsIjEiXX0=", "mimeType": "application/json", "size": 128, "description": "Public inputs for proof verification: [agentId, validationType]" } ] } ``` **Context**: Used in Validation Request/Response for zkSNARK validations. ### Use Case 6: Multiple File Types Combining different evidence types in a single record. ```json { "attachments": [ { "name": "Screenshot - Agent Response", "uri": "ipfs://QmImg...", "mimeType": "image/png", "size": 1024000, "description": "Screenshot of agent's analysis output" }, { "name": "Video Demonstration", "uri": "ar://video123...", "mimeType": "video/mp4", "size": 15728640, "description": "Screen recording of agent interaction session" }, { "name": "Raw Data Export", "uri": "ipfs://QmData...", "mimeType": "text/csv", "size": 204800, "description": "CSV export of agent's analysis results for verification" } ] } ``` **Context**: Demonstrates flexibility to support any file type. ## Best Practices ### For File Selection 1. **Relevance**: Only attach files directly relevant to the feedback/validation 2. **Size**: Keep total attachment size reasonable (< 10 MB per record recommended) 3. **Format**: Use widely-supported formats (PDF, PNG, JSON, CSV, TXT) 4. **Quality**: Ensure files are readable and not corrupted ### For URI Selection 1. **Permanence**: Prefer decentralized storage (IPFS, Arweave) over HTTPS for long-term availability 2. **Accessibility**: Ensure URIs are publicly accessible (no authentication required) 3. **Performance**: Use CDNs or IPFS gateways for faster access 4. **Backup**: Consider storing critical files on multiple platforms ### For MIME Types 1. **Accuracy**: Use correct MIME types matching actual file format 2. **Standards**: Use IANA-registered MIME types when possible 3. **Custom**: Use `application/x-` pattern for custom formats 4. **Fallback**: Use `application/octet-stream` only as last resort ### For Descriptions 1. **Clarity**: Explain what the file contains and why it's relevant 2. **Context**: Mention key details (date, purpose, format specifics) 3. **Brevity**: Keep descriptions concise (1-2 sentences) 4. **Audience**: Write for someone unfamiliar with the interaction ### For File Uploads 1. **Validation**: Check file size and type before uploading 2. **Naming**: Use descriptive filenames without special characters 3. **Metadata**: Include `uploadedAt` for audit trails 4. **Verification**: Test file accessibility after upload ## Security Considerations ### For Data Producers ⚠️ **Do NOT attach**: * Private keys or passwords * Personal identifiable information (PII) without consent * Confidential business data * Executable files (`.exe`, `.sh`, `.bat`) * Files with embedded malware βœ… **DO**: * Review file contents before attaching * Redact sensitive information * Use file integrity checks (hashes) * Warn about file size in descriptions ### For Data Consumers ⚠️ **Risks**: * **Malicious Content**: Files may contain malware or exploits * **Large Files**: May consume excessive bandwidth or storage * **External Links**: HTTPS URIs may become unavailable * **Privacy Leaks**: Files may contain unintended personal data βœ… **Mitigations**: * Scan downloaded files for malware * Implement size limits (e.g., warn if > 10 MB) * Sandbox file previews in isolated environments * Respect user privacy (don't auto-download) * Provide clear warnings before file access ### IPFS-Specific Considerations * **Content Persistence**: IPFS content may become unavailable if no nodes pin it * **Gateway Risks**: Public IPFS gateways may be rate-limited or blocked * **Content Addressing**: CIDs are unique, but content can still be malicious **Recommendations**: * Use multiple IPFS gateways for redundancy * Pin important content to ensure availability * Verify file integrity using CID ### Data URI Considerations * **Size**: Data URIs increase JSON size significantly * **Encoding**: Base64 encoding adds ~33% overhead * **Performance**: Large data URIs slow parsing and transfer **Recommendations**: * Only use data URIs for small files (< 1 KB) * Prefer external storage (IPFS/HTTPS) for larger files * Consider compression for data URIs (see [Data URI Compression Extension](data-uri-compression.md)) ## Validation Rules ### Field Validation **`name`**: * MUST NOT be empty string * SHOULD be 1–200 characters * SHOULD NOT contain path separators (`/`, `\`) * SHOULD be descriptive **`uri`**: * MUST be valid URI * MUST use supported scheme (`https://`, `ipfs://`, `ar://`, `data:`) * MUST NOT be relative path * SHOULD be accessible (reachable) **`mimeType`**: * MUST be valid MIME type format (`type/subtype`) * SHOULD be IANA-registered or use `x-` prefix for custom types * SHOULD match actual file content **`size`**: * MUST be non-negative integer * SHOULD accurately reflect file size * SHOULD be reasonable (< 100 MB recommended) **`description`** (optional): * SHOULD be 0–1000 characters * SHOULD be human-readable **`uploadedAt`** (optional): * MUST be valid ISO 8601 format * MUST be in UTC timezone (`Z` suffix) * SHOULD be reasonably recent ## Error Handling ### Missing Required Fields If a required field is missing: **Status**: `validation_error` **Code**: `attachment_missing_` **Example**: `attachment_missing_uri` **Behavior**: * Implementations MAY reject the entire record * Implementations MAY skip the invalid attachment but preserve others * Implementations SHOULD log the error ### Invalid Field Values If a field value is invalid: **Status**: `validation_warning` **Code**: `attachment_invalid_` **Example**: `attachment_invalid_mime_type` **Behavior**: * Implementations SHOULD accept the record with warning * Implementations SHOULD display warning in UI * Implementations MAY attempt to correct (e.g., infer MIME type) ### Unknown Fields If unknown fields are present: **Behavior**: * Implementations MUST NOT reject * Implementations SHOULD preserve unknown fields * Implementations MAY log informational message ## Migration and Compatibility ### Forward Compatibility This schema supports forward compatibility by: 1. Allowing unknown fields (MUST preserve) 2. Using optional fields for new features 3. Maintaining stable required field set ### Backward Compatibility Future versions of this standard will: * **NEVER** remove required fields * **NEVER** change field semantics without major version bump * **MAY** add new optional fields in minor versions * **MAY** promote optional fields to recommended in minor versions ### Versioning This Attachment Pattern Standard follows its own version number: **Current Version**: 1.0 Future versions referenced in documents will specify compatibility: * **1.x**: Fully compatible (new optional fields) * **2.x**: Breaking changes (read migration guide) ## References * **[Conventions](../00-CONVENTIONS.md)**: Shared terminology and format standards * **[Feedback Standard](../02-feedback-standard.md)**: Feedback record format using attachments * **[Validation Standard](../03-validation-standard.md)**: Validation record format using attachments * **[Data URI Compression Extension](data-uri-compression.md)**: Gas optimization for data URIs ## Appendix: Full Schema (Informative) ### JSON Schema (Draft-07) ```json { "$schema": "http://json-schema.org/draft-07/schema#", "title": "AttachmentFile", "description": "Attachment file metadata for ERC-8004 offchain data", "type": "object", "required": ["name", "uri", "mimeType", "size"], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Display name of the file" }, "uri": { "type": "string", "format": "uri", "description": "URI to the file content" }, "mimeType": { "type": "string", "pattern": "^[a-z]+/[a-z0-9.+-]+$", "description": "IANA MIME type of the file" }, "size": { "type": "integer", "minimum": 0, "description": "File size in bytes" }, "description": { "type": "string", "maxLength": 1000, "description": "Optional context or explanation" }, "uploadedAt": { "type": "string", "format": "date-time", "description": "Upload timestamp (ISO 8601 UTC)" } }, "additionalProperties": true } ``` --- --- url: /legacy-pre-v1/docs/04-attachment-pattern-standard.md description: Reusable attachment schema for evidence and supporting documents --- ## Description Reusable attachment schema for evidence and supporting documents in ERC-8004 offchain data ## Document Purpose This document defines a **reusable attachment pattern** for including evidence files, receipts, and supporting documents in ERC-8004 offchain data structures. This pattern is shared across: * **Feedback Records** (Reputation Registry) * **Validation Requests** (Validation Registry) * **Validation Responses** (Validation Registry) **Terminology**: This document follows conventions defined in [Conventions](00-CONVENTIONS.md). ## Table of Contents 1. [Overview](#overview) 2. [Attachment Object Schema](#attachment-object-schema) 3. [Field Reference](#field-reference) 4. [Implementation Requirements](#implementation-requirements) 5. [Use Cases and Examples](#use-cases-and-examples) 6. [Best Practices](#best-practices) 7. [Security Considerations](#security-considerations) ## Overview ### Purpose The Attachment Pattern provides a standardized way to reference external files in offchain data, enabling: * **Evidence Collection**: Supporting documents for feedback or validation claims * **Transparency**: Providing verifiable proof of service delivery or test results * **Rich Context**: Adding detailed information beyond JSON fields * **Flexibility**: Supporting any file type without schema changes ### Design Goals 1. **Simplicity**: Minimal required fields for easy adoption 2. **Extensibility**: Optional fields for rich metadata 3. **Interoperability**: Standard MIME types and URI schemes 4. **Backward Compatibility**: Unknown fields preserved for future extensions ### Inspiration This pattern was **inspired by the v1 frontend design** of 8004scan, which proved successful in production for feedback evidence collection. ## Attachment Object Schema ### Minimal Example (Required Fields Only) ```json { "name": "Service Receipt", "uri": "ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco", "mimeType": "application/pdf", "size": 245760 } ``` ### Full Example (All Fields) ```json { "name": "Portfolio Analysis Report", "uri": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4", "mimeType": "application/pdf", "size": 1536000, "description": "Detailed analysis report with recommendations for portfolio optimization", "uploadedAt": "2025-12-21T14:30:00Z" } ``` ### TypeScript Interface (Informative) ```typescript /** * Attachment file metadata for evidence and supporting documents * @see https://docs.8004scan.io/standards/attachment-pattern (coming soon) */ interface AttachmentFile { /** Display name of the file */ name: string; /** URI to the file content (IPFS, HTTPS, Arweave, Data URI) */ uri: string; /** IANA MIME type of the file */ mimeType: string; /** File size in bytes */ size: number; /** Optional context or explanation of the file's purpose */ description?: string; /** Optional timestamp when file was uploaded (ISO 8601 UTC) */ uploadedAt?: string; } ``` ## Field Reference ### Required Fields | Field | Type | Constraints | Description | | ---------- | -------- | ------------------- | --------------------------------------------------------------------------------------------------------------- | | `name` | `string` | Length: 1–200 chars | Display name for the file. SHOULD be descriptive and human-readable. | | `uri` | `string` | Valid URI | Location of the file content. MUST use supported URI scheme (see [Conventions](00-CONVENTIONS.md#uri-schemes)). | | `mimeType` | `string` | IANA MIME type | File type identifier. MUST be a valid MIME type (see [Conventions](00-CONVENTIONS.md#mime-types)). | | `size` | `number` | `uint`, `β‰₯ 0` | File size in bytes. SHOULD be accurate to enable size validation and UI display. | ### Optional Fields | Field | Type | Constraints | Description | | ------------- | -------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `description` | `string` | Length: 0–1000 chars | Human-readable explanation of the file's purpose, context, or contents. | | `uploadedAt` | `string` | ISO 8601 UTC | Timestamp when the file was uploaded or created. MUST follow ISO 8601 format in UTC (see [Conventions](00-CONVENTIONS.md#timestamp-format)). | ## Implementation Requirements ### For Data Producers (Clients, Validators) Implementations that **create** attachment data MUST: 1. βœ… **Include all required fields** (`name`, `uri`, `mimeType`, `size`) 2. βœ… **Use valid URI schemes** (see [Conventions](00-CONVENTIONS.md#uri-schemes)) 3. βœ… **Provide accurate MIME types** (see [Conventions](00-CONVENTIONS.md#mime-types)) 4. βœ… **Report correct file sizes** in bytes Implementations SHOULD: 1. 🟑 **Include `description`** for context and transparency 2. 🟑 **Include `uploadedAt`** for audit trails 3. 🟑 **Validate file accessibility** before submitting URIs 4. 🟑 **Use decentralized storage** (IPFS, Arweave) for permanence ### For Data Consumers (Explorers, Indexers, Clients) Implementations that **parse** attachment data MUST: 1. βœ… **Support all required fields** (`name`, `uri`, `mimeType`, `size`) 2. βœ… **Gracefully handle missing optional fields** 3. βœ… **Preserve unknown fields** for forward compatibility Implementations SHOULD: 1. 🟑 **Display optional fields** when present (`description`, `uploadedAt`) 2. 🟑 **Validate file sizes** against `size` field before download 3. 🟑 **Support multiple URI schemes** (at minimum: `https://`, `ipfs://`) 4. 🟑 **Provide MIME type icons** for visual file type identification 5. 🟑 **Warn users** about large files before download Implementations MAY: 1. βšͺ **Cache file metadata** for performance 2. βšͺ **Verify file integrity** using content hashes 3. βšͺ **Scan for malware** before displaying downloads 4. βšͺ **Generate thumbnails** for image/video files ## Use Cases and Examples ### Use Case 1: Service Receipt (Feedback) A client provides proof of service completion with their feedback. ```json { "attachments": [ { "name": "Service Receipt - Portfolio Analysis", "uri": "ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco", "mimeType": "application/pdf", "size": 245760, "description": "Invoice and deliverables for portfolio analysis service completed on 2025-12-20", "uploadedAt": "2025-12-20T15:00:00Z" } ] } ``` **Context**: Used in Feedback Standard's `attachments` array. ### Use Case 2: Chat Transcript (Feedback) A client provides communication logs as evidence of responsiveness. ```json { "attachments": [ { "name": "Chat Transcript", "uri": "https://storage.example.com/transcripts/session-abc123.txt", "mimeType": "text/plain", "size": 15360, "description": "Full conversation transcript showing agent responsiveness and professionalism" } ] } ``` **Context**: Used in Feedback Standard's `attachments` array. ### Use Case 3: Test Dataset (Validation Request) A client provides test data for the validator to use. ```json { "attachments": [ { "name": "Test Dataset - Portfolio Scenarios", "uri": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4", "mimeType": "application/json", "size": 50000, "description": "Sample portfolio data for testing rebalancing logic. Contains 10 realistic scenarios.", "uploadedAt": "2025-12-21T10:00:00Z" }, { "name": "Expected Outputs", "uri": "ipfs://bafkreib234...", "mimeType": "application/json", "size": 25000, "description": "Expected rebalancing recommendations for each test scenario" } ] } ``` **Context**: Used in Validation Request's `attachments` array. ### Use Case 4: Validation Proof (Validation Response) A validator provides test results and proof of validation. ```json { "attachments": [ { "name": "Test Results Summary", "uri": "https://validator.example.com/results/abc123.pdf", "mimeType": "application/pdf", "size": 512000, "description": "Comprehensive test report with pass/fail results for all scenarios" }, { "name": "Execution Logs", "uri": "ipfs://QmYyy...", "mimeType": "text/plain", "size": 102400, "description": "Raw execution logs from validation test runs" } ] } ``` **Context**: Used in Validation Response's `attachments` array. ### Use Case 5: zkSNARK Proof Circuit (Validation) A validator provides the proof circuit definition and public inputs. ```json { "attachments": [ { "name": "Circuit Definition", "uri": "ipfs://Qmcircuit...", "mimeType": "application/json", "size": 8192, "description": "ZyFi rebalancing validation circuit (Groth16 format)" }, { "name": "Public Inputs", "uri": "data:application/json;base64,eyJpbnB1dHMiOlsiNDE5MDgwNDQ0NSIsIjEiXX0=", "mimeType": "application/json", "size": 128, "description": "Public inputs for proof verification: [agentId, validationType]" } ] } ``` **Context**: Used in Validation Request/Response for zkSNARK validations. ### Use Case 6: Multiple File Types Combining different evidence types in a single record. ```json { "attachments": [ { "name": "Screenshot - Agent Response", "uri": "ipfs://QmImg...", "mimeType": "image/png", "size": 1024000, "description": "Screenshot of agent's analysis output" }, { "name": "Video Demonstration", "uri": "ar://video123...", "mimeType": "video/mp4", "size": 15728640, "description": "Screen recording of agent interaction session" }, { "name": "Raw Data Export", "uri": "ipfs://QmData...", "mimeType": "text/csv", "size": 204800, "description": "CSV export of agent's analysis results for verification" } ] } ``` **Context**: Demonstrates flexibility to support any file type. ## Best Practices ### For File Selection 1. **Relevance**: Only attach files directly relevant to the feedback/validation 2. **Size**: Keep total attachment size reasonable (< 10 MB per record recommended) 3. **Format**: Use widely-supported formats (PDF, PNG, JSON, CSV, TXT) 4. **Quality**: Ensure files are readable and not corrupted ### For URI Selection 1. **Permanence**: Prefer decentralized storage (IPFS, Arweave) over HTTPS for long-term availability 2. **Accessibility**: Ensure URIs are publicly accessible (no authentication required) 3. **Performance**: Use CDNs or IPFS gateways for faster access 4. **Backup**: Consider storing critical files on multiple platforms ### For MIME Types 1. **Accuracy**: Use correct MIME types matching actual file format 2. **Standards**: Use IANA-registered MIME types when possible 3. **Custom**: Use `application/x-` pattern for custom formats 4. **Fallback**: Use `application/octet-stream` only as last resort ### For Descriptions 1. **Clarity**: Explain what the file contains and why it's relevant 2. **Context**: Mention key details (date, purpose, format specifics) 3. **Brevity**: Keep descriptions concise (1-2 sentences) 4. **Audience**: Write for someone unfamiliar with the interaction ### For File Uploads 1. **Validation**: Check file size and type before uploading 2. **Naming**: Use descriptive filenames without special characters 3. **Metadata**: Include `uploadedAt` for audit trails 4. **Verification**: Test file accessibility after upload ## Security Considerations ### For Data Producers ⚠️ **Do NOT attach**: * Private keys or passwords * Personal identifiable information (PII) without consent * Confidential business data * Executable files (`.exe`, `.sh`, `.bat`) * Files with embedded malware βœ… **DO**: * Review file contents before attaching * Redact sensitive information * Use file integrity checks (hashes) * Warn about file size in descriptions ### For Data Consumers ⚠️ **Risks**: * **Malicious Content**: Files may contain malware or exploits * **Large Files**: May consume excessive bandwidth or storage * **External Links**: HTTPS URIs may become unavailable * **Privacy Leaks**: Files may contain unintended personal data βœ… **Mitigations**: * Scan downloaded files for malware * Implement size limits (e.g., warn if > 10 MB) * Sandbox file previews in isolated environments * Respect user privacy (don't auto-download) * Provide clear warnings before file access ### IPFS-Specific Considerations * **Content Persistence**: IPFS content may become unavailable if no nodes pin it * **Gateway Risks**: Public IPFS gateways may be rate-limited or blocked * **Content Addressing**: CIDs are unique, but content can still be malicious **Recommendations**: * Use multiple IPFS gateways for redundancy * Pin important content to ensure availability * Verify file integrity using CID ### Data URI Considerations * **Size**: Data URIs increase JSON size significantly * **Encoding**: Base64 encoding adds ~33% overhead * **Performance**: Large data URIs slow parsing and transfer **Recommendations**: * Only use data URIs for small files (< 1 KB) * Prefer external storage (IPFS/HTTPS) for larger files * Consider compression for data URIs (see [Data URI Compression Extension](extensions/data-uri-compression.md)) ## Validation Rules ### Field Validation **`name`**: * MUST NOT be empty string * SHOULD be 1–200 characters * SHOULD NOT contain path separators (`/`, `\`) * SHOULD be descriptive **`uri`**: * MUST be valid URI * MUST use supported scheme (`https://`, `ipfs://`, `ar://`, `data:`) * MUST NOT be relative path * SHOULD be accessible (reachable) **`mimeType`**: * MUST be valid MIME type format (`type/subtype`) * SHOULD be IANA-registered or use `x-` prefix for custom types * SHOULD match actual file content **`size`**: * MUST be non-negative integer * SHOULD accurately reflect file size * SHOULD be reasonable (< 100 MB recommended) **`description`** (optional): * SHOULD be 0–1000 characters * SHOULD be human-readable **`uploadedAt`** (optional): * MUST be valid ISO 8601 format * MUST be in UTC timezone (`Z` suffix) * SHOULD be reasonably recent ## Error Handling ### Missing Required Fields If a required field is missing: **Status**: `validation_error` **Code**: `attachment_missing_` **Example**: `attachment_missing_uri` **Behavior**: * Implementations MAY reject the entire record * Implementations MAY skip the invalid attachment but preserve others * Implementations SHOULD log the error ### Invalid Field Values If a field value is invalid: **Status**: `validation_warning` **Code**: `attachment_invalid_` **Example**: `attachment_invalid_mime_type` **Behavior**: * Implementations SHOULD accept the record with warning * Implementations SHOULD display warning in UI * Implementations MAY attempt to correct (e.g., infer MIME type) ### Unknown Fields If unknown fields are present: **Behavior**: * Implementations MUST NOT reject * Implementations SHOULD preserve unknown fields * Implementations MAY log informational message ## Migration and Compatibility ### Forward Compatibility This schema supports forward compatibility by: 1. Allowing unknown fields (MUST preserve) 2. Using optional fields for new features 3. Maintaining stable required field set ### Backward Compatibility Future versions of this standard will: * **NEVER** remove required fields * **NEVER** change field semantics without major version bump * **MAY** add new optional fields in minor versions * **MAY** promote optional fields to recommended in minor versions ### Versioning This Attachment Pattern Standard follows its own version number: **Current Version**: 1.0 Future versions referenced in documents will specify compatibility: * **1.x**: Fully compatible (new optional fields) * **2.x**: Breaking changes (read migration guide) ## References * **[Conventions](00-CONVENTIONS.md)**: Shared terminology and format standards * **[Feedback Standard](02-feedback-standard.md)**: Feedback record format using attachments * **[Validation Standard](03-validation-standard.md)**: Validation record format using attachments * **[Data URI Compression Extension](extensions/data-uri-compression.md)**: Gas optimization for data URIs ## Appendix: Full Schema (Informative) ### JSON Schema (Draft-07) ```json { "$schema": "http://json-schema.org/draft-07/schema#", "title": "AttachmentFile", "description": "Attachment file metadata for ERC-8004 offchain data", "type": "object", "required": ["name", "uri", "mimeType", "size"], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Display name of the file" }, "uri": { "type": "string", "format": "uri", "description": "URI to the file content" }, "mimeType": { "type": "string", "pattern": "^[a-z]+/[a-z0-9.+-]+$", "description": "IANA MIME type of the file" }, "size": { "type": "integer", "minimum": 0, "description": "File size in bytes" }, "description": { "type": "string", "maxLength": 1000, "description": "Optional context or explanation" }, "uploadedAt": { "type": "string", "format": "date-time", "description": "Upload timestamp (ISO 8601 UTC)" } }, "additionalProperties": true } ``` --- --- url: /v1/docs/extensions/04-attachment-pattern-standard.md description: Reusable attachment schema for evidence and supporting documents --- ## Description Reusable attachment schema for evidence and supporting documents in ERC-8004 offchain data ## Document Purpose This document defines a **reusable attachment pattern** for including evidence files, receipts, and supporting documents in ERC-8004 offchain data structures. This pattern is shared across: * **Feedback Records** (Reputation Registry) * **Validation Requests** (Validation Registry) * **Validation Responses** (Validation Registry) **Terminology**: This document follows conventions defined in [Conventions](../00-CONVENTIONS.md). ## Table of Contents 1. [Overview](#overview) 2. [Attachment Object Schema](#attachment-object-schema) 3. [Field Reference](#field-reference) 4. [Implementation Requirements](#implementation-requirements) 5. [Use Cases and Examples](#use-cases-and-examples) 6. [Best Practices](#best-practices) 7. [Security Considerations](#security-considerations) ## Overview ### Purpose The Attachment Pattern provides a standardized way to reference external files in offchain data, enabling: * **Evidence Collection**: Supporting documents for feedback or validation claims * **Transparency**: Providing verifiable proof of service delivery or test results * **Rich Context**: Adding detailed information beyond JSON fields * **Flexibility**: Supporting any file type without schema changes ### Design Goals 1. **Simplicity**: Minimal required fields for easy adoption 2. **Extensibility**: Optional fields for rich metadata 3. **Interoperability**: Standard MIME types and URI schemes 4. **Backward Compatibility**: Unknown fields preserved for future extensions ### Inspiration This pattern was **inspired by the v1 frontend design** of 8004scan, which proved successful in production for feedback evidence collection. ## Attachment Object Schema ### Minimal Example (Required Fields Only) ```json { "name": "Service Receipt", "uri": "ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco", "mimeType": "application/pdf", "size": 245760 } ``` ### Full Example (All Fields) ```json { "name": "Portfolio Analysis Report", "uri": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4", "mimeType": "application/pdf", "size": 1536000, "description": "Detailed analysis report with recommendations for portfolio optimization", "uploadedAt": "2025-12-21T14:30:00Z" } ``` ### TypeScript Interface (Informative) ```typescript /** * Attachment file metadata for evidence and supporting documents * @see https://docs.8004scan.io/standards/attachment-pattern (coming soon) */ interface AttachmentFile { /** Display name of the file */ name: string; /** URI to the file content (IPFS, HTTPS, Arweave, Data URI) */ uri: string; /** IANA MIME type of the file */ mimeType: string; /** File size in bytes */ size: number; /** Optional context or explanation of the file's purpose */ description?: string; /** Optional timestamp when file was uploaded (ISO 8601 UTC) */ uploadedAt?: string; } ``` ## Field Reference ### Required Fields | Field | Type | Constraints | Description | | ---------- | -------- | ------------------- | ------------------------------------------------------------------------------------------------------------------ | | `name` | `string` | Length: 1–200 chars | Display name for the file. SHOULD be descriptive and human-readable. | | `uri` | `string` | Valid URI | Location of the file content. MUST use supported URI scheme (see [Conventions](../00-CONVENTIONS.md#uri-schemes)). | | `mimeType` | `string` | IANA MIME type | File type identifier. MUST be a valid MIME type (see [Conventions](../00-CONVENTIONS.md#mime-types)). | | `size` | `number` | `uint`, `β‰₯ 0` | File size in bytes. SHOULD be accurate to enable size validation and UI display. | ### Optional Fields | Field | Type | Constraints | Description | | ------------- | -------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `description` | `string` | Length: 0–1000 chars | Human-readable explanation of the file's purpose, context, or contents. | | `uploadedAt` | `string` | ISO 8601 UTC | Timestamp when the file was uploaded or created. MUST follow ISO 8601 format in UTC (see [Conventions](../00-CONVENTIONS.md#timestamp-format)). | ## Implementation Requirements ### For Data Producers (Clients, Validators) Implementations that **create** attachment data MUST: 1. βœ… **Include all required fields** (`name`, `uri`, `mimeType`, `size`) 2. βœ… **Use valid URI schemes** (see [Conventions](../00-CONVENTIONS.md#uri-schemes)) 3. βœ… **Provide accurate MIME types** (see [Conventions](../00-CONVENTIONS.md#mime-types)) 4. βœ… **Report correct file sizes** in bytes Implementations SHOULD: 1. 🟑 **Include `description`** for context and transparency 2. 🟑 **Include `uploadedAt`** for audit trails 3. 🟑 **Validate file accessibility** before submitting URIs 4. 🟑 **Use decentralized storage** (IPFS, Arweave) for permanence ### For Data Consumers (Explorers, Indexers, Clients) Implementations that **parse** attachment data MUST: 1. βœ… **Support all required fields** (`name`, `uri`, `mimeType`, `size`) 2. βœ… **Gracefully handle missing optional fields** 3. βœ… **Preserve unknown fields** for forward compatibility Implementations SHOULD: 1. 🟑 **Display optional fields** when present (`description`, `uploadedAt`) 2. 🟑 **Validate file sizes** against `size` field before download 3. 🟑 **Support multiple URI schemes** (at minimum: `https://`, `ipfs://`) 4. 🟑 **Provide MIME type icons** for visual file type identification 5. 🟑 **Warn users** about large files before download Implementations MAY: 1. βšͺ **Cache file metadata** for performance 2. βšͺ **Verify file integrity** using content hashes 3. βšͺ **Scan for malware** before displaying downloads 4. βšͺ **Generate thumbnails** for image/video files ## Use Cases and Examples ### Use Case 1: Service Receipt (Feedback) A client provides proof of service completion with their feedback. ```json { "attachments": [ { "name": "Service Receipt - Portfolio Analysis", "uri": "ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco", "mimeType": "application/pdf", "size": 245760, "description": "Invoice and deliverables for portfolio analysis service completed on 2025-12-20", "uploadedAt": "2025-12-20T15:00:00Z" } ] } ``` **Context**: Used in Feedback Standard's `attachments` array. ### Use Case 2: Chat Transcript (Feedback) A client provides communication logs as evidence of responsiveness. ```json { "attachments": [ { "name": "Chat Transcript", "uri": "https://storage.example.com/transcripts/session-abc123.txt", "mimeType": "text/plain", "size": 15360, "description": "Full conversation transcript showing agent responsiveness and professionalism" } ] } ``` **Context**: Used in Feedback Standard's `attachments` array. ### Use Case 3: Test Dataset (Validation Request) A client provides test data for the validator to use. ```json { "attachments": [ { "name": "Test Dataset - Portfolio Scenarios", "uri": "ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4", "mimeType": "application/json", "size": 50000, "description": "Sample portfolio data for testing rebalancing logic. Contains 10 realistic scenarios.", "uploadedAt": "2025-12-21T10:00:00Z" }, { "name": "Expected Outputs", "uri": "ipfs://bafkreib234...", "mimeType": "application/json", "size": 25000, "description": "Expected rebalancing recommendations for each test scenario" } ] } ``` **Context**: Used in Validation Request's `attachments` array. ### Use Case 4: Validation Proof (Validation Response) A validator provides test results and proof of validation. ```json { "attachments": [ { "name": "Test Results Summary", "uri": "https://validator.example.com/results/abc123.pdf", "mimeType": "application/pdf", "size": 512000, "description": "Comprehensive test report with pass/fail results for all scenarios" }, { "name": "Execution Logs", "uri": "ipfs://QmYyy...", "mimeType": "text/plain", "size": 102400, "description": "Raw execution logs from validation test runs" } ] } ``` **Context**: Used in Validation Response's `attachments` array. ### Use Case 5: zkSNARK Proof Circuit (Validation) A validator provides the proof circuit definition and public inputs. ```json { "attachments": [ { "name": "Circuit Definition", "uri": "ipfs://Qmcircuit...", "mimeType": "application/json", "size": 8192, "description": "ZyFi rebalancing validation circuit (Groth16 format)" }, { "name": "Public Inputs", "uri": "data:application/json;base64,eyJpbnB1dHMiOlsiNDE5MDgwNDQ0NSIsIjEiXX0=", "mimeType": "application/json", "size": 128, "description": "Public inputs for proof verification: [agentId, validationType]" } ] } ``` **Context**: Used in Validation Request/Response for zkSNARK validations. ### Use Case 6: Multiple File Types Combining different evidence types in a single record. ```json { "attachments": [ { "name": "Screenshot - Agent Response", "uri": "ipfs://QmImg...", "mimeType": "image/png", "size": 1024000, "description": "Screenshot of agent's analysis output" }, { "name": "Video Demonstration", "uri": "ar://video123...", "mimeType": "video/mp4", "size": 15728640, "description": "Screen recording of agent interaction session" }, { "name": "Raw Data Export", "uri": "ipfs://QmData...", "mimeType": "text/csv", "size": 204800, "description": "CSV export of agent's analysis results for verification" } ] } ``` **Context**: Demonstrates flexibility to support any file type. ## Best Practices ### For File Selection 1. **Relevance**: Only attach files directly relevant to the feedback/validation 2. **Size**: Keep total attachment size reasonable (< 10 MB per record recommended) 3. **Format**: Use widely-supported formats (PDF, PNG, JSON, CSV, TXT) 4. **Quality**: Ensure files are readable and not corrupted ### For URI Selection 1. **Permanence**: Prefer decentralized storage (IPFS, Arweave) over HTTPS for long-term availability 2. **Accessibility**: Ensure URIs are publicly accessible (no authentication required) 3. **Performance**: Use CDNs or IPFS gateways for faster access 4. **Backup**: Consider storing critical files on multiple platforms ### For MIME Types 1. **Accuracy**: Use correct MIME types matching actual file format 2. **Standards**: Use IANA-registered MIME types when possible 3. **Custom**: Use `application/x-` pattern for custom formats 4. **Fallback**: Use `application/octet-stream` only as last resort ### For Descriptions 1. **Clarity**: Explain what the file contains and why it's relevant 2. **Context**: Mention key details (date, purpose, format specifics) 3. **Brevity**: Keep descriptions concise (1-2 sentences) 4. **Audience**: Write for someone unfamiliar with the interaction ### For File Uploads 1. **Validation**: Check file size and type before uploading 2. **Naming**: Use descriptive filenames without special characters 3. **Metadata**: Include `uploadedAt` for audit trails 4. **Verification**: Test file accessibility after upload ## Security Considerations ### For Data Producers ⚠️ **Do NOT attach**: * Private keys or passwords * Personal identifiable information (PII) without consent * Confidential business data * Executable files (`.exe`, `.sh`, `.bat`) * Files with embedded malware βœ… **DO**: * Review file contents before attaching * Redact sensitive information * Use file integrity checks (hashes) * Warn about file size in descriptions ### For Data Consumers ⚠️ **Risks**: * **Malicious Content**: Files may contain malware or exploits * **Large Files**: May consume excessive bandwidth or storage * **External Links**: HTTPS URIs may become unavailable * **Privacy Leaks**: Files may contain unintended personal data βœ… **Mitigations**: * Scan downloaded files for malware * Implement size limits (e.g., warn if > 10 MB) * Sandbox file previews in isolated environments * Respect user privacy (don't auto-download) * Provide clear warnings before file access ### IPFS-Specific Considerations * **Content Persistence**: IPFS content may become unavailable if no nodes pin it * **Gateway Risks**: Public IPFS gateways may be rate-limited or blocked * **Content Addressing**: CIDs are unique, but content can still be malicious **Recommendations**: * Use multiple IPFS gateways for redundancy * Pin important content to ensure availability * Verify file integrity using CID ### Data URI Considerations * **Size**: Data URIs increase JSON size significantly * **Encoding**: Base64 encoding adds ~33% overhead * **Performance**: Large data URIs slow parsing and transfer **Recommendations**: * Only use data URIs for small files (< 1 KB) * Prefer external storage (IPFS/HTTPS) for larger files * Consider compression for data URIs (see [Data URI Compression Extension](data-uri-compression.md)) ## Validation Rules ### Field Validation **`name`**: * MUST NOT be empty string * SHOULD be 1–200 characters * SHOULD NOT contain path separators (`/`, `\`) * SHOULD be descriptive **`uri`**: * MUST be valid URI * MUST use supported scheme (`https://`, `ipfs://`, `ar://`, `data:`) * MUST NOT be relative path * SHOULD be accessible (reachable) **`mimeType`**: * MUST be valid MIME type format (`type/subtype`) * SHOULD be IANA-registered or use `x-` prefix for custom types * SHOULD match actual file content **`size`**: * MUST be non-negative integer * SHOULD accurately reflect file size * SHOULD be reasonable (< 100 MB recommended) **`description`** (optional): * SHOULD be 0–1000 characters * SHOULD be human-readable **`uploadedAt`** (optional): * MUST be valid ISO 8601 format * MUST be in UTC timezone (`Z` suffix) * SHOULD be reasonably recent ## Error Handling ### Missing Required Fields If a required field is missing: **Status**: `validation_error` **Code**: `attachment_missing_` **Example**: `attachment_missing_uri` **Behavior**: * Implementations MAY reject the entire record * Implementations MAY skip the invalid attachment but preserve others * Implementations SHOULD log the error ### Invalid Field Values If a field value is invalid: **Status**: `validation_warning` **Code**: `attachment_invalid_` **Example**: `attachment_invalid_mime_type` **Behavior**: * Implementations SHOULD accept the record with warning * Implementations SHOULD display warning in UI * Implementations MAY attempt to correct (e.g., infer MIME type) ### Unknown Fields If unknown fields are present: **Behavior**: * Implementations MUST NOT reject * Implementations SHOULD preserve unknown fields * Implementations MAY log informational message ## Migration and Compatibility ### Forward Compatibility This schema supports forward compatibility by: 1. Allowing unknown fields (MUST preserve) 2. Using optional fields for new features 3. Maintaining stable required field set ### Backward Compatibility Future versions of this standard will: * **NEVER** remove required fields * **NEVER** change field semantics without major version bump * **MAY** add new optional fields in minor versions * **MAY** promote optional fields to recommended in minor versions ### Versioning This Attachment Pattern Standard follows its own version number: **Current Version**: 1.0 Future versions referenced in documents will specify compatibility: * **1.x**: Fully compatible (new optional fields) * **2.x**: Breaking changes (read migration guide) ## References * **[Conventions](../00-CONVENTIONS.md)**: Shared terminology and format standards * **[Feedback Standard](../02-feedback-standard.md)**: Feedback record format using attachments * **[Validation Standard](../03-validation-standard.md)**: Validation record format using attachments * **[Data URI Compression Extension](data-uri-compression.md)**: Gas optimization for data URIs ## Appendix: Full Schema (Informative) ### JSON Schema (Draft-07) ```json { "$schema": "http://json-schema.org/draft-07/schema#", "title": "AttachmentFile", "description": "Attachment file metadata for ERC-8004 offchain data", "type": "object", "required": ["name", "uri", "mimeType", "size"], "properties": { "name": { "type": "string", "minLength": 1, "maxLength": 200, "description": "Display name of the file" }, "uri": { "type": "string", "format": "uri", "description": "URI to the file content" }, "mimeType": { "type": "string", "pattern": "^[a-z]+/[a-z0-9.+-]+$", "description": "IANA MIME type of the file" }, "size": { "type": "integer", "minimum": 0, "description": "File size in bytes" }, "description": { "type": "string", "maxLength": 1000, "description": "Optional context or explanation" }, "uploadedAt": { "type": "string", "format": "date-time", "description": "Upload timestamp (ISO 8601 UTC)" } }, "additionalProperties": true } ``` --- --- url: /CHANGELOG_v1.0.md --- # Changelog: ERC-8004 Documentation Update to v1.1 **Date**: January 9, 2026 **Type**: Major Documentation Update **Status**: Ready for Deployment ## Summary Updated ERC-8004 documentation to reflect the v1.1 specification (January 2026) with full support for multiple documentation versions. ## What's New ### 1. βœ… v1.1 Documentation Updates #### Core Changes Implemented * **Tag Type Migration**: `bytes32` β†’ `string` (direct strings, no encoding) * **URI Naming**: `feedbackUri` β†’ `feedbackURI` (consistent camelCase) * **FeedbackAuth Removal**: Deprecated entire pre-authorization flow * **Endpoint Field**: Added optional `endpoint` field for service tracking * **Index Handling**: `feedbackIndex` now emitted from event (no calculation needed) #### Updated Files 1. **[docs/02-feedback-standard.md](docs/02-feedback-standard.md)** * Updated version metadata: v2.0 β†’ v1.1 * Added pre-v1 (legacy) β†’ v1.1 comparison table * Removed `feedbackAuth` field documentation * Updated all examples to remove `feedbackAuth` * Added `endpoint` field to schema and examples * Updated onchain event signatures * Marked Authorization section as DEPRECATED * Added version selector banner ### 2. βœ… Multi-Version Support #### Archive Structure ```text root/ β”œβ”€β”€ docs/ # v1.1 (latest) β”œβ”€β”€ legacy-pre-v1/ # pre-v1 (legacy archive) β”‚ β”œβ”€β”€ docs/ # Archived pre-v1 docs β”‚ β”œβ”€β”€ .vitepress/ # Separate pre-v1 config β”‚ └── README.md # pre-v1 archive info β”œβ”€β”€ VERSION.md # Version selector page └── .vitepress/ └── config.mts # Updated with version nav ``` #### Version Navigation * Added "v1.1" dropdown in main navbar * Links to v1.1 (latest) and pre-v1 (legacy archive) * Version selector page at `/VERSION.md` * Cross-links between versions ### 3. βœ… Migration Guide Created comprehensive [Migration Guide: pre-v1 (legacy) β†’ v1.1](docs/implementation/migration-v0-4-to-v1-0.md) **Contents**: * Overview of all breaking changes * Data format comparisons (side-by-side examples) * Code migration checklist (Frontend, Backend, API) * TypeScript/React examples * GraphQL query updates * FAQ for common questions * Timeline recommendations ### 4. βœ… Configuration Updates #### VitePress Main Config (`.vitepress/config.mts`) * Added version selector dropdown to nav * Added Implementation section to sidebar * Added Migration Guide to implementation section * Maintained backwards compatibility #### pre-v1 VitePress Config (`legacy-pre-v1/.vitepress/config.mts`) * Standalone pre-v1 documentation configuration * Version navigation back to v1.1 * Separate base path: `/legacy-pre-v1/` ### 5. βœ… New Files Created | File | Purpose | | ----------------------------------------------- | ----------------------------------------- | | `VERSION.md` | Version selection and information page | | `docs/implementation/migration-v0-4-to-v1-0.md` | Complete migration guide | | `legacy-pre-v1/README.md` | pre-v1 archive information | | `legacy-pre-v1/.vitepress/config.mts` | pre-v1 documentation config | | `legacy-pre-v1/docs/*` | Archived pre-v1 documentation (full copy) | ## Key Changes Reference ### Onchain Field Changes | Field | pre-v1 (legacy) | v1.1 | Breaking | | --------------- | --------------- | ---------- | ----------- | | `tag1` | `bytes32` | `string` | βœ… YES | | `tag2` | `bytes32` | `string` | βœ… YES | | `feedbackUri` | String | Renamed | βœ… YES | | `feedbackURI` | - | String | βœ… New | | `endpoint` | - | String | ⚠️ Addition | | `feedbackAuth` | Required | Removed | βœ… YES | | `feedbackIndex` | Calculated | From event | ⚠️ Changed | ### Offchain Data Format **pre-v1 (legacy) Example**: ```json { "feedbackAuth": "0xabc123...", "tag1": "6465666900000...", "tag2": "616e616c7974...", "feedbackUri": "ipfs://QmXxx..." } ``` **v1.1 Example**: ```json { "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.example.com/v1", "feedbackURI": "ipfs://QmXxx..." } ``` ## Integration Points ### For Documentation Site Builders 1. Build both v1.1 and pre-v1 documentation 2. Deploy to separate paths: * v1.1: `/` or `/docs/` * pre-v1: `/legacy-pre-v1/` 3. Use version selector in navbar for navigation ### For API/Backend Developers * See [Migration Guide](docs/implementation/migration-v0-4-to-v1-0.md#backend-updates) * Update feedback submission endpoints * Remove `feedbackAuth` validation * Add support for `endpoint` field (optional) ### For Frontend Developers * See [Migration Guide](docs/implementation/migration-v0-4-to-v1-0.md#frontend-updates) * Simplify feedback form (remove auth UI) * Update tag inputs (string instead of hex) * Add optional `endpoint` field ## Testing Checklist * βœ… Verified v1.1 documentation completeness * βœ… Created pre-v1 (legacy) archive with full history * βœ… Tested version navigation structure * βœ… Validated markdown syntax and links * βœ… Verified migration guide accuracy * βœ… Checked cross-version references * βœ… Confirmed all examples are current ## Deployment Instructions ### Step 1: Build Documentation ```bash npm run build # Builds main v1.1 docs ``` ### Step 2: Build pre-v1 Archive (Optional) ```bash cd legacy-pre-v1 npm run build # Builds pre-v1 docs separately ``` ### Step 3: Deploy * Deploy main docs to `best-practices.8004scan.io/` * Deploy pre-v1 to `best-practices.8004scan.io/legacy-pre-v1/` * Configure DNS/reverse proxy as needed ## References * [Official ERC-8004 Spec](https://eips.ethereum.org/EIPS/eip-8004) * [Contract PR #11](https://github.com/erc-8004/erc-8004-contracts/pull/11) * [Spec Changes Guide](https://github.com/erc-8004/erc-8004-contracts/blob/main/SpecsJan26Update.md) * [Migration Guide](https://best-practices.8004scan.io/docs/implementation/migration-v0-4-to-v1-0) ## Files Modified ```text .vitepress/config.mts # Updated nav and sidebar docs/02-feedback-standard.md # v1.1 updates ``` ## Files Added ```text VERSION.md # Version selector docs/implementation/migration-v0-4-to-v1-0.md # Migration guide legacy-pre-v1/README.md # Archive info legacy-pre-v1/.vitepress/config.mts # pre-v1 config legacy-pre-v1/docs/ # pre-v1 archive (6 subdirs) ``` ## Next Steps 1. Review all changes in PR 2. Verify documentation builds correctly 3. Test version switching in deployed site 4. Update main README if needed 5. Announce v1.1 documentation availability 6. Update SDK documentation (if applicable) ## Notes * pre-v1 (legacy) documentation is **read-only** archival content * All new development should target v1.1 * Migration guide provides clear path for pre-v1 users * Version selector makes it easy to find relevant docs *** **Documentation Version**: 1.0.0 **Last Updated**: January 9, 2026 **Status**: Ready for Production Deployment --- --- url: /CONTRIBUTING.md --- # Contributing to ERC-8004 Documentation Thank you for your interest in contributing to the ERC-8004 documentation! ## How to Contribute ### Reporting Issues If you find errors, inconsistencies, or have suggestions for improvements: 1. Check if the issue already exists in the issue tracker 2. Create a new issue with a clear description 3. Include specific file references and line numbers if applicable ### Submitting Changes 1. **Fork the repository** 2. **Create a feature branch** ```bash git checkout -b feature/your-feature-name ``` 3. **Make your changes** * Follow the existing document structure and style * Ensure all links work correctly * Use proper markdown formatting 4. **Format and lint your changes** ```bash # Auto-format all Markdown files make format # Check for linting issues make lint # Auto-fix linting issues make lint-fix ``` 5. **Test locally** ```bash make install make dev ``` The development server will open automatically at localhost:5173 6. **Commit your changes** ```bash git add . git commit -m "Brief description of changes" ``` 7. **Push to your fork** ```bash git push origin feature/your-feature-name ``` 8. **Create a Pull Request** * Provide a clear description of your changes * Reference any related issues ## Documentation Standards ### File Naming * Use lowercase with hyphens for file names: `my-document.md` * Exception: Special files use UPPERCASE: `README.md`, `CONTRIBUTING.md`, `LICENSE` * Number prefixes for sequential documents: `01-first-topic.md`, `02-second-topic.md` ### Writing Style * Use clear, concise language * Include code examples where appropriate * Add links to related sections * Keep line length reasonable (around 80-100 characters) ### Markdown Guidelines * Use ATX-style headers (`#` instead of underlines) * Include blank lines before and after headers * Use fenced code blocks with language specifiers * Use relative links for internal documentation ### Code Examples ```markdown \`\`\`solidity // Include language identifier function example() public returns (bool) { return true; } \`\`\` ``` ## Formatting and Linting This project uses **Prettier** for automatic formatting and **markdownlint** for linting Markdown files. ### Formatting Tools **Prettier** automatically handles: * Removing trailing spaces * Normalizing blank lines * Formatting tables * Consistent line breaks **markdownlint** ensures: * Consistent heading styles * Proper list formatting * No duplicate headings at the same level * Compliance with Markdown best practices ### Usage ```bash # Format all Markdown files (auto-fix formatting) make format # Check formatting without modifying files make format-check # Lint Markdown files make lint # Auto-fix linting issues make lint-fix ``` ### Before Committing Always run formatting and linting before committing: ```bash make format && make lint-fix ``` This ensures consistent formatting across all documentation. ## Building the Documentation ### Prerequisites * Node.js (v18 or higher) * npm (v9 or higher) ### Build Commands ```bash # Install dependencies make install # Start development server (with hot reload) make dev # Build static site make build # Preview built site make preview # Clean build artifacts make clean ``` ## Questions? If you have questions about contributing, please open an issue or reach out to the maintainers. ## License By contributing, you agree that your contributions will be licensed under the MIT License. --- --- url: /docs/00-CONVENTIONS.md description: Shared terminology and format conventions for ERC-8004 standards --- ## Description Shared terminology and format conventions for ERC-8004 Offchain Standards ## Purpose This document defines the common conventions, terminology, and data format standards used across all ERC-8004 offchain standard documents in this specification set. It serves as a normative reference for understanding field types, constraints, and validation requirements. ## RFC 2119 Key Words The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in all standard documents are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119). **Summary**: * **MUST** / **REQUIRED** / **SHALL**: Absolute requirement of the specification * **MUST NOT** / **SHALL NOT**: Absolute prohibition * **SHOULD** / **RECOMMENDED**: Valid reasons may exist to ignore, but implications must be understood * **SHOULD NOT** / **NOT RECOMMENDED**: Valid reasons may exist to permit, but implications must be understood * **MAY** / **OPTIONAL**: Truly optional; implementers can choose to include or omit ## Field Type System All field specifications in standard documents use the following type notation: ### JSON Primitive Types | Type | Description | Examples | | --------- | ------------------------------------ | -------------------------------------------- | | `string` | UTF-8 text string | `"DataAnalyst Pro"`, `"https://example.com"` | | `number` | JavaScript number (integer or float) | `42`, `3.14`, `100` | | `boolean` | True or false value | `true`, `false` | | `object` | JSON object (key-value pairs) | `{"key": "value"}` | | `array` | Ordered list of values | `[1, 2, 3]`, `["a", "b"]` | | `null` | Null value | `null` | ### Constrained Types When fields have specific constraints, they are documented as: **Type**: `number` **Constraints**: `uint256`, `β‰₯ 0`, `≀ 100` **Common Constraint Patterns**: * `uint256`: Unsigned 256-bit integer (0 to 2^256-1) * `0–100 inclusive`: Integer or number in range \[0, 100] * `β‰₯ 0`: Non-negative number * `enum: "A" | "B" | "C"`: One of the specified string values * `ISO 8601`: ISO 8601 date-time format * `CAIP-2`: CAIP-2 blockchain identifier format * `CAIP-10`: CAIP-10 account address format * `hex (0x...)`: Hexadecimal string prefixed with "0x" * `URI`: Uniform Resource Identifier (https://, ipfs://, ar://, data:) ### Type Notation in Tables Standard documents use tables with the following columns: | Field | Type | Constraints | Description | | ----------- | -------- | ------------------ | -------------------------- | | `fieldName` | `string` | `enum: "A" \| "B"` | Human-readable explanation | ## Address and Chain Identifiers ### CAIP-2: Blockchain ID Format **Specification**: [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) **Format**: `namespace:reference` For EVM chains: `eip155:chainId` **Examples**: ```text eip155:1 β†’ Ethereum Mainnet eip155:11155111 β†’ Sepolia Testnet eip155:8453 β†’ Base Mainnet eip155:84532 β†’ Base Sepolia eip155:137 β†’ Polygon PoS eip155:42161 β†’ Arbitrum One eip155:10 β†’ Optimism ``` For Solana chains: `solana:genesisHash` (first 32 bytes of the genesis block hash, base58-encoded) ```text solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp β†’ Solana Mainnet solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 β†’ Solana Devnet ``` > See [Solana Chain Support Extension](extensions/solana-support.md) for full details. ### CAIP-10: Account Address Format **Specification**: [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) **Format**: `namespace:chainId:address` For EVM chains: `eip155:chainId:0x...` **Examples**: ```text eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847 eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb eip155:137:0xABCDEF1234567890ABCDEF1234567890ABCDEF12 ``` For Solana chains: `solana:genesisHash:base58Address` ```text solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:Aqq2ZKnzXpsR4S18biMnJVEXVecgqU4Szi6rduszF8Sn solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1:2KmHw8VbShuz9xfj3ecEjBM5nPKR5BcYHRDSFfK1286t ``` **Validation Rules**: * EVM: Address MUST be checksummed (EIP-55) or lowercase * Solana: Address is base58-encoded, **case-sensitive** (do NOT normalize case) * Chain ID MUST be valid for the namespace * Format MUST match exactly `namespace:chainId:address` ### CAIP-10 for Contract Addresses For referencing smart contracts (e.g., agent registries): **Format**: `namespace:chainId:contractAddress` **Example**: ```text eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55 ``` This uses the CAIP-10 format for contract references in the standards. ## OASF: Agent Skills and Domains Taxonomy ### Overview **Specification**: [OASF v0.8.0](https://github.com/agntcy/oasf/tree/v0.8.0) **Full Name**: Open Agent Skills Framework OASF provides a standardized hierarchical taxonomy for describing agent capabilities and application domains. ### Skills Format **Format**: `category/skill_name` Skills describe what agents can do, organized hierarchically. **Examples**: ```text analytical_skills/data_analysis communication_skills/natural_language_processing creative_skills/content_generation technical_skills/code_generation ``` ### Domains Format **Format**: `domain_name` Domains categorize agent application areas. **Examples**: ```text finance_and_business healthcare_and_medicine education_and_training creative_arts ``` ### Usage in Standards OASF taxonomy is used in Agent Metadata Standard for declaring agent capabilities. See [Agent Metadata Standard](01-agent-metadata-standard.md#3-oasf-open-agentic-schema-framework) for detailed endpoint specification. ## Timestamp Format All timestamps in standard documents MUST use **ISO 8601** format in **UTC** timezone. ### ISO 8601 Extended Format **Format**: `YYYY-MM-DDTHH:mm:ssZ` or `YYYY-MM-DDTHH:mm:ss.sssZ` **Examples**: ```text 2025-12-21T14:30:00Z 2025-12-21T14:30:00.123Z ``` **Requirements**: * Date separator: `-` (hyphen) * Date-time separator: `T` (capital T) * Time separator: `:` (colon) * Timezone: `Z` (UTC) REQUIRED * Milliseconds: `.sss` (OPTIONAL) **Invalid Examples**: ```text ❌ 2025-12-21 14:30:00 (missing T) ❌ 2025-12-21T14:30:00+08:00 (non-UTC timezone) ❌ 12/21/2025 2:30 PM (non-ISO format) ``` ### Unix Timestamps In some contexts (e.g., `updatedAt` field in Agent Metadata), Unix timestamps (seconds since epoch) MAY be used: **Type**: `number` **Constraints**: `uint`, `β‰₯ 0` **Example**: `1763112328` (represents 2025-12-21 14:30:28 UTC) When both ISO 8601 and Unix timestamps are acceptable, the standard document will specify clearly. ## URI Schemes All URI fields (e.g., `agentURI`, `feedbackUri`, `image`, `endpoint`) MUST use one of the following schemes: ### Supported Schemes | Scheme | Description | Example | Use Case | | ---------- | ---------------------- | ------------------------------------ | ------------------------------- | | `https://` | HTTP Secure | `https://example.com/file.json` | Production APIs, hosted files | | `ipfs://` | IPFS Content ID | `ipfs://bafkreiabc...` | Decentralized immutable storage | | `ar://` | Arweave Transaction ID | `ar://abc123...` | Permanent decentralized storage | | `data:` | Data URI | `data:application/json;base64,ew...` | Inline data embedding | ### Recommended Minimum Support Implementations SHOULD support at minimum: * **REQUIRED**: `https://` * **RECOMMENDED**: `ipfs://`, `data:` * **OPTIONAL**: `ar://` ### IPFS URI Format **CIDv0** (legacy): ```text ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco ``` **CIDv1** (recommended): ```text ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4 ``` **Gateway Translation** (informative): ```text ipfs://bafkreiabc... β†’ https://ipfs.io/ipfs/bafkreiabc... β†’ https://cloudflare-ipfs.com/ipfs/bafkreiabc... ``` ### Data URI Format **Syntax**: `data:[][;base64],` **Example** (JSON): ```text data:application/json;base64,eyJuYW1lIjoiQWdlbnQifQ== ``` **Example** (inline JSON without encoding): ```text data:application/json,{"name":"Agent"} ``` ### URI Validation Implementations MUST: * Validate scheme is supported * Reject relative URIs (e.g., `./file.json`, `../data.json`) * Reject URIs without scheme (e.g., `example.com/file.json`) Implementations SHOULD: * Support scheme-specific validation (e.g., IPFS CID format) * Handle gateway fallbacks for decentralized schemes ## Versioning Strategy ### Standard Document Versions Each standard document has an independent version number following **Semantic Versioning** (SemVer) principles: **Format**: `MAJOR.MINOR` * **MAJOR**: Incremented for breaking changes (incompatible field changes, removals) * **MINOR**: Incremented for backward-compatible additions (new optional fields, clarifications) ### Version 0.x (Pre-release) * Version `0.x` indicates **draft status** * Breaking changes MAY occur between `0.x` versions * Once stable, version advances to `1.0` ### Version 1.x+ (Stable) * Version `1.x` and above follow **strict backward compatibility** * Breaking changes REQUIRE advancing to next MAJOR version * OPTIONAL fields may be promoted to RECOMMENDED/REQUIRED in MINOR versions with transition period ### Document Version Table Each standard document includes a version table: | Version | Date | Changes | | ------- | ---------- | ---------------------- | | 1.0 | 2025-12-21 | Initial stable release | | 0.2 | 2025-12-15 | Added optional field X | | 0.1 | 2025-12-01 | Initial draft | ## Normative vs Non-normative Content ### Normative Content Content that **defines requirements** and MUST be followed for compliance. Normative sections include: * Field requirements (MUST, SHOULD, MAY) * Field types and constraints * Validation rules * Format specifications ### Non-normative Content Content that provides **informative guidance** but does not define requirements. Non-normative sections are marked with: > **Non-normative**: This section provides informative guidance and examples. It does not define normative requirements. **Examples of Non-normative Content**: * Real-world usage statistics * Implementation recommendations beyond SHOULD/MAY * Design philosophy and rationale * Historical context * Migration suggestions * Extended examples and tutorials ## Relationship to EIP-8004 These standard documents are **supplementary and non-normative** with respect to the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification. ### Scope Distinction | Aspect | EIP-8004 (Official) | These Standards (Supplementary) | | ----------------- | ------------------------- | --------------------------------- | | **Defines** | Smart contract interfaces | Offchain data formats | | **Scope** | Onchain behavior | Offchain metadata schemas | | **Status** | Ethereum EIP process | Community recommendations | | **Authority** | Normative for ERC-8004 | Informative guidance | | **Compatibility** | MUST comply | SHOULD adopt for interoperability | ### Design Goals 1. **Complement, not replace**: These standards fill gaps in offchain data formats not covered by EIP-8004 2. **Implementation-agnostic**: Any ERC-8004 registry or explorer MAY adopt these formats 3. **Interoperability**: Following these standards improves cross-platform compatibility 4. **Flexibility**: Allow custom extensions while maintaining core interoperability ### Non-normative Status * These standards **do not** override EIP-8004 requirements * Where conflicts exist, **EIP-8004 takes precedence** * Implementations MAY use alternative offchain formats * Adoption of these standards is **RECOMMENDED** but **OPTIONAL** ## Field Specification Format All core standard documents (Agent Metadata, Feedback, Validation) use consistent field specification tables: ### Standard Field Table | Field | Type | Constraints | Description | | ----------- | -------- | ---------------- | ----------------------------------------------------------- | | `fieldName` | `string` | `maxLength: 100` | Human-readable explanation of the field's purpose and usage | ### Extended Field Specification For complex fields, specifications include: **Field Name**: `fieldName` **Type**: `string` **Constraints**: `maxLength: 100`, `pattern: ^[a-z0-9-]+$` **Required**: `MUST` / `SHOULD` / `MAY` **Default**: (if applicable) **Purpose**: High-level description **Validation**: * βœ… Valid example * ❌ Invalid example with error code **Example**: ```json { "fieldName": "example-value" } ``` ## Unknown Field Handling ### Forward Compatibility Principle To support extensibility and forward compatibility, implementations SHOULD adopt the following behavior for unknown fields: 1. **MUST NOT reject** documents containing unknown fields 2. **SHOULD preserve** unknown fields when re-serializing data 3. **SHOULD log** warnings for unexpected fields (informative, not errors) 4. **MAY ignore** unknown fields in processing logic ### Custom Extensions Implementations MAY add custom extension fields using reverse domain notation: **Recommended pattern**: `x--` **Examples**: ```json { "name": "Agent", "x-8004scan-internal-id": "abc123", "x-mycompany-custom-tag": "value" } ``` **Constraints**: * Extension fields SHOULD use `x-` prefix * Extension fields MUST NOT conflict with standard field names * Extension fields SHOULD be documented in implementation guides ## Content Hashing When standards reference content hashing (e.g., `feedbackHash`, `requestHash`, `responseHash`), the following applies: ### Hash Algorithm **Algorithm**: **Keccak-256** (Ethereum standard) **Output Format**: * **Type**: `bytes32` (onchain) * **Type**: `string` with `hex (0x...)` prefix (offchain references) **Example**: ```text 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd ``` ### Hash Computation For JSON content: 1. Serialize JSON with **no whitespace** (compact form) 2. Encode as UTF-8 bytes 3. Compute Keccak-256 hash 4. Represent as hex string with `0x` prefix **Example** (informative): ```javascript import { keccak256 } from "ethers"; const data = JSON.stringify({ name: "Agent" }); const hash = keccak256(toUtf8Bytes(data)); // Result: 0x... ``` ## MIME Types When specifying file types (e.g., in Attachment Pattern), use standard IANA MIME types: ### Common MIME Types | File Type | MIME Type | Usage | | ---------- | ------------------ | --------------- | | JSON | `application/json` | Structured data | | PDF | `application/pdf` | Documents | | PNG | `image/png` | Images | | JPEG | `image/jpeg` | Images | | SVG | `image/svg+xml` | Vector images | | Plain Text | `text/plain` | Text files | | CSV | `text/csv` | Tabular data | | MP4 | `video/mp4` | Videos | | ZIP | `application/zip` | Archives | ### Custom MIME Types For custom or specialized formats, use `application/x-`: **Examples**: ```text application/x-groth16-proof application/x-plonk-proof ``` ## Validation and Error Codes Standard documents reference validation error codes in the format: **Pattern**: `_` **Examples**: * `missing_required_name`: Missing required field `name` * `invalid_caip2_format`: Invalid CAIP-2 blockchain identifier format * `mcp_missing_endpoint`: MCP endpoint configuration missing required `endpoint` field **Scope Prefixes**: * `missing_`: Field is absent * `invalid_`: Field has incorrect format or value * `empty_`: Field is present but empty (array, string, object) * `_`: Protocol-specific validation (e.g., `mcp_`, `a2a_`) ## Character Encoding All text content MUST use **UTF-8** encoding. **Requirements**: * JSON files MUST be valid UTF-8 * String fields MUST support Unicode characters * No BOM (Byte Order Mark) in JSON files ## Number Precision ### Integer Values For integer fields (e.g., `agentId`, `valueDecimals`): * Use JSON number type without decimal point * Support range: `0` to `2^53-1` (JavaScript safe integer) * For Ethereum `uint256`, use string representation if value > `2^53-1` ### Decimal Values For decimal fields (e.g., `amount` in payment proofs): * Use string representation for precision-sensitive values * Recommended: Wei/smallest unit representation as string * Example: `"1000000000000000000"` (1 ETH in wei) ## Language and Localization ### Default Language All standard documents and examples use **English (en-US)** as the default language. ### Localization Support Standards do not currently define localization requirements. Implementations MAY support: * Language tags (e.g., `description-en`, `description-zh`) * Accept-Language header negotiation * Separate localized metadata files ## Abbreviations and Acronyms ### Standard Abbreviations | Abbreviation | Full Term | | ------------ | ------------------------------------------------------------- | | **A2A** | Agent-to-Agent Protocol | | **CAIP** | Chain Agnostic Improvement Proposal | | **CID** | Content Identifier (IPFS) | | **EIP** | Ethereum Improvement Proposal | | **ERC** | Ethereum Request for Comments | | **IPFS** | InterPlanetary File System | | **JSON** | JavaScript Object Notation | | **MCP** | Model Context Protocol | | **NFT** | Non-Fungible Token | | **OASF** | Open Agent Skills Framework | | **TEE** | Trusted Execution Environment | | **URI** | Uniform Resource Identifier | | **URL** | Uniform Resource Locator | | **UTC** | Coordinated Universal Time | | **zkML** | Zero-Knowledge Machine Learning | | **zkSNARK** | Zero-Knowledge Succinct Non-Interactive Argument of Knowledge | ### First Use Convention When introducing an abbreviation for the first time in a document: * Write full term followed by abbreviation in parentheses * Example: "Model Context Protocol (MCP)" ## References * **RFC 2119**: Key words for use in RFCs to Indicate Requirement Levels * **CAIP-2**: Blockchain ID Specification * **CAIP-10**: Account ID Specification * **ISO 8601**: Date and time format * **Semantic Versioning 2.0.0** * **IANA Media Types** (MIME types) **Version**: 1.0 **Last Updated**: 2026-01-09 **Status**: Normative --- --- url: /legacy-pre-v1/docs/00-CONVENTIONS.md description: Shared terminology and format conventions for ERC-8004 standards --- ## Description Shared terminology and format conventions for ERC-8004 Offchain Standards ## Purpose This document defines the common conventions, terminology, and data format standards used across all ERC-8004 offchain standard documents in this specification set. It serves as a normative reference for understanding field types, constraints, and validation requirements. ## RFC 2119 Key Words The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in all standard documents are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119). **Summary**: * **MUST** / **REQUIRED** / **SHALL**: Absolute requirement of the specification * **MUST NOT** / **SHALL NOT**: Absolute prohibition * **SHOULD** / **RECOMMENDED**: Valid reasons may exist to ignore, but implications must be understood * **SHOULD NOT** / **NOT RECOMMENDED**: Valid reasons may exist to permit, but implications must be understood * **MAY** / **OPTIONAL**: Truly optional; implementers can choose to include or omit ## Field Type System All field specifications in standard documents use the following type notation: ### JSON Primitive Types | Type | Description | Examples | | --------- | ------------------------------------ | -------------------------------------------- | | `string` | UTF-8 text string | `"DataAnalyst Pro"`, `"https://example.com"` | | `number` | JavaScript number (integer or float) | `42`, `3.14`, `100` | | `boolean` | True or false value | `true`, `false` | | `object` | JSON object (key-value pairs) | `{"key": "value"}` | | `array` | Ordered list of values | `[1, 2, 3]`, `["a", "b"]` | | `null` | Null value | `null` | ### Constrained Types When fields have specific constraints, they are documented as: **Type**: `number` **Constraints**: `uint256`, `β‰₯ 0`, `≀ 100` **Common Constraint Patterns**: * `uint256`: Unsigned 256-bit integer (0 to 2^256-1) * `0–100 inclusive`: Integer or number in range \[0, 100] * `β‰₯ 0`: Non-negative number * `enum: "A" | "B" | "C"`: One of the specified string values * `ISO 8601`: ISO 8601 date-time format * `CAIP-2`: CAIP-2 blockchain identifier format * `CAIP-10`: CAIP-10 account address format * `hex (0x...)`: Hexadecimal string prefixed with "0x" * `URI`: Uniform Resource Identifier (https://, ipfs://, ar://, data:) ### Type Notation in Tables Standard documents use tables with the following columns: | Field | Type | Constraints | Description | | ----------- | -------- | ------------------ | -------------------------- | | `fieldName` | `string` | `enum: "A" \| "B"` | Human-readable explanation | ## Address and Chain Identifiers ### CAIP-2: Blockchain ID Format **Specification**: [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) **Format**: `namespace:reference` For EVM chains: `eip155:chainId` **Examples**: ```text eip155:1 β†’ Ethereum Mainnet eip155:11155111 β†’ Sepolia Testnet eip155:8453 β†’ Base Mainnet eip155:84532 β†’ Base Sepolia eip155:137 β†’ Polygon PoS eip155:42161 β†’ Arbitrum One eip155:10 β†’ Optimism ``` ### CAIP-10: Account Address Format **Specification**: [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) **Format**: `namespace:chainId:address` For EVM chains: `eip155:chainId:0x...` **Examples**: ```text eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847 eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb eip155:137:0xABCDEF1234567890ABCDEF1234567890ABCDEF12 ``` **Validation Rules**: * Address MUST be checksummed (EIP-55) or lowercase * Chain ID MUST be valid for the namespace * Format MUST match exactly `namespace:chainId:address` ### CAIP-10 for Contract Addresses For referencing smart contracts (e.g., agent registries): **Format**: `namespace:chainId:contractAddress` **Example**: ```text eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55 ``` This uses the CAIP-10 format for contract references in the standards. ## OASF: Agent Skills and Domains Taxonomy ### Overview **Specification**: [OASF v0.8.0](https://github.com/agntcy/oasf/tree/v0.8.0) **Full Name**: Open Agent Skills Framework OASF provides a standardized hierarchical taxonomy for describing agent capabilities and application domains. ### Skills Format **Format**: `category/skill_name` Skills describe what agents can do, organized hierarchically. **Examples**: ```text analytical_skills/data_analysis communication_skills/natural_language_processing creative_skills/content_generation technical_skills/code_generation ``` ### Domains Format **Format**: `domain_name` Domains categorize agent application areas. **Examples**: ```text finance_and_business healthcare_and_medicine education_and_training creative_arts ``` ### Usage in Standards OASF taxonomy is used in Agent Metadata Standard for declaring agent capabilities. See [Agent Metadata Standard](01-agent-metadata-standard.md#3-oasf-open-agentic-schema-framework) for detailed endpoint specification. ## Timestamp Format All timestamps in standard documents MUST use **ISO 8601** format in **UTC** timezone. ### ISO 8601 Extended Format **Format**: `YYYY-MM-DDTHH:mm:ssZ` or `YYYY-MM-DDTHH:mm:ss.sssZ` **Examples**: ```text 2025-12-21T14:30:00Z 2025-12-21T14:30:00.123Z ``` **Requirements**: * Date separator: `-` (hyphen) * Date-time separator: `T` (capital T) * Time separator: `:` (colon) * Timezone: `Z` (UTC) REQUIRED * Milliseconds: `.sss` (OPTIONAL) **Invalid Examples**: ```text ❌ 2025-12-21 14:30:00 (missing T) ❌ 2025-12-21T14:30:00+08:00 (non-UTC timezone) ❌ 12/21/2025 2:30 PM (non-ISO format) ``` ### Unix Timestamps In some contexts (e.g., `updatedAt` field in Agent Metadata), Unix timestamps (seconds since epoch) MAY be used: **Type**: `number` **Constraints**: `uint`, `β‰₯ 0` **Example**: `1763112328` (represents 2025-12-21 14:30:28 UTC) When both ISO 8601 and Unix timestamps are acceptable, the standard document will specify clearly. ## URI Schemes All URI fields (e.g., `agentURI`, `feedbackUri`, `image`, `endpoint`) MUST use one of the following schemes: ### Supported Schemes | Scheme | Description | Example | Use Case | | ---------- | ---------------------- | ------------------------------------ | ------------------------------- | | `https://` | HTTP Secure | `https://example.com/file.json` | Production APIs, hosted files | | `ipfs://` | IPFS Content ID | `ipfs://bafkreiabc...` | Decentralized immutable storage | | `ar://` | Arweave Transaction ID | `ar://abc123...` | Permanent decentralized storage | | `data:` | Data URI | `data:application/json;base64,ew...` | Inline data embedding | ### Recommended Minimum Support Implementations SHOULD support at minimum: * **REQUIRED**: `https://` * **RECOMMENDED**: `ipfs://`, `data:` * **OPTIONAL**: `ar://` ### IPFS URI Format **CIDv0** (legacy): ```text ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco ``` **CIDv1** (recommended): ```text ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4 ``` **Gateway Translation** (informative): ```text ipfs://bafkreiabc... β†’ https://ipfs.io/ipfs/bafkreiabc... β†’ https://cloudflare-ipfs.com/ipfs/bafkreiabc... ``` ### Data URI Format **Syntax**: `data:[][;base64],` **Example** (JSON): ```text data:application/json;base64,eyJuYW1lIjoiQWdlbnQifQ== ``` **Example** (inline JSON without encoding): ```text data:application/json,{"name":"Agent"} ``` ### URI Validation Implementations MUST: * Validate scheme is supported * Reject relative URIs (e.g., `./file.json`, `../data.json`) * Reject URIs without scheme (e.g., `example.com/file.json`) Implementations SHOULD: * Support scheme-specific validation (e.g., IPFS CID format) * Handle gateway fallbacks for decentralized schemes ## Versioning Strategy ### Standard Document Versions Each standard document has an independent version number following **Semantic Versioning** (SemVer) principles: **Format**: `MAJOR.MINOR` * **MAJOR**: Incremented for breaking changes (incompatible field changes, removals) * **MINOR**: Incremented for backward-compatible additions (new optional fields, clarifications) ### Version 0.x (Pre-release) * Version `0.x` indicates **draft status** * Breaking changes MAY occur between `0.x` versions * Once stable, version advances to `1.0` ### Version 1.x+ (Stable) * Version `1.x` and above follow **strict backward compatibility** * Breaking changes REQUIRE advancing to next MAJOR version * OPTIONAL fields may be promoted to RECOMMENDED/REQUIRED in MINOR versions with transition period ### Document Version Table Each standard document includes a version table: | Version | Date | Changes | | ------- | ---------- | ---------------------- | | 1.0 | 2025-12-21 | Initial stable release | | 0.2 | 2025-12-15 | Added optional field X | | 0.1 | 2025-12-01 | Initial draft | ## Normative vs Non-normative Content ### Normative Content Content that **defines requirements** and MUST be followed for compliance. Normative sections include: * Field requirements (MUST, SHOULD, MAY) * Field types and constraints * Validation rules * Format specifications ### Non-normative Content Content that provides **informative guidance** but does not define requirements. Non-normative sections are marked with: > **Non-normative**: This section provides informative guidance and examples. It does not define normative requirements. **Examples of Non-normative Content**: * Real-world usage statistics * Implementation recommendations beyond SHOULD/MAY * Design philosophy and rationale * Historical context * Migration suggestions * Extended examples and tutorials ## Relationship to EIP-8004 These standard documents are **supplementary and non-normative** with respect to the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification. ### Scope Distinction | Aspect | EIP-8004 (Official) | These Standards (Supplementary) | | ----------------- | ------------------------- | --------------------------------- | | **Defines** | Smart contract interfaces | Offchain data formats | | **Scope** | Onchain behavior | Offchain metadata schemas | | **Status** | Ethereum EIP process | Community recommendations | | **Authority** | Normative for ERC-8004 | Informative guidance | | **Compatibility** | MUST comply | SHOULD adopt for interoperability | ### Design Goals 1. **Complement, not replace**: These standards fill gaps in offchain data formats not covered by EIP-8004 2. **Implementation-agnostic**: Any ERC-8004 registry or explorer MAY adopt these formats 3. **Interoperability**: Following these standards improves cross-platform compatibility 4. **Flexibility**: Allow custom extensions while maintaining core interoperability ### Non-normative Status * These standards **do not** override EIP-8004 requirements * Where conflicts exist, **EIP-8004 takes precedence** * Implementations MAY use alternative offchain formats * Adoption of these standards is **RECOMMENDED** but **OPTIONAL** ## Field Specification Format All core standard documents (Agent Metadata, Feedback, Validation) use consistent field specification tables: ### Standard Field Table | Field | Type | Constraints | Description | | ----------- | -------- | ---------------- | ----------------------------------------------------------- | | `fieldName` | `string` | `maxLength: 100` | Human-readable explanation of the field's purpose and usage | ### Extended Field Specification For complex fields, specifications include: **Field Name**: `fieldName` **Type**: `string` **Constraints**: `maxLength: 100`, `pattern: ^[a-z0-9-]+$` **Required**: `MUST` / `SHOULD` / `MAY` **Default**: (if applicable) **Purpose**: High-level description **Validation**: * βœ… Valid example * ❌ Invalid example with error code **Example**: ```json { "fieldName": "example-value" } ``` ## Unknown Field Handling ### Forward Compatibility Principle To support extensibility and forward compatibility, implementations SHOULD adopt the following behavior for unknown fields: 1. **MUST NOT reject** documents containing unknown fields 2. **SHOULD preserve** unknown fields when re-serializing data 3. **SHOULD log** warnings for unexpected fields (informative, not errors) 4. **MAY ignore** unknown fields in processing logic ### Custom Extensions Implementations MAY add custom extension fields using reverse domain notation: **Recommended pattern**: `x--` **Examples**: ```json { "name": "Agent", "x-8004scan-internal-id": "abc123", "x-mycompany-custom-tag": "value" } ``` **Constraints**: * Extension fields SHOULD use `x-` prefix * Extension fields MUST NOT conflict with standard field names * Extension fields SHOULD be documented in implementation guides ## Content Hashing When standards reference content hashing (e.g., `feedbackHash`, `requestHash`, `responseHash`), the following applies: ### Hash Algorithm **Algorithm**: **Keccak-256** (Ethereum standard) **Output Format**: * **Type**: `bytes32` (onchain) * **Type**: `string` with `hex (0x...)` prefix (offchain references) **Example**: ```text 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd ``` ### Hash Computation For JSON content: 1. Serialize JSON with **no whitespace** (compact form) 2. Encode as UTF-8 bytes 3. Compute Keccak-256 hash 4. Represent as hex string with `0x` prefix **Example** (informative): ```javascript import { keccak256 } from "ethers"; const data = JSON.stringify({ name: "Agent" }); const hash = keccak256(toUtf8Bytes(data)); // Result: 0x... ``` ## MIME Types When specifying file types (e.g., in Attachment Pattern), use standard IANA MIME types: ### Common MIME Types | File Type | MIME Type | Usage | | ---------- | ------------------ | --------------- | | JSON | `application/json` | Structured data | | PDF | `application/pdf` | Documents | | PNG | `image/png` | Images | | JPEG | `image/jpeg` | Images | | SVG | `image/svg+xml` | Vector images | | Plain Text | `text/plain` | Text files | | CSV | `text/csv` | Tabular data | | MP4 | `video/mp4` | Videos | | ZIP | `application/zip` | Archives | ### Custom MIME Types For custom or specialized formats, use `application/x-`: **Examples**: ```text application/x-groth16-proof application/x-plonk-proof ``` ## Validation and Error Codes Standard documents reference validation error codes in the format: **Pattern**: `_` **Examples**: * `missing_required_name`: Missing required field `name` * `invalid_caip2_format`: Invalid CAIP-2 blockchain identifier format * `mcp_missing_endpoint`: MCP endpoint configuration missing required `endpoint` field **Scope Prefixes**: * `missing_`: Field is absent * `invalid_`: Field has incorrect format or value * `empty_`: Field is present but empty (array, string, object) * `_`: Protocol-specific validation (e.g., `mcp_`, `a2a_`) ## Character Encoding All text content MUST use **UTF-8** encoding. **Requirements**: * JSON files MUST be valid UTF-8 * String fields MUST support Unicode characters * No BOM (Byte Order Mark) in JSON files ## Number Precision ### Integer Values For integer fields (e.g., `agentId`, `score`): * Use JSON number type without decimal point * Support range: `0` to `2^53-1` (JavaScript safe integer) * For Ethereum `uint256`, use string representation if value > `2^53-1` ### Decimal Values For decimal fields (e.g., `amount` in payment proofs): * Use string representation for precision-sensitive values * Recommended: Wei/smallest unit representation as string * Example: `"1000000000000000000"` (1 ETH in wei) ## Language and Localization ### Default Language All standard documents and examples use **English (en-US)** as the default language. ### Localization Support Standards do not currently define localization requirements. Implementations MAY support: * Language tags (e.g., `description-en`, `description-zh`) * Accept-Language header negotiation * Separate localized metadata files ## Abbreviations and Acronyms ### Standard Abbreviations | Abbreviation | Full Term | | ------------ | ------------------------------------------------------------- | | **A2A** | Agent-to-Agent Protocol | | **CAIP** | Chain Agnostic Improvement Proposal | | **CID** | Content Identifier (IPFS) | | **EIP** | Ethereum Improvement Proposal | | **ERC** | Ethereum Request for Comments | | **IPFS** | InterPlanetary File System | | **JSON** | JavaScript Object Notation | | **MCP** | Model Context Protocol | | **NFT** | Non-Fungible Token | | **OASF** | Open Agent Skills Framework | | **TEE** | Trusted Execution Environment | | **URI** | Uniform Resource Identifier | | **URL** | Uniform Resource Locator | | **UTC** | Coordinated Universal Time | | **zkML** | Zero-Knowledge Machine Learning | | **zkSNARK** | Zero-Knowledge Succinct Non-Interactive Argument of Knowledge | ### First Use Convention When introducing an abbreviation for the first time in a document: * Write full term followed by abbreviation in parentheses * Example: "Model Context Protocol (MCP)" ## References * **RFC 2119**: Key words for use in RFCs to Indicate Requirement Levels * **CAIP-2**: Blockchain ID Specification * **CAIP-10**: Account ID Specification * **ISO 8601**: Date and time format * **Semantic Versioning 2.0.0** * **IANA Media Types** (MIME types) **Version**: 1.0 **Last Updated**: 2025-12-21 **Status**: Normative --- --- url: /v1/docs/00-CONVENTIONS.md description: Shared terminology and format conventions for ERC-8004 standards --- ## Description Shared terminology and format conventions for ERC-8004 Offchain Standards ## Purpose This document defines the common conventions, terminology, and data format standards used across all ERC-8004 offchain standard documents in this specification set. It serves as a normative reference for understanding field types, constraints, and validation requirements. ## RFC 2119 Key Words The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in all standard documents are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119). **Summary**: * **MUST** / **REQUIRED** / **SHALL**: Absolute requirement of the specification * **MUST NOT** / **SHALL NOT**: Absolute prohibition * **SHOULD** / **RECOMMENDED**: Valid reasons may exist to ignore, but implications must be understood * **SHOULD NOT** / **NOT RECOMMENDED**: Valid reasons may exist to permit, but implications must be understood * **MAY** / **OPTIONAL**: Truly optional; implementers can choose to include or omit ## Field Type System All field specifications in standard documents use the following type notation: ### JSON Primitive Types | Type | Description | Examples | | --------- | ------------------------------------ | -------------------------------------------- | | `string` | UTF-8 text string | `"DataAnalyst Pro"`, `"https://example.com"` | | `number` | JavaScript number (integer or float) | `42`, `3.14`, `100` | | `boolean` | True or false value | `true`, `false` | | `object` | JSON object (key-value pairs) | `{"key": "value"}` | | `array` | Ordered list of values | `[1, 2, 3]`, `["a", "b"]` | | `null` | Null value | `null` | ### Constrained Types When fields have specific constraints, they are documented as: **Type**: `number` **Constraints**: `uint256`, `β‰₯ 0`, `≀ 100` **Common Constraint Patterns**: * `uint256`: Unsigned 256-bit integer (0 to 2^256-1) * `0–100 inclusive`: Integer or number in range \[0, 100] * `β‰₯ 0`: Non-negative number * `enum: "A" | "B" | "C"`: One of the specified string values * `ISO 8601`: ISO 8601 date-time format * `CAIP-2`: CAIP-2 blockchain identifier format * `CAIP-10`: CAIP-10 account address format * `hex (0x...)`: Hexadecimal string prefixed with "0x" * `URI`: Uniform Resource Identifier (https://, ipfs://, ar://, data:) ### Type Notation in Tables Standard documents use tables with the following columns: | Field | Type | Constraints | Description | | ----------- | -------- | ------------------ | -------------------------- | | `fieldName` | `string` | `enum: "A" \| "B"` | Human-readable explanation | ## Address and Chain Identifiers ### CAIP-2: Blockchain ID Format **Specification**: [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) **Format**: `namespace:reference` For EVM chains: `eip155:chainId` **Examples**: ```text eip155:1 β†’ Ethereum Mainnet eip155:11155111 β†’ Sepolia Testnet eip155:8453 β†’ Base Mainnet eip155:84532 β†’ Base Sepolia eip155:137 β†’ Polygon PoS eip155:42161 β†’ Arbitrum One eip155:10 β†’ Optimism ``` ### CAIP-10: Account Address Format **Specification**: [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) **Format**: `namespace:chainId:address` For EVM chains: `eip155:chainId:0x...` **Examples**: ```text eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847 eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb eip155:137:0xABCDEF1234567890ABCDEF1234567890ABCDEF12 ``` **Validation Rules**: * Address MUST be checksummed (EIP-55) or lowercase * Chain ID MUST be valid for the namespace * Format MUST match exactly `namespace:chainId:address` ### CAIP-10 for Contract Addresses For referencing smart contracts (e.g., agent registries): **Format**: `namespace:chainId:contractAddress` **Example**: ```text eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55 ``` This uses the CAIP-10 format for contract references in the standards. ## OASF: Agent Skills and Domains Taxonomy ### Overview **Specification**: [OASF v0.8.0](https://github.com/agntcy/oasf/tree/v0.8.0) **Full Name**: Open Agent Skills Framework OASF provides a standardized hierarchical taxonomy for describing agent capabilities and application domains. ### Skills Format **Format**: `category/skill_name` Skills describe what agents can do, organized hierarchically. **Examples**: ```text analytical_skills/data_analysis communication_skills/natural_language_processing creative_skills/content_generation technical_skills/code_generation ``` ### Domains Format **Format**: `domain_name` Domains categorize agent application areas. **Examples**: ```text finance_and_business healthcare_and_medicine education_and_training creative_arts ``` ### Usage in Standards OASF taxonomy is used in Agent Metadata Standard for declaring agent capabilities. See [Agent Metadata Standard](01-agent-metadata-standard.md#3-oasf-open-agentic-schema-framework) for detailed endpoint specification. ## Timestamp Format All timestamps in standard documents MUST use **ISO 8601** format in **UTC** timezone. ### ISO 8601 Extended Format **Format**: `YYYY-MM-DDTHH:mm:ssZ` or `YYYY-MM-DDTHH:mm:ss.sssZ` **Examples**: ```text 2025-12-21T14:30:00Z 2025-12-21T14:30:00.123Z ``` **Requirements**: * Date separator: `-` (hyphen) * Date-time separator: `T` (capital T) * Time separator: `:` (colon) * Timezone: `Z` (UTC) REQUIRED * Milliseconds: `.sss` (OPTIONAL) **Invalid Examples**: ```text ❌ 2025-12-21 14:30:00 (missing T) ❌ 2025-12-21T14:30:00+08:00 (non-UTC timezone) ❌ 12/21/2025 2:30 PM (non-ISO format) ``` ### Unix Timestamps In some contexts (e.g., `updatedAt` field in Agent Metadata), Unix timestamps (seconds since epoch) MAY be used: **Type**: `number` **Constraints**: `uint`, `β‰₯ 0` **Example**: `1763112328` (represents 2025-12-21 14:30:28 UTC) When both ISO 8601 and Unix timestamps are acceptable, the standard document will specify clearly. ## URI Schemes All URI fields (e.g., `agentURI`, `feedbackUri`, `image`, `endpoint`) MUST use one of the following schemes: ### Supported Schemes | Scheme | Description | Example | Use Case | | ---------- | ---------------------- | ------------------------------------ | ------------------------------- | | `https://` | HTTP Secure | `https://example.com/file.json` | Production APIs, hosted files | | `ipfs://` | IPFS Content ID | `ipfs://bafkreiabc...` | Decentralized immutable storage | | `ar://` | Arweave Transaction ID | `ar://abc123...` | Permanent decentralized storage | | `data:` | Data URI | `data:application/json;base64,ew...` | Inline data embedding | ### Recommended Minimum Support Implementations SHOULD support at minimum: * **REQUIRED**: `https://` * **RECOMMENDED**: `ipfs://`, `data:` * **OPTIONAL**: `ar://` ### IPFS URI Format **CIDv0** (legacy): ```text ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco ``` **CIDv1** (recommended): ```text ipfs://bafkreiaqdaerh5dvqmtjievkfnwfft6psghkxezygncbuvhl2uwyu6scn4 ``` **Gateway Translation** (informative): ```text ipfs://bafkreiabc... β†’ https://ipfs.io/ipfs/bafkreiabc... β†’ https://cloudflare-ipfs.com/ipfs/bafkreiabc... ``` ### Data URI Format **Syntax**: `data:[][;base64],` **Example** (JSON): ```text data:application/json;base64,eyJuYW1lIjoiQWdlbnQifQ== ``` **Example** (inline JSON without encoding): ```text data:application/json,{"name":"Agent"} ``` ### URI Validation Implementations MUST: * Validate scheme is supported * Reject relative URIs (e.g., `./file.json`, `../data.json`) * Reject URIs without scheme (e.g., `example.com/file.json`) Implementations SHOULD: * Support scheme-specific validation (e.g., IPFS CID format) * Handle gateway fallbacks for decentralized schemes ## Versioning Strategy ### Standard Document Versions Each standard document has an independent version number following **Semantic Versioning** (SemVer) principles: **Format**: `MAJOR.MINOR` * **MAJOR**: Incremented for breaking changes (incompatible field changes, removals) * **MINOR**: Incremented for backward-compatible additions (new optional fields, clarifications) ### Version 0.x (Pre-release) * Version `0.x` indicates **draft status** * Breaking changes MAY occur between `0.x` versions * Once stable, version advances to `1.0` ### Version 1.x+ (Stable) * Version `1.x` and above follow **strict backward compatibility** * Breaking changes REQUIRE advancing to next MAJOR version * OPTIONAL fields may be promoted to RECOMMENDED/REQUIRED in MINOR versions with transition period ### Document Version Table Each standard document includes a version table: | Version | Date | Changes | | ------- | ---------- | ---------------------- | | 1.0 | 2025-12-21 | Initial stable release | | 0.2 | 2025-12-15 | Added optional field X | | 0.1 | 2025-12-01 | Initial draft | ## Normative vs Non-normative Content ### Normative Content Content that **defines requirements** and MUST be followed for compliance. Normative sections include: * Field requirements (MUST, SHOULD, MAY) * Field types and constraints * Validation rules * Format specifications ### Non-normative Content Content that provides **informative guidance** but does not define requirements. Non-normative sections are marked with: > **Non-normative**: This section provides informative guidance and examples. It does not define normative requirements. **Examples of Non-normative Content**: * Real-world usage statistics * Implementation recommendations beyond SHOULD/MAY * Design philosophy and rationale * Historical context * Migration suggestions * Extended examples and tutorials ## Relationship to EIP-8004 These standard documents are **supplementary and non-normative** with respect to the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification. ### Scope Distinction | Aspect | EIP-8004 (Official) | These Standards (Supplementary) | | ----------------- | ------------------------- | --------------------------------- | | **Defines** | Smart contract interfaces | Offchain data formats | | **Scope** | Onchain behavior | Offchain metadata schemas | | **Status** | Ethereum EIP process | Community recommendations | | **Authority** | Normative for ERC-8004 | Informative guidance | | **Compatibility** | MUST comply | SHOULD adopt for interoperability | ### Design Goals 1. **Complement, not replace**: These standards fill gaps in offchain data formats not covered by EIP-8004 2. **Implementation-agnostic**: Any ERC-8004 registry or explorer MAY adopt these formats 3. **Interoperability**: Following these standards improves cross-platform compatibility 4. **Flexibility**: Allow custom extensions while maintaining core interoperability ### Non-normative Status * These standards **do not** override EIP-8004 requirements * Where conflicts exist, **EIP-8004 takes precedence** * Implementations MAY use alternative offchain formats * Adoption of these standards is **RECOMMENDED** but **OPTIONAL** ## Field Specification Format All core standard documents (Agent Metadata, Feedback, Validation) use consistent field specification tables: ### Standard Field Table | Field | Type | Constraints | Description | | ----------- | -------- | ---------------- | ----------------------------------------------------------- | | `fieldName` | `string` | `maxLength: 100` | Human-readable explanation of the field's purpose and usage | ### Extended Field Specification For complex fields, specifications include: **Field Name**: `fieldName` **Type**: `string` **Constraints**: `maxLength: 100`, `pattern: ^[a-z0-9-]+$` **Required**: `MUST` / `SHOULD` / `MAY` **Default**: (if applicable) **Purpose**: High-level description **Validation**: * βœ… Valid example * ❌ Invalid example with error code **Example**: ```json { "fieldName": "example-value" } ``` ## Unknown Field Handling ### Forward Compatibility Principle To support extensibility and forward compatibility, implementations SHOULD adopt the following behavior for unknown fields: 1. **MUST NOT reject** documents containing unknown fields 2. **SHOULD preserve** unknown fields when re-serializing data 3. **SHOULD log** warnings for unexpected fields (informative, not errors) 4. **MAY ignore** unknown fields in processing logic ### Custom Extensions Implementations MAY add custom extension fields using reverse domain notation: **Recommended pattern**: `x--` **Examples**: ```json { "name": "Agent", "x-8004scan-internal-id": "abc123", "x-mycompany-custom-tag": "value" } ``` **Constraints**: * Extension fields SHOULD use `x-` prefix * Extension fields MUST NOT conflict with standard field names * Extension fields SHOULD be documented in implementation guides ## Content Hashing When standards reference content hashing (e.g., `feedbackHash`, `requestHash`, `responseHash`), the following applies: ### Hash Algorithm **Algorithm**: **Keccak-256** (Ethereum standard) **Output Format**: * **Type**: `bytes32` (onchain) * **Type**: `string` with `hex (0x...)` prefix (offchain references) **Example**: ```text 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd ``` ### Hash Computation For JSON content: 1. Serialize JSON with **no whitespace** (compact form) 2. Encode as UTF-8 bytes 3. Compute Keccak-256 hash 4. Represent as hex string with `0x` prefix **Example** (informative): ```javascript import { keccak256 } from "ethers"; const data = JSON.stringify({ name: "Agent" }); const hash = keccak256(toUtf8Bytes(data)); // Result: 0x... ``` ## MIME Types When specifying file types (e.g., in Attachment Pattern), use standard IANA MIME types: ### Common MIME Types | File Type | MIME Type | Usage | | ---------- | ------------------ | --------------- | | JSON | `application/json` | Structured data | | PDF | `application/pdf` | Documents | | PNG | `image/png` | Images | | JPEG | `image/jpeg` | Images | | SVG | `image/svg+xml` | Vector images | | Plain Text | `text/plain` | Text files | | CSV | `text/csv` | Tabular data | | MP4 | `video/mp4` | Videos | | ZIP | `application/zip` | Archives | ### Custom MIME Types For custom or specialized formats, use `application/x-`: **Examples**: ```text application/x-groth16-proof application/x-plonk-proof ``` ## Validation and Error Codes Standard documents reference validation error codes in the format: **Pattern**: `_` **Examples**: * `missing_required_name`: Missing required field `name` * `invalid_caip2_format`: Invalid CAIP-2 blockchain identifier format * `mcp_missing_endpoint`: MCP endpoint configuration missing required `endpoint` field **Scope Prefixes**: * `missing_`: Field is absent * `invalid_`: Field has incorrect format or value * `empty_`: Field is present but empty (array, string, object) * `_`: Protocol-specific validation (e.g., `mcp_`, `a2a_`) ## Character Encoding All text content MUST use **UTF-8** encoding. **Requirements**: * JSON files MUST be valid UTF-8 * String fields MUST support Unicode characters * No BOM (Byte Order Mark) in JSON files ## Number Precision ### Integer Values For integer fields (e.g., `agentId`, `score`): * Use JSON number type without decimal point * Support range: `0` to `2^53-1` (JavaScript safe integer) * For Ethereum `uint256`, use string representation if value > `2^53-1` ### Decimal Values For decimal fields (e.g., `amount` in payment proofs): * Use string representation for precision-sensitive values * Recommended: Wei/smallest unit representation as string * Example: `"1000000000000000000"` (1 ETH in wei) ## Language and Localization ### Default Language All standard documents and examples use **English (en-US)** as the default language. ### Localization Support Standards do not currently define localization requirements. Implementations MAY support: * Language tags (e.g., `description-en`, `description-zh`) * Accept-Language header negotiation * Separate localized metadata files ## Abbreviations and Acronyms ### Standard Abbreviations | Abbreviation | Full Term | | ------------ | ------------------------------------------------------------- | | **A2A** | Agent-to-Agent Protocol | | **CAIP** | Chain Agnostic Improvement Proposal | | **CID** | Content Identifier (IPFS) | | **EIP** | Ethereum Improvement Proposal | | **ERC** | Ethereum Request for Comments | | **IPFS** | InterPlanetary File System | | **JSON** | JavaScript Object Notation | | **MCP** | Model Context Protocol | | **NFT** | Non-Fungible Token | | **OASF** | Open Agent Skills Framework | | **TEE** | Trusted Execution Environment | | **URI** | Uniform Resource Identifier | | **URL** | Uniform Resource Locator | | **UTC** | Coordinated Universal Time | | **zkML** | Zero-Knowledge Machine Learning | | **zkSNARK** | Zero-Knowledge Succinct Non-Interactive Argument of Knowledge | ### First Use Convention When introducing an abbreviation for the first time in a document: * Write full term followed by abbreviation in parentheses * Example: "Model Context Protocol (MCP)" ## References * **RFC 2119**: Key words for use in RFCs to Indicate Requirement Levels * **CAIP-2**: Blockchain ID Specification * **CAIP-10**: Account ID Specification * **ISO 8601**: Date and time format * **Semantic Versioning 2.0.0** * **IANA Media Types** (MIME types) **Version**: 1.0 **Last Updated**: 2026-01-09 **Status**: Normative --- --- url: /docs/extensions/compression-test-results.md description: 'Benchmark results from 4,916 production agent metadata' --- ## Overview **Test Data**: 4,916 production agent metadata from 8004scan database ## Test Summary ### Dataset Distribution | Size Range | Count | Percentage | Average Size | | ---------- | ----- | ---------- | ------------ | | **< 1KB** | 2,872 | 58.4% | 0.51 KB | | **1-2KB** | 2,015 | 41.0% | 1.19 KB | | **2-3KB** | 13 | 0.3% | 2.26 KB | | **3-5KB** | 15 | 0.3% | 3.76 KB | | **> 5KB** | 1 | 0.02% | 5.76 KB | **Key Insight**: 99.4% of real agents use metadata < 2KB. ## Small Metadata (< 2KB) - 99.4% of Agents **Test**: 30 samples, average 0.73 KB (751 bytes), ~33,000 gas uncompressed | Algorithm | Level | Compression Ratio | Gas Saved | Compression Speed | Decompression Speed | | ---------- | ----- | ----------------- | ------------------ | ----------------- | ------------------- | | **Brotli** | 11 | **47.7%** | ~6,180 gas (17.4%) | 2.62ms | 0.02ms | | **Brotli** | 9 | 41.2% | ~5,327 gas (15.0%) | 1.43ms | 0.02ms | | **Zstd** | 22 | 34.9% | ~4,570 gas (12.8%) | 0.15ms | 0.01ms | | **Zstd** | 15 | 34.8% | ~4,561 gas (12.8%) | **0.11ms** | **0.01ms** | | **Zstd** | 9 | 34.4% | ~4,533 gas (12.7%) | 0.06ms | 0.01ms | | **Gzip** | 9 | 34.7% | ~4,613 gas (12.9%) | 0.05ms | 0.02ms | | **Gzip** | 6 | 34.7% | ~4,613 gas (12.9%) | 0.05ms | 0.03ms | | **LZ4** | 12 | 14.5% | ~2,110 gas (5.8%) | 0.04ms | 0.00ms | | **LZ4** | 9 | 14.5% | ~2,110 gas (5.8%) | **0.03ms** | **0.00ms** | ### Recommendations for Small Metadata | Priority | Algorithm | Reason | | ------------------ | ------------- | ------------------------------------------------------------------------- | | **1st Choice** | **Zstd-15** | Best balance: 34.8% ratio, 0.11ms speed, excellent cross-platform support | | **2nd Choice** | **Brotli-11** | Highest ratio (47.7%) but slower (2.62ms), good for static content | | **Speed Priority** | **LZ4-9** | Fastest (0.03ms) but lowest ratio (14.5%), only if speed critical | ## Medium Metadata (2-5KB) - 0.6% of Agents **Test**: 2 samples, average 3.11 KB (3,182 bytes), ~71,920 gas uncompressed | Algorithm | Level | Compression Ratio | Gas Saved | Compression Speed | Decompression Speed | | ---------- | ----- | ----------------- | ------------------- | ----------------- | ------------------- | | **Brotli** | 11 | **66.8%** | ~35,288 gas (46.9%) | 6.91ms | 0.04ms | | **Brotli** | 9 | 62.3% | ~33,144 gas (43.8%) | 3.75ms | 0.03ms | | **Zstd** | 22 | 59.3% | ~31,672 gas (41.8%) | 1.23ms | 0.02ms | | **Zstd** | 15 | 59.2% | ~31,576 gas (41.6%) | **0.68ms** | **0.02ms** | | **Zstd** | 9 | 58.9% | ~31,472 gas (41.5%) | 0.20ms | 0.03ms | | **Gzip** | 9 | 59.5% | ~31,704 gas (41.9%) | 0.10ms | 0.04ms | | **Gzip** | 6 | 59.5% | ~31,704 gas (41.9%) | 0.12ms | 0.07ms | | **LZ4** | 12 | 45.2% | ~24,920 gas (32.2%) | 0.13ms | 0.01ms | | **LZ4** | 9 | 45.2% | ~24,912 gas (32.1%) | **0.07ms** | **0.01ms** | ### Recommendations for Medium Metadata | Priority | Algorithm | Reason | | ------------------ | ------------- | ------------------------------------------------------------------------ | | **1st Choice** | **Zstd-15** | Excellent ratio (59.2%), fast (0.68ms), production-ready | | **2nd Choice** | **Brotli-11** | Best ratio (66.8%) but slower (6.91ms), worth it for rare large metadata | | **Speed Priority** | **Gzip-9** | Very fast (0.10ms), good ratio (59.5%), best compatibility | ## Key Findings ### 1. Real Compression Ratios Lower Than Expected **Previous Estimates**: 60-70% compression ratio **Actual Results**: * Small metadata (<2KB): **35-48%** compression ratio * Medium metadata (2-5KB): **59-67%** compression ratio **Reason**: Real agent metadata is already fairly compact with minimal repetition. ### 2. Gas Savings Still Worthwhile Despite lower compression ratios, gas savings remain valuable: * **Small metadata** (99% of agents): Save **4,000-6,000 gas per registration** * **Medium metadata** (1% of agents): Save **31,000-35,000 gas per registration** For platforms with 1,000+ agents, cumulative savings are significant. ### 3. Zstd-15 is the Clear Winner **Why Zstd-15**: * βœ… Excellent compression ratio (35-59%) * βœ… Fast speed (0.11-0.68ms) * βœ… Cross-platform support (Python, Node.js, Rust, Go) * βœ… Production-proven in many systems (Facebook, Linux kernel) **Brotli-11 Alternative**: * Better compression (48-67%) but 6-24x slower * Good for static content, pre-computed compression * Worse cross-platform support (native in browsers, libraries elsewhere) ### 4. LZ4 Not Recommended **LZ4 Results**: * Lowest compression ratio (14-45%) * Marginal speed advantage (0.03ms vs 0.11ms for Zstd-15) * Speed difference negligible for typical use cases **Conclusion**: Zstd-15's superior compression ratio outweighs LZ4's minimal speed advantage. ## Production Recommendations ### Default Algorithm **Recommended**: **Zstd level 15** ```python # Backend (Python) import zstandard as zstd compressor = zstd.ZstdCompressor(level=15) compressed = compressor.compress(json_bytes) ``` ```typescript // Frontend (TypeScript) // Note: Use gzip instead of zstd for browser compatibility import { compress } from "fflate"; const compressed = compress(json_bytes, { level: 9 }); ``` ### When to Use Compression | Metadata Size | Recommendation | Gas Saved | | ------------------ | ------------------------- | -------------------------------------- | | **< 500 bytes** | ❌ Don't compress | Minimal savings, overhead not worth it | | **500-2000 bytes** | βš–οΈ Optional | ~2,000-6,000 gas | | **2-5KB** | βœ… Recommended | ~31,000-35,000 gas | | **> 5KB** | βœ…βœ… Strongly recommended | 35,000+ gas | ### Implementation Checklist * \[x] Parser supports `enc=zstd` parameter in Data URI * \[x] Zip bomb protection (100KB decompression limit) * \[x] Algorithm whitelist (zstd, gzip, br, lz4 only) * \[x] Async decompression in Celery workers * \[ ] Frontend compression UI with gas savings preview * \[ ] Analytics dashboard tracking compression adoption ## Test Methodology ### Data Source * **Database**: 8004scan production PostgreSQL * **Table**: `agents.metadata_json` * **Total Records**: 4,916 agents * **Chains**: Ethereum Sepolia + Base Sepolia ### Test Process 1. Fetch real metadata from database 2. Test each algorithm at multiple compression levels 3. Measure compression ratio, gas savings, speed 4. Verify decompression correctness 5. Aggregate statistics ### Gas Calculation Formula ```text Gas = (data_size_bytes Γ— 16) + 21,000 ``` * **16 gas/byte**: EVM calldata cost * **21,000 gas**: Base transaction cost ## Conclusion **TLDR**: * Real compression ratios (35-67%) are lower than theoretical estimates (60-70%) * Gas savings (4,000-35,000 per agent) are still worthwhile for production * **Recommended: Zstd-15** for best balance of compression and speed * Alternative: Brotli-11 for maximum compression (rare large metadata) * 99% of agents use small metadata (<2KB), save ~4,500 gas each **Next Steps**: 1. Update documentation with real test data βœ… 2. Set default compression to Zstd-15 in backend 3. Add frontend compression UI with gas preview 4. Track compression adoption metrics --- --- url: /legacy-pre-v1/docs/extensions/compression-test-results.md description: 'Benchmark results from 4,916 production agent metadata' --- ## Overview **Test Data**: 4,916 production agent metadata from 8004scan database ## Test Summary ### Dataset Distribution | Size Range | Count | Percentage | Average Size | | ---------- | ----- | ---------- | ------------ | | **< 1KB** | 2,872 | 58.4% | 0.51 KB | | **1-2KB** | 2,015 | 41.0% | 1.19 KB | | **2-3KB** | 13 | 0.3% | 2.26 KB | | **3-5KB** | 15 | 0.3% | 3.76 KB | | **> 5KB** | 1 | 0.02% | 5.76 KB | **Key Insight**: 99.4% of real agents use metadata < 2KB. ## Small Metadata (< 2KB) - 99.4% of Agents **Test**: 30 samples, average 0.73 KB (751 bytes), ~33,000 gas uncompressed | Algorithm | Level | Compression Ratio | Gas Saved | Compression Speed | Decompression Speed | | ---------- | ----- | ----------------- | ------------------ | ----------------- | ------------------- | | **Brotli** | 11 | **47.7%** | ~6,180 gas (17.4%) | 2.62ms | 0.02ms | | **Brotli** | 9 | 41.2% | ~5,327 gas (15.0%) | 1.43ms | 0.02ms | | **Zstd** | 22 | 34.9% | ~4,570 gas (12.8%) | 0.15ms | 0.01ms | | **Zstd** | 15 | 34.8% | ~4,561 gas (12.8%) | **0.11ms** | **0.01ms** | | **Zstd** | 9 | 34.4% | ~4,533 gas (12.7%) | 0.06ms | 0.01ms | | **Gzip** | 9 | 34.7% | ~4,613 gas (12.9%) | 0.05ms | 0.02ms | | **Gzip** | 6 | 34.7% | ~4,613 gas (12.9%) | 0.05ms | 0.03ms | | **LZ4** | 12 | 14.5% | ~2,110 gas (5.8%) | 0.04ms | 0.00ms | | **LZ4** | 9 | 14.5% | ~2,110 gas (5.8%) | **0.03ms** | **0.00ms** | ### Recommendations for Small Metadata | Priority | Algorithm | Reason | | ------------------ | ------------- | ------------------------------------------------------------------------- | | **1st Choice** | **Zstd-15** | Best balance: 34.8% ratio, 0.11ms speed, excellent cross-platform support | | **2nd Choice** | **Brotli-11** | Highest ratio (47.7%) but slower (2.62ms), good for static content | | **Speed Priority** | **LZ4-9** | Fastest (0.03ms) but lowest ratio (14.5%), only if speed critical | ## Medium Metadata (2-5KB) - 0.6% of Agents **Test**: 2 samples, average 3.11 KB (3,182 bytes), ~71,920 gas uncompressed | Algorithm | Level | Compression Ratio | Gas Saved | Compression Speed | Decompression Speed | | ---------- | ----- | ----------------- | ------------------- | ----------------- | ------------------- | | **Brotli** | 11 | **66.8%** | ~35,288 gas (46.9%) | 6.91ms | 0.04ms | | **Brotli** | 9 | 62.3% | ~33,144 gas (43.8%) | 3.75ms | 0.03ms | | **Zstd** | 22 | 59.3% | ~31,672 gas (41.8%) | 1.23ms | 0.02ms | | **Zstd** | 15 | 59.2% | ~31,576 gas (41.6%) | **0.68ms** | **0.02ms** | | **Zstd** | 9 | 58.9% | ~31,472 gas (41.5%) | 0.20ms | 0.03ms | | **Gzip** | 9 | 59.5% | ~31,704 gas (41.9%) | 0.10ms | 0.04ms | | **Gzip** | 6 | 59.5% | ~31,704 gas (41.9%) | 0.12ms | 0.07ms | | **LZ4** | 12 | 45.2% | ~24,920 gas (32.2%) | 0.13ms | 0.01ms | | **LZ4** | 9 | 45.2% | ~24,912 gas (32.1%) | **0.07ms** | **0.01ms** | ### Recommendations for Medium Metadata | Priority | Algorithm | Reason | | ------------------ | ------------- | ------------------------------------------------------------------------ | | **1st Choice** | **Zstd-15** | Excellent ratio (59.2%), fast (0.68ms), production-ready | | **2nd Choice** | **Brotli-11** | Best ratio (66.8%) but slower (6.91ms), worth it for rare large metadata | | **Speed Priority** | **Gzip-9** | Very fast (0.10ms), good ratio (59.5%), best compatibility | ## Key Findings ### 1. Real Compression Ratios Lower Than Expected **Previous Estimates**: 60-70% compression ratio **Actual Results**: * Small metadata (<2KB): **35-48%** compression ratio * Medium metadata (2-5KB): **59-67%** compression ratio **Reason**: Real agent metadata is already fairly compact with minimal repetition. ### 2. Gas Savings Still Worthwhile Despite lower compression ratios, gas savings remain valuable: * **Small metadata** (99% of agents): Save **4,000-6,000 gas per registration** * **Medium metadata** (1% of agents): Save **31,000-35,000 gas per registration** For platforms with 1,000+ agents, cumulative savings are significant. ### 3. Zstd-15 is the Clear Winner **Why Zstd-15**: * βœ… Excellent compression ratio (35-59%) * βœ… Fast speed (0.11-0.68ms) * βœ… Cross-platform support (Python, Node.js, Rust, Go) * βœ… Production-proven in many systems (Facebook, Linux kernel) **Brotli-11 Alternative**: * Better compression (48-67%) but 6-24x slower * Good for static content, pre-computed compression * Worse cross-platform support (native in browsers, libraries elsewhere) ### 4. LZ4 Not Recommended **LZ4 Results**: * Lowest compression ratio (14-45%) * Marginal speed advantage (0.03ms vs 0.11ms for Zstd-15) * Speed difference negligible for typical use cases **Conclusion**: Zstd-15's superior compression ratio outweighs LZ4's minimal speed advantage. ## Production Recommendations ### Default Algorithm **Recommended**: **Zstd level 15** ```python # Backend (Python) import zstandard as zstd compressor = zstd.ZstdCompressor(level=15) compressed = compressor.compress(json_bytes) ``` ```typescript // Frontend (TypeScript) // Note: Use gzip instead of zstd for browser compatibility import { compress } from "fflate"; const compressed = compress(json_bytes, { level: 9 }); ``` ### When to Use Compression | Metadata Size | Recommendation | Gas Saved | | ------------------ | ------------------------- | -------------------------------------- | | **< 500 bytes** | ❌ Don't compress | Minimal savings, overhead not worth it | | **500-2000 bytes** | βš–οΈ Optional | ~2,000-6,000 gas | | **2-5KB** | βœ… Recommended | ~31,000-35,000 gas | | **> 5KB** | βœ…βœ… Strongly recommended | 35,000+ gas | ### Implementation Checklist * \[x] Parser supports `enc=zstd` parameter in Data URI * \[x] Zip bomb protection (100KB decompression limit) * \[x] Algorithm whitelist (zstd, gzip, br, lz4 only) * \[x] Async decompression in Celery workers * \[ ] Frontend compression UI with gas savings preview * \[ ] Analytics dashboard tracking compression adoption ## Test Methodology ### Data Source * **Database**: 8004scan production PostgreSQL * **Table**: `agents.metadata_json` * **Total Records**: 4,916 agents * **Chains**: Ethereum Sepolia + Base Sepolia ### Test Process 1. Fetch real metadata from database 2. Test each algorithm at multiple compression levels 3. Measure compression ratio, gas savings, speed 4. Verify decompression correctness 5. Aggregate statistics ### Gas Calculation Formula ```text Gas = (data_size_bytes Γ— 16) + 21,000 ``` * **16 gas/byte**: EVM calldata cost * **21,000 gas**: Base transaction cost ## Conclusion **TLDR**: * Real compression ratios (35-67%) are lower than theoretical estimates (60-70%) * Gas savings (4,000-35,000 per agent) are still worthwhile for production * **Recommended: Zstd-15** for best balance of compression and speed * Alternative: Brotli-11 for maximum compression (rare large metadata) * 99% of agents use small metadata (<2KB), save ~4,500 gas each **Next Steps**: 1. Update documentation with real test data βœ… 2. Set default compression to Zstd-15 in backend 3. Add frontend compression UI with gas preview 4. Track compression adoption metrics --- --- url: /v1/docs/extensions/compression-test-results.md description: 'Benchmark results from 4,916 production agent metadata' --- ## Overview **Test Data**: 4,916 production agent metadata from 8004scan database ## Test Summary ### Dataset Distribution | Size Range | Count | Percentage | Average Size | | ---------- | ----- | ---------- | ------------ | | **< 1KB** | 2,872 | 58.4% | 0.51 KB | | **1-2KB** | 2,015 | 41.0% | 1.19 KB | | **2-3KB** | 13 | 0.3% | 2.26 KB | | **3-5KB** | 15 | 0.3% | 3.76 KB | | **> 5KB** | 1 | 0.02% | 5.76 KB | **Key Insight**: 99.4% of real agents use metadata < 2KB. ## Small Metadata (< 2KB) - 99.4% of Agents **Test**: 30 samples, average 0.73 KB (751 bytes), ~33,000 gas uncompressed | Algorithm | Level | Compression Ratio | Gas Saved | Compression Speed | Decompression Speed | | ---------- | ----- | ----------------- | ------------------ | ----------------- | ------------------- | | **Brotli** | 11 | **47.7%** | ~6,180 gas (17.4%) | 2.62ms | 0.02ms | | **Brotli** | 9 | 41.2% | ~5,327 gas (15.0%) | 1.43ms | 0.02ms | | **Zstd** | 22 | 34.9% | ~4,570 gas (12.8%) | 0.15ms | 0.01ms | | **Zstd** | 15 | 34.8% | ~4,561 gas (12.8%) | **0.11ms** | **0.01ms** | | **Zstd** | 9 | 34.4% | ~4,533 gas (12.7%) | 0.06ms | 0.01ms | | **Gzip** | 9 | 34.7% | ~4,613 gas (12.9%) | 0.05ms | 0.02ms | | **Gzip** | 6 | 34.7% | ~4,613 gas (12.9%) | 0.05ms | 0.03ms | | **LZ4** | 12 | 14.5% | ~2,110 gas (5.8%) | 0.04ms | 0.00ms | | **LZ4** | 9 | 14.5% | ~2,110 gas (5.8%) | **0.03ms** | **0.00ms** | ### Recommendations for Small Metadata | Priority | Algorithm | Reason | | ------------------ | ------------- | ------------------------------------------------------------------------- | | **1st Choice** | **Zstd-15** | Best balance: 34.8% ratio, 0.11ms speed, excellent cross-platform support | | **2nd Choice** | **Brotli-11** | Highest ratio (47.7%) but slower (2.62ms), good for static content | | **Speed Priority** | **LZ4-9** | Fastest (0.03ms) but lowest ratio (14.5%), only if speed critical | ## Medium Metadata (2-5KB) - 0.6% of Agents **Test**: 2 samples, average 3.11 KB (3,182 bytes), ~71,920 gas uncompressed | Algorithm | Level | Compression Ratio | Gas Saved | Compression Speed | Decompression Speed | | ---------- | ----- | ----------------- | ------------------- | ----------------- | ------------------- | | **Brotli** | 11 | **66.8%** | ~35,288 gas (46.9%) | 6.91ms | 0.04ms | | **Brotli** | 9 | 62.3% | ~33,144 gas (43.8%) | 3.75ms | 0.03ms | | **Zstd** | 22 | 59.3% | ~31,672 gas (41.8%) | 1.23ms | 0.02ms | | **Zstd** | 15 | 59.2% | ~31,576 gas (41.6%) | **0.68ms** | **0.02ms** | | **Zstd** | 9 | 58.9% | ~31,472 gas (41.5%) | 0.20ms | 0.03ms | | **Gzip** | 9 | 59.5% | ~31,704 gas (41.9%) | 0.10ms | 0.04ms | | **Gzip** | 6 | 59.5% | ~31,704 gas (41.9%) | 0.12ms | 0.07ms | | **LZ4** | 12 | 45.2% | ~24,920 gas (32.2%) | 0.13ms | 0.01ms | | **LZ4** | 9 | 45.2% | ~24,912 gas (32.1%) | **0.07ms** | **0.01ms** | ### Recommendations for Medium Metadata | Priority | Algorithm | Reason | | ------------------ | ------------- | ------------------------------------------------------------------------ | | **1st Choice** | **Zstd-15** | Excellent ratio (59.2%), fast (0.68ms), production-ready | | **2nd Choice** | **Brotli-11** | Best ratio (66.8%) but slower (6.91ms), worth it for rare large metadata | | **Speed Priority** | **Gzip-9** | Very fast (0.10ms), good ratio (59.5%), best compatibility | ## Key Findings ### 1. Real Compression Ratios Lower Than Expected **Previous Estimates**: 60-70% compression ratio **Actual Results**: * Small metadata (<2KB): **35-48%** compression ratio * Medium metadata (2-5KB): **59-67%** compression ratio **Reason**: Real agent metadata is already fairly compact with minimal repetition. ### 2. Gas Savings Still Worthwhile Despite lower compression ratios, gas savings remain valuable: * **Small metadata** (99% of agents): Save **4,000-6,000 gas per registration** * **Medium metadata** (1% of agents): Save **31,000-35,000 gas per registration** For platforms with 1,000+ agents, cumulative savings are significant. ### 3. Zstd-15 is the Clear Winner **Why Zstd-15**: * βœ… Excellent compression ratio (35-59%) * βœ… Fast speed (0.11-0.68ms) * βœ… Cross-platform support (Python, Node.js, Rust, Go) * βœ… Production-proven in many systems (Facebook, Linux kernel) **Brotli-11 Alternative**: * Better compression (48-67%) but 6-24x slower * Good for static content, pre-computed compression * Worse cross-platform support (native in browsers, libraries elsewhere) ### 4. LZ4 Not Recommended **LZ4 Results**: * Lowest compression ratio (14-45%) * Marginal speed advantage (0.03ms vs 0.11ms for Zstd-15) * Speed difference negligible for typical use cases **Conclusion**: Zstd-15's superior compression ratio outweighs LZ4's minimal speed advantage. ## Production Recommendations ### Default Algorithm **Recommended**: **Zstd level 15** ```python # Backend (Python) import zstandard as zstd compressor = zstd.ZstdCompressor(level=15) compressed = compressor.compress(json_bytes) ``` ```typescript // Frontend (TypeScript) // Note: Use gzip instead of zstd for browser compatibility import { compress } from "fflate"; const compressed = compress(json_bytes, { level: 9 }); ``` ### When to Use Compression | Metadata Size | Recommendation | Gas Saved | | ------------------ | ------------------------- | -------------------------------------- | | **< 500 bytes** | ❌ Don't compress | Minimal savings, overhead not worth it | | **500-2000 bytes** | βš–οΈ Optional | ~2,000-6,000 gas | | **2-5KB** | βœ… Recommended | ~31,000-35,000 gas | | **> 5KB** | βœ…βœ… Strongly recommended | 35,000+ gas | ### Implementation Checklist * \[x] Parser supports `enc=zstd` parameter in Data URI * \[x] Zip bomb protection (100KB decompression limit) * \[x] Algorithm whitelist (zstd, gzip, br, lz4 only) * \[x] Async decompression in Celery workers * \[ ] Frontend compression UI with gas savings preview * \[ ] Analytics dashboard tracking compression adoption ## Test Methodology ### Data Source * **Database**: 8004scan production PostgreSQL * **Table**: `agents.metadata_json` * **Total Records**: 4,916 agents * **Chains**: Ethereum Sepolia + Base Sepolia ### Test Process 1. Fetch real metadata from database 2. Test each algorithm at multiple compression levels 3. Measure compression ratio, gas savings, speed 4. Verify decompression correctness 5. Aggregate statistics ### Gas Calculation Formula ```text Gas = (data_size_bytes Γ— 16) + 21,000 ``` * **16 gas/byte**: EVM calldata cost * **21,000 gas**: Base transaction cost ## Conclusion **TLDR**: * Real compression ratios (35-67%) are lower than theoretical estimates (60-70%) * Gas savings (4,000-35,000 per agent) are still worthwhile for production * **Recommended: Zstd-15** for best balance of compression and speed * Alternative: Brotli-11 for maximum compression (rare large metadata) * 99% of agents use small metadata (<2KB), save ~4,500 gas each **Next Steps**: 1. Update documentation with real test data βœ… 2. Set default compression to Zstd-15 in backend 3. Add frontend compression UI with gas preview 4. Track compression adoption metrics --- --- url: /docs/extensions/data-uri-compression.md description: Gas optimization through onchain data compression --- ## Description 8004scan Extension for Gas Fee Optimization ## Table of Contents 1. [Overview](#overview) 2. [Motivation](#motivation) 3. [Protocol Specification](#protocol-specification) 4. [Security Considerations](#security-considerations) 5. [Gas Cost Analysis](#gas-cost-analysis) 6. [Adoption Strategy](#adoption-strategy) 7. [Reference Implementation](#reference-implementation) 8. [FAQ](#faq) ## Overview ### What is Data URI Compression? The **Data URI Compression Extension** is an optional protocol extension designed by 8004scan to dramatically reduce on-chain gas fees for ERC-8004 agent metadata while maintaining the perfect immutability guarantees of Data URI storage. **Key Innovation**: Add a compression layer between JSON serialization and base64 encoding, reducing data size by 60-70%. ### Problem Statement Standard Data URI storage format: ```text data:application/json;base64, ``` **Issues**: * **Expensive**: 3KB metadata costs ~69,000 gas for on-chain storage * **Limited adoption**: Only 18% of agents use Data URI due to high gas costs * **Prohibitive for production**: Most projects choose mutable IPFS/HTTP instead ### Solution Compressed Data URI format: ```text data:application/json;enc=;base64, ``` **Benefits**: * **60-70% gas reduction**: ~69,000 β†’ ~37,000 gas for typical 3KB metadata * **Perfect immutability**: Data stored on-chain, cannot be changed * **Backward compatible**: Old parsers will error clearly, not silently fail * **Simple adoption**: Single parameter addition to existing Data URI format ## Motivation ### Why Compression? #### Gas Cost Comparison | Storage Method | Immutability | 3KB Metadata Gas Cost | Recommendation | | ---------------------------- | -------------- | -------------------------------- | ---------------- | | **Data URI (Uncompressed)** | βœ…βœ…βœ… Perfect | ~69,000 gas | High gas cost | | **Data URI (Compressed)** ✨ | βœ…βœ…βœ… Perfect | ~37,000 gas | **Recommended** | | **IPFS/Arweave** | βœ…βœ… Strong | ~40,000-70,000 gas (URI storage) | Good balance | | **HTTP/HTTPS** | ❌ None | ~40,000-70,000 gas (URI storage) | Development only | **Insight**: Compression makes Data URI practical for production use, not just high-value scenarios. **Note**: Gas estimates based on calldata cost formula: `Gas = (size_bytes Γ— 16) + 21,000`. Actual costs may vary depending on network conditions and contract implementation. ### Real-World Impact #### Production Agents (4,725 total) * **18%** use Data URI (high-value agents only) * **51%** use IPFS (good immutability, low cost) * **22%** use HTTP/HTTPS (no immutability, lowest cost) **With compression**: * Data URI becomes cost-competitive with IPFS * Agents can achieve perfect immutability at reasonable cost * Expected adoption: 40%+ of production agents ### Use Cases #### 1. Regulatory Compliance Agents **Requirement**: Immutable audit trail **Solution**: Compressed Data URI ensures metadata cannot be tampered with **Gas Reduction**: ~149,000 β†’ ~61,000 gas for 8KB full metadata (~59% reduction) #### 2. Financial Service Agents **Requirement**: Transparency and trust **Solution**: On-chain metadata provides cryptographic proof **Gas Reduction**: ~69,000 β†’ ~37,000 gas for typical 3KB metadata (~46% reduction) #### 3. Long-Term Archive Agents **Requirement**: Guaranteed availability (no IPFS pinning) **Solution**: On-chain storage eliminates external dependencies **Savings**: 60-70% gas reduction ## Protocol Specification ### Formal Specification #### Grammar (ABNF) ```text compressed-data-uri = "data:" media-type compression-params ";base64," base64-data media-type = "application/json" compression-params = ";enc=" algorithm [";level=" compression-level] algorithm = "zstd" / "gzip" / "br" / "lz4" compression-level = 1*2DIGIT ; Algorithm-specific (e.g., 1-22 for zstd) base64-data = ``` #### Example ```text data:application/json;enc=zstd;level=9;base64,KLUv/WD8zQAUfRS4VTYwMDE... ``` **Breakdown**: 1. `data:` - Data URI scheme 2. `application/json` - MIME type (must be JSON) 3. `;enc=zstd` - Compression algorithm (required for compression) 4. `;level=9` - Compression level (optional, algorithm-specific) 5. `;base64` - Base64 encoding flag (required) 6. `,KLUv/...` - Compressed then base64-encoded payload ### Supported Algorithms | Algorithm | Compression Ratio | Speed | Decompression Speed | Default Level | Recommendation | | -------------------- | ----------------- | ---------- | ------------------- | ------------- | ------------------ | | **zstd** (Zstandard) | ⭐⭐⭐⭐⭐ (70%) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 3 | **Best Choice** ✨ | | **br** (Brotli) | ⭐⭐⭐⭐⭐ (72%) | ⭐⭐⭐ | ⭐⭐⭐⭐ | 11 | Highest ratio | | **gzip** (GNU zip) | ⭐⭐⭐ (60%) | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 6 | Best compatibility | | **lz4** (LZ4) | ⭐⭐ (50%) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 0 | Fastest | **Recommendation**: **Zstd level 9** for optimal balance of compression ratio and speed. ### Compression Level Guidelines #### Zstd (Recommended) ```text Level 1-3: Fast compression, lower ratio (~55-65%) Level 9: Balanced (recommended) (~70%) Level 19: Maximum compression (~75%), 10x slower Level 22: Extreme (rarely needed) (~77%), 100x slower ``` **Recommendation**: Level 9 (default in reference implementation) #### Brotli ```text Level 4: Fast (~65%) Level 11: Maximum (recommended) (~72%) ``` **Note**: Levels 10-11 provide only marginal gains over level 6 but are much slower. #### Gzip ```text Level 6: Default (~60%) Level 9: Maximum (~62%) ``` **Note**: Gzip has minimal ratio improvement at higher levels. #### LZ4 ```text Level 0: Fast mode (default) (~50%) Level 9: High compression (~55%) ``` **Note**: LZ4 prioritizes speed over ratio. ### Processing Pipeline #### Encoding (Creating Compressed Data URI) ```text Agent Metadata (JSON object) ↓ 1. JSON.stringify() with compact separators (no whitespace) ↓ 2. UTF-8 encode β†’ bytes ↓ 3. Compress with algorithm (e.g., zstd level 9) ↓ 4. Base64 encode ↓ 5. Prepend header: "data:application/json;enc=zstd;level=9;base64," ↓ Compressed Data URI (ready for on-chain storage) ``` #### Decoding (Parsing Compressed Data URI) ```text Compressed Data URI ↓ 1. Parse header parameters (detect "enc=zstd") ↓ 2. Extract base64 payload ↓ 3. Base64 decode β†’ compressed bytes ↓ 4. Decompress with detected algorithm (with size limit check) ↓ 5. UTF-8 decode β†’ JSON string ↓ 6. JSON.parse() ↓ Agent Metadata (JSON object) ``` ## Security Considerations ### 1. Zip Bomb Protection ⚠️ **Attack Vector**: Adversary uploads small compressed data that expands to enormous size **Example**: ```text Compressed: 10KB Decompressed: 10GB (1000x expansion) Result: Memory exhaustion, DoS ``` **Defense**: Strict decompression size limits ```python MAX_DECOMPRESSED_SIZE = 100 * 1024 # 100KB hard limit def safe_decompress(data, algorithm): decompressed = decompress_with_algorithm(data, algorithm) if len(decompressed) > MAX_DECOMPRESSED_SIZE: raise SecurityError("Decompressed data exceeds 100KB (possible zip bomb)") return decompressed ``` **8004scan Implementation**: * 100KB decompression limit enforced * Decompression in async workers (isolated) * Security events logged for monitoring ### 2. Algorithm Whitelist **Attack Vector**: Malicious algorithm name causes arbitrary code execution **Defense**: Strict whitelist of allowed algorithms ```python ALLOWED_ALGORITHMS = {"zstd", "gzip", "br", "lz4"} if algorithm not in ALLOWED_ALGORITHMS: raise ValueError(f"Algorithm not allowed: {algorithm}") ``` **8004scan Implementation**: * Only 4 algorithms supported * Reject all unknown algorithms with clear error * No dynamic algorithm loading ### 3. Async Decompression **Problem**: CPU-intensive decompression can block API requests **Solution**: Process in background workers ```python # API endpoint (returns immediately) @router.post("/agents") async def create_agent(agent_uri: str): task_id = parse_agent_metadata.delay(agent_uri) return {"status": "processing", "task_id": task_id} # Celery worker (handles decompression) @celery_app.task def parse_agent_metadata(uri: str): metadata = parse_compressed_data_uri(uri) # Safe here # Store in database... ``` **8004scan Implementation**: * All URI parsing in Celery workers * API never blocks on decompression * Worker isolation prevents DoS on API server ### 4. JSON Validation **Defense**: Always validate decompressed data is valid JSON ```python try: metadata = json.loads(decompressed_data) except json.JSONDecodeError: raise ValueError("Decompressed data is not valid JSON") if not isinstance(metadata, dict): raise ValueError("Metadata must be a JSON object (not array or primitive)") ``` ## Gas Cost Analysis ### Detailed Gas Cost Breakdown **Estimated Gas Costs** (based on calldata pricing): | Data Size | Gas (Uncompressed) | Gas (Compressed @ 60%) | **Gas Reduction** | | --------- | ------------------ | ---------------------- | ----------------- | | **1KB** | ~37,000 | - | - | | **2KB** | ~53,000 | ~29,000 | ~24,000 (45%) | | **3KB** | ~69,000 | ~37,000 | ~32,000 (46%) | | **5KB** | ~101,000 | ~53,000 | ~48,000 (48%) | | **8KB** | ~149,000 | ~77,000 | ~72,000 (48%) | | **10KB** | ~181,000 | ~93,000 | ~88,000 (49%) | **Formula**: ```text Gas = (size_bytes Γ— 16) + 21,000 # 16 gas per calldata byte + base tx cost ``` **Compression ratio assumption**: 60% (conservative estimate - zstd typically achieves 65-75%) **⚠️ Important**: These are theoretical estimates. Actual gas costs and compression ratios need to be measured with real-world on-chain deployment data. ### When to Use Compression | Scenario | Uncompressed Size | Recommendation | | -------------------- | ----------------- | ----------------------------------------------------- | | **Minimal metadata** | < 1KB | ❌ Don't compress (overhead not worth it) | | **Typical agent** | 1-3KB | βš–οΈ Optional (saves ~24,000-32,000 gas) | | **Full metadata** | 3-8KB | βœ… Recommended (saves ~32,000-72,000 gas) | | **Rich metadata** | 8-20KB | βœ…βœ… Strongly recommended (saves ~72,000-176,000 gas) | | **Complex agent** | > 20KB | βœ…βœ… Essential (saves 176,000+ gas) | **Rule of Thumb**: If metadata > 3KB, always use compression. **Note**: Gas savings are estimates based on 60% compression ratio. Actual savings may vary. ### Real-World Cost Examples #### Example 1: Minimal Agent (1.5KB) ```json { "type": "...", "name": "SimpleAgent", "description": "Basic agent with one endpoint", "image": "ipfs://...", "services": [{ "name": "MCP", "endpoint": "..." }] } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 1.5KB | ~45,000 | | Compressed | ~0.6KB | ~30,000 | | **Gas Reduction** | - | **~15,000 (33%)** | **Verdict**: Marginal gas savings, compression optional. #### Example 2: Typical Agent (3KB) ```json { "type": "...", "name": "DataAnalyst Pro", "description": "...", "image": "...", "services": [ {"name": "MCP", "endpoint": "...", "version": "...", "mcpTools": [...]}, {"name": "A2A", "endpoint": "...", "version": "...", "a2aSkills": [...]}, {"name": "agentWallet", "endpoint": "..."} ], "registrations": [...], "supportedTrust": ["reputation", "crypto-economic"] } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 3KB | ~69,000 | | Compressed | ~1.2KB | ~37,000 | | **Gas Reduction** | - | **~32,000 (46%)** | **Verdict**: βœ… Recommended - good gas savings. #### Example 3: Full Metadata (8KB) ```json { "type": "...", "name": "Enterprise Agent", "description": "...", "image": "...", "services": [ {"name": "MCP", "endpoint": "...", "mcpTools": [30 tools], "mcpPrompts": [...]}, {"name": "A2A", "endpoint": "...", "a2aSkills": [50 skills]}, {"name": "OASF", "endpoint": "...", "skills": [100 skills], "domains": [...]}, {"name": "agentWallet", "endpoint": "..."} ], "registrations": [multiple chains], "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"], "active": true, "x402Support": true } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 8KB | ~149,000 | | Compressed | ~2.5KB | ~61,000 | | **Gas Reduction** | - | **~88,000 (59%)** | **Verdict**: βœ…βœ… Strongly recommended - major gas savings. ## Adoption Strategy ### Phase 1: Support (Current) **Status**: βœ… Complete **8004scan Capabilities**: * βœ… Parser supports compressed Data URIs * βœ… Documentation published * βœ… Reference implementation available * βœ… Security measures implemented **Developer Actions**: None required - existing agents work unchanged ### Phase 2: Tooling **Status**: 🚧 In Progress **8004scan Will Provide**: * Web-based compression tool (paste JSON β†’ get compressed URI) * CLI tool for batch compression * Frontend SDK integration examples * Gas savings calculator **Developer Actions**: * Use tools to generate compressed URIs * Test with existing agents ### Phase 3: Incentivization **Status**: πŸ“… Planned **8004scan Features**: * πŸ’° Badge on explorer: "Gas-Optimized" for compressed agents * πŸ“Š Analytics dashboard: Compression adoption rate * πŸ† Leaderboard: Most gas-efficient agents * πŸ’‘ UI hints: "Save ~32,000 gas by compressing" on registration **Developer Actions**: * Migrate existing agents to compression * Monitor gas savings ### Phase 4: Standardization **Status**: πŸ“… Future **Community Efforts**: * Propose compression extension to ERC-8004 spec * Submit EIP if adoption > 30% * Coordinate with other explorers **Developer Actions**: * Provide feedback on protocol * Participate in governance ## Reference Implementation The 8004scan reference implementation provides a robust framework for handling compressed metadata. Key features: * **Multi-Algorithm Support**: Full support for zstd, gzip, brotli, and lz4 algorithms. * **Browser Compatibility**: Gzip and deflate support for frontend applications. * **Security First**: Built-in zip bomb protection, algorithm whitelisting, and async processing. ### Quick Start Examples **Python** (Zstd-15 recommended): ```python 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) ``` **TypeScript** (using fflate for gzip): ```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 compressedBytes = Uint8Array.from(atob(data), (c) => c.charCodeAt(0)); const jsonStr = new TextDecoder().decode(decompress(compressedBytes)); const metadata = JSON.parse(jsonStr); ``` **Security Note**: Always implement zip bomb protection (100KB decompression limit) in production. For production deployment, refer to the security considerations and follow the recommended implementation patterns. ## FAQ ### General **Q: Is this an official ERC-8004 feature?** A: No, this is an **optional extension** proposed by 8004scan. The official ERC-8004 spec does not specify compression. However, this extension is designed to be **forward-compatible** with future spec updates. **Q: Will old clients break?** A: Old clients will **fail gracefully** with a clear error message indicating compression is not supported. They will NOT silently misparse the data. **Q: Can I mix compressed and uncompressed agents?** A: Yes, 8004scan supports both formats seamlessly. You can update agents incrementally. ### Technical **Q: Which algorithm should I use?** A: **Zstd level 9** for best balance. Brotli level 11 for maximum compression (slightly better ratio, slower). **Q: Can I use custom compression algorithms?** A: No, only `zstd`, `gzip`, `br`, and `lz4` are allowed for security reasons. **Q: What happens if I exceed 100KB decompressed?** A: Parse will fail with `SecurityError`. Split metadata across multiple agents or use IPFS for large data. **Q: Does compression work with IPFS URIs?** A: This protocol is for **Data URIs only**. IPFS URIs should remain uncompressed (already efficient). ### Gas & Cost **Q: Is compression worth it for 1KB metadata?** A: Marginal gas savings (~15,000-20,000 gas reduction). Optional unless you value immutability highly. **Q: Is compression still worth it at low gas prices?** A: Yes. Compression saves ~24,000-88,000 gas per agent regardless of gas price. The percentage savings (45-59%) remains constant. **Q: Can I update metadata after registration?** A: Yes, call `setAgentURI(agentId, newURI)` on the registry contract. However, this costs additional gas (~45,000 gas). Consider using mutable storage (IPFS/HTTP) if frequent updates are needed. ### Security **Q: Is this safe?** A: Yes, with proper implementation. 8004scan enforces: * 100KB decompression size limit (zip bomb protection) * Algorithm whitelist (no arbitrary code) * Async processing (no API blocking) * JSON validation (data integrity) **Q: What if someone tries a zip bomb?** A: Decompression will fail safely with `SecurityError`. No system impact. **Q: Can metadata be tampered with?** A: No, Data URI metadata is stored on-chain and cryptographically verified by the blockchain. ## Appendix ### Algorithm Comparison #### Test Metadata (3KB JSON) ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Test Agent", ... } ``` | Algorithm | Level | Compressed Size | Ratio | Compression Time | Decompression Time | | --------- | ----- | --------------- | ----- | ---------------- | ------------------ | | zstd | 9 | 1.2KB | 60% | 5ms | 1ms | | zstd | 19 | 1.1KB | 63% | 50ms | 1ms | | brotli | 11 | 1.1KB | 63% | 120ms | 3ms | | gzip | 6 | 1.5KB | 50% | 8ms | 2ms | | gzip | 9 | 1.4KB | 53% | 15ms | 2ms | | lz4 | 0 | 1.8KB | 40% | 2ms | 1ms | **Conclusion**: Zstd level 9 offers best balance (good ratio, fast speed). ### Changelog | Version | Date | Changes | | ------- | ---------- | --------------------------------------------------------------- | | **0.1** | 2025-12-20 | Initial draft - protocol specification and implementation guide | ### Contact & Feedback * **Maintainer**: 8004scan Development Team **Feedback Channels**: * GitHub Issues: Technical bugs and feature requests *(coming soon)* * Discord: Community discussion and support *(coming soon)* * Email: maintainers@altresear.ch --- --- url: /legacy-pre-v1/docs/extensions/data-uri-compression.md description: Gas optimization through onchain data compression --- ## Description 8004scan Extension for Gas Fee Optimization ## Table of Contents 1. [Overview](#overview) 2. [Motivation](#motivation) 3. [Protocol Specification](#protocol-specification) 4. [Security Considerations](#security-considerations) 5. [Gas Cost Analysis](#gas-cost-analysis) 6. [Adoption Strategy](#adoption-strategy) 7. [Reference Implementation](#reference-implementation) 8. [FAQ](#faq) ## Overview ### What is Data URI Compression? The **Data URI Compression Extension** is an optional protocol extension designed by 8004scan to dramatically reduce on-chain gas fees for ERC-8004 agent metadata while maintaining the perfect immutability guarantees of Data URI storage. **Key Innovation**: Add a compression layer between JSON serialization and base64 encoding, reducing data size by 60-70%. ### Problem Statement Standard Data URI storage format: ```text data:application/json;base64, ``` **Issues**: * **Expensive**: 3KB metadata costs ~69,000 gas for on-chain storage * **Limited adoption**: Only 18% of agents use Data URI due to high gas costs * **Prohibitive for production**: Most projects choose mutable IPFS/HTTP instead ### Solution Compressed Data URI format: ```text data:application/json;enc=;base64, ``` **Benefits**: * **60-70% gas reduction**: ~69,000 β†’ ~37,000 gas for typical 3KB metadata * **Perfect immutability**: Data stored on-chain, cannot be changed * **Backward compatible**: Old parsers will error clearly, not silently fail * **Simple adoption**: Single parameter addition to existing Data URI format ## Motivation ### Why Compression? #### Gas Cost Comparison | Storage Method | Immutability | 3KB Metadata Gas Cost | Recommendation | | ---------------------------- | -------------- | -------------------------------- | ---------------- | | **Data URI (Uncompressed)** | βœ…βœ…βœ… Perfect | ~69,000 gas | High gas cost | | **Data URI (Compressed)** ✨ | βœ…βœ…βœ… Perfect | ~37,000 gas | **Recommended** | | **IPFS/Arweave** | βœ…βœ… Strong | ~40,000-70,000 gas (URI storage) | Good balance | | **HTTP/HTTPS** | ❌ None | ~40,000-70,000 gas (URI storage) | Development only | **Insight**: Compression makes Data URI practical for production use, not just high-value scenarios. **Note**: Gas estimates based on calldata cost formula: `Gas = (size_bytes Γ— 16) + 21,000`. Actual costs may vary depending on network conditions and contract implementation. ### Real-World Impact #### Production Agents (4,725 total) * **18%** use Data URI (high-value agents only) * **51%** use IPFS (good immutability, low cost) * **22%** use HTTP/HTTPS (no immutability, lowest cost) **With compression**: * Data URI becomes cost-competitive with IPFS * Agents can achieve perfect immutability at reasonable cost * Expected adoption: 40%+ of production agents ### Use Cases #### 1. Regulatory Compliance Agents **Requirement**: Immutable audit trail **Solution**: Compressed Data URI ensures metadata cannot be tampered with **Gas Reduction**: ~149,000 β†’ ~61,000 gas for 8KB full metadata (~59% reduction) #### 2. Financial Service Agents **Requirement**: Transparency and trust **Solution**: On-chain metadata provides cryptographic proof **Gas Reduction**: ~69,000 β†’ ~37,000 gas for typical 3KB metadata (~46% reduction) #### 3. Long-Term Archive Agents **Requirement**: Guaranteed availability (no IPFS pinning) **Solution**: On-chain storage eliminates external dependencies **Savings**: 60-70% gas reduction ## Protocol Specification ### Formal Specification #### Grammar (ABNF) ```text compressed-data-uri = "data:" media-type compression-params ";base64," base64-data media-type = "application/json" compression-params = ";enc=" algorithm [";level=" compression-level] algorithm = "zstd" / "gzip" / "br" / "lz4" compression-level = 1*2DIGIT ; Algorithm-specific (e.g., 1-22 for zstd) base64-data = ``` #### Example ```text data:application/json;enc=zstd;level=9;base64,KLUv/WD8zQAUfRS4VTYwMDE... ``` **Breakdown**: 1. `data:` - Data URI scheme 2. `application/json` - MIME type (must be JSON) 3. `;enc=zstd` - Compression algorithm (required for compression) 4. `;level=9` - Compression level (optional, algorithm-specific) 5. `;base64` - Base64 encoding flag (required) 6. `,KLUv/...` - Compressed then base64-encoded payload ### Supported Algorithms | Algorithm | Compression Ratio | Speed | Decompression Speed | Default Level | Recommendation | | -------------------- | ----------------- | ---------- | ------------------- | ------------- | ------------------ | | **zstd** (Zstandard) | ⭐⭐⭐⭐⭐ (70%) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 3 | **Best Choice** ✨ | | **br** (Brotli) | ⭐⭐⭐⭐⭐ (72%) | ⭐⭐⭐ | ⭐⭐⭐⭐ | 11 | Highest ratio | | **gzip** (GNU zip) | ⭐⭐⭐ (60%) | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 6 | Best compatibility | | **lz4** (LZ4) | ⭐⭐ (50%) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 0 | Fastest | **Recommendation**: **Zstd level 9** for optimal balance of compression ratio and speed. ### Compression Level Guidelines #### Zstd (Recommended) ```text Level 1-3: Fast compression, lower ratio (~55-65%) Level 9: Balanced (recommended) (~70%) Level 19: Maximum compression (~75%), 10x slower Level 22: Extreme (rarely needed) (~77%), 100x slower ``` **Recommendation**: Level 9 (default in reference implementation) #### Brotli ```text Level 4: Fast (~65%) Level 11: Maximum (recommended) (~72%) ``` **Note**: Levels 10-11 provide only marginal gains over level 6 but are much slower. #### Gzip ```text Level 6: Default (~60%) Level 9: Maximum (~62%) ``` **Note**: Gzip has minimal ratio improvement at higher levels. #### LZ4 ```text Level 0: Fast mode (default) (~50%) Level 9: High compression (~55%) ``` **Note**: LZ4 prioritizes speed over ratio. ### Processing Pipeline #### Encoding (Creating Compressed Data URI) ```text Agent Metadata (JSON object) ↓ 1. JSON.stringify() with compact separators (no whitespace) ↓ 2. UTF-8 encode β†’ bytes ↓ 3. Compress with algorithm (e.g., zstd level 9) ↓ 4. Base64 encode ↓ 5. Prepend header: "data:application/json;enc=zstd;level=9;base64," ↓ Compressed Data URI (ready for on-chain storage) ``` #### Decoding (Parsing Compressed Data URI) ```text Compressed Data URI ↓ 1. Parse header parameters (detect "enc=zstd") ↓ 2. Extract base64 payload ↓ 3. Base64 decode β†’ compressed bytes ↓ 4. Decompress with detected algorithm (with size limit check) ↓ 5. UTF-8 decode β†’ JSON string ↓ 6. JSON.parse() ↓ Agent Metadata (JSON object) ``` ## Security Considerations ### 1. Zip Bomb Protection ⚠️ **Attack Vector**: Adversary uploads small compressed data that expands to enormous size **Example**: ```text Compressed: 10KB Decompressed: 10GB (1000x expansion) Result: Memory exhaustion, DoS ``` **Defense**: Strict decompression size limits ```python MAX_DECOMPRESSED_SIZE = 100 * 1024 # 100KB hard limit def safe_decompress(data, algorithm): decompressed = decompress_with_algorithm(data, algorithm) if len(decompressed) > MAX_DECOMPRESSED_SIZE: raise SecurityError("Decompressed data exceeds 100KB (possible zip bomb)") return decompressed ``` **8004scan Implementation**: * 100KB decompression limit enforced * Decompression in async workers (isolated) * Security events logged for monitoring ### 2. Algorithm Whitelist **Attack Vector**: Malicious algorithm name causes arbitrary code execution **Defense**: Strict whitelist of allowed algorithms ```python ALLOWED_ALGORITHMS = {"zstd", "gzip", "br", "lz4"} if algorithm not in ALLOWED_ALGORITHMS: raise ValueError(f"Algorithm not allowed: {algorithm}") ``` **8004scan Implementation**: * Only 4 algorithms supported * Reject all unknown algorithms with clear error * No dynamic algorithm loading ### 3. Async Decompression **Problem**: CPU-intensive decompression can block API requests **Solution**: Process in background workers ```python # API endpoint (returns immediately) @router.post("/agents") async def create_agent(agent_uri: str): task_id = parse_agent_metadata.delay(agent_uri) return {"status": "processing", "task_id": task_id} # Celery worker (handles decompression) @celery_app.task def parse_agent_metadata(uri: str): metadata = parse_compressed_data_uri(uri) # Safe here # Store in database... ``` **8004scan Implementation**: * All URI parsing in Celery workers * API never blocks on decompression * Worker isolation prevents DoS on API server ### 4. JSON Validation **Defense**: Always validate decompressed data is valid JSON ```python try: metadata = json.loads(decompressed_data) except json.JSONDecodeError: raise ValueError("Decompressed data is not valid JSON") if not isinstance(metadata, dict): raise ValueError("Metadata must be a JSON object (not array or primitive)") ``` ## Gas Cost Analysis ### Detailed Gas Cost Breakdown **Estimated Gas Costs** (based on calldata pricing): | Data Size | Gas (Uncompressed) | Gas (Compressed @ 60%) | **Gas Reduction** | | --------- | ------------------ | ---------------------- | ----------------- | | **1KB** | ~37,000 | - | - | | **2KB** | ~53,000 | ~29,000 | ~24,000 (45%) | | **3KB** | ~69,000 | ~37,000 | ~32,000 (46%) | | **5KB** | ~101,000 | ~53,000 | ~48,000 (48%) | | **8KB** | ~149,000 | ~77,000 | ~72,000 (48%) | | **10KB** | ~181,000 | ~93,000 | ~88,000 (49%) | **Formula**: ```text Gas = (size_bytes Γ— 16) + 21,000 # 16 gas per calldata byte + base tx cost ``` **Compression ratio assumption**: 60% (conservative estimate - zstd typically achieves 65-75%) **⚠️ Important**: These are theoretical estimates. Actual gas costs and compression ratios need to be measured with real-world on-chain deployment data. ### When to Use Compression | Scenario | Uncompressed Size | Recommendation | | -------------------- | ----------------- | ----------------------------------------------------- | | **Minimal metadata** | < 1KB | ❌ Don't compress (overhead not worth it) | | **Typical agent** | 1-3KB | βš–οΈ Optional (saves ~24,000-32,000 gas) | | **Full metadata** | 3-8KB | βœ… Recommended (saves ~32,000-72,000 gas) | | **Rich metadata** | 8-20KB | βœ…βœ… Strongly recommended (saves ~72,000-176,000 gas) | | **Complex agent** | > 20KB | βœ…βœ… Essential (saves 176,000+ gas) | **Rule of Thumb**: If metadata > 3KB, always use compression. **Note**: Gas savings are estimates based on 60% compression ratio. Actual savings may vary. ### Real-World Cost Examples #### Example 1: Minimal Agent (1.5KB) ```json { "type": "...", "name": "SimpleAgent", "description": "Basic agent with one endpoint", "image": "ipfs://...", "endpoints": [{ "name": "MCP", "endpoint": "..." }] } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 1.5KB | ~45,000 | | Compressed | ~0.6KB | ~30,000 | | **Gas Reduction** | - | **~15,000 (33%)** | **Verdict**: Marginal gas savings, compression optional. #### Example 2: Typical Agent (3KB) ```json { "type": "...", "name": "DataAnalyst Pro", "description": "...", "image": "...", "endpoints": [ {"name": "MCP", "endpoint": "...", "version": "...", "mcpTools": [...]}, {"name": "A2A", "endpoint": "...", "version": "...", "a2aSkills": [...]}, {"name": "agentWallet", "endpoint": "..."} ], "registrations": [...], "supportedTrust": ["reputation", "crypto-economic"] } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 3KB | ~69,000 | | Compressed | ~1.2KB | ~37,000 | | **Gas Reduction** | - | **~32,000 (46%)** | **Verdict**: βœ… Recommended - good gas savings. #### Example 3: Full Metadata (8KB) ```json { "type": "...", "name": "Enterprise Agent", "description": "...", "image": "...", "endpoints": [ {"name": "MCP", "endpoint": "...", "mcpTools": [30 tools], "mcpPrompts": [...]}, {"name": "A2A", "endpoint": "...", "a2aSkills": [50 skills]}, {"name": "OASF", "endpoint": "...", "skills": [100 skills], "domains": [...]}, {"name": "agentWallet", "endpoint": "..."} ], "registrations": [multiple chains], "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"], "active": true, "x402support": true } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 8KB | ~149,000 | | Compressed | ~2.5KB | ~61,000 | | **Gas Reduction** | - | **~88,000 (59%)** | **Verdict**: βœ…βœ… Strongly recommended - major gas savings. ## Adoption Strategy ### Phase 1: Support (Current) **Status**: βœ… Complete **8004scan Capabilities**: * βœ… Parser supports compressed Data URIs * βœ… Documentation published * βœ… Reference implementation available * βœ… Security measures implemented **Developer Actions**: None required - existing agents work unchanged ### Phase 2: Tooling **Status**: 🚧 In Progress **8004scan Will Provide**: * Web-based compression tool (paste JSON β†’ get compressed URI) * CLI tool for batch compression * Frontend SDK integration examples * Gas savings calculator **Developer Actions**: * Use tools to generate compressed URIs * Test with existing agents ### Phase 3: Incentivization **Status**: πŸ“… Planned **8004scan Features**: * πŸ’° Badge on explorer: "Gas-Optimized" for compressed agents * πŸ“Š Analytics dashboard: Compression adoption rate * πŸ† Leaderboard: Most gas-efficient agents * πŸ’‘ UI hints: "Save ~32,000 gas by compressing" on registration **Developer Actions**: * Migrate existing agents to compression * Monitor gas savings ### Phase 4: Standardization **Status**: πŸ“… Future **Community Efforts**: * Propose compression extension to ERC-8004 spec * Submit EIP if adoption > 30% * Coordinate with other explorers **Developer Actions**: * Provide feedback on protocol * Participate in governance ## Reference Implementation The 8004scan reference implementation provides a robust framework for handling compressed metadata. Key features: * **Multi-Algorithm Support**: Full support for zstd, gzip, brotli, and lz4 algorithms. * **Browser Compatibility**: Gzip and deflate support for frontend applications. * **Security First**: Built-in zip bomb protection, algorithm whitelisting, and async processing. For production deployment, refer to the security considerations and follow the recommended implementation patterns. ## FAQ ### General **Q: Is this an official ERC-8004 feature?** A: No, this is an **optional extension** proposed by 8004scan. The official ERC-8004 spec does not specify compression. However, this extension is designed to be **forward-compatible** with future spec updates. **Q: Will old clients break?** A: Old clients will **fail gracefully** with a clear error message indicating compression is not supported. They will NOT silently misparse the data. **Q: Can I mix compressed and uncompressed agents?** A: Yes, 8004scan supports both formats seamlessly. You can update agents incrementally. ### Technical **Q: Which algorithm should I use?** A: **Zstd level 9** for best balance. Brotli level 11 for maximum compression (slightly better ratio, slower). **Q: Can I use custom compression algorithms?** A: No, only `zstd`, `gzip`, `br`, and `lz4` are allowed for security reasons. **Q: What happens if I exceed 100KB decompressed?** A: Parse will fail with `SecurityError`. Split metadata across multiple agents or use IPFS for large data. **Q: Does compression work with IPFS URIs?** A: This protocol is for **Data URIs only**. IPFS URIs should remain uncompressed (already efficient). ### Gas & Cost **Q: Is compression worth it for 1KB metadata?** A: Marginal gas savings (~15,000-20,000 gas reduction). Optional unless you value immutability highly. **Q: Is compression still worth it at low gas prices?** A: Yes. Compression saves ~24,000-88,000 gas per agent regardless of gas price. The percentage savings (45-59%) remains constant. **Q: Can I update metadata after registration?** A: Yes, call `setAgentURI(agentId, newURI)` on the registry contract. However, this costs additional gas (~45,000 gas). Consider using mutable storage (IPFS/HTTP) if frequent updates are needed. ### Security **Q: Is this safe?** A: Yes, with proper implementation. 8004scan enforces: * 100KB decompression size limit (zip bomb protection) * Algorithm whitelist (no arbitrary code) * Async processing (no API blocking) * JSON validation (data integrity) **Q: What if someone tries a zip bomb?** A: Decompression will fail safely with `SecurityError`. No system impact. **Q: Can metadata be tampered with?** A: No, Data URI metadata is stored on-chain and cryptographically verified by the blockchain. ## Appendix ### Algorithm Comparison #### Test Metadata (3KB JSON) ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Test Agent", ... } ``` | Algorithm | Level | Compressed Size | Ratio | Compression Time | Decompression Time | | --------- | ----- | --------------- | ----- | ---------------- | ------------------ | | zstd | 9 | 1.2KB | 60% | 5ms | 1ms | | zstd | 19 | 1.1KB | 63% | 50ms | 1ms | | brotli | 11 | 1.1KB | 63% | 120ms | 3ms | | gzip | 6 | 1.5KB | 50% | 8ms | 2ms | | gzip | 9 | 1.4KB | 53% | 15ms | 2ms | | lz4 | 0 | 1.8KB | 40% | 2ms | 1ms | **Conclusion**: Zstd level 9 offers best balance (good ratio, fast speed). ### Changelog | Version | Date | Changes | | ------- | ---------- | --------------------------------------------------------------- | | **0.1** | 2025-12-20 | Initial draft - protocol specification and implementation guide | ### Contact & Feedback * **Maintainer**: 8004scan Development Team **Feedback Channels**: * GitHub Issues: Technical bugs and feature requests *(coming soon)* * Discord: Community discussion and support *(coming soon)* * Email: maintainers@altresear.ch --- --- url: /v1/docs/extensions/data-uri-compression.md description: Gas optimization through onchain data compression --- ## Description 8004scan Extension for Gas Fee Optimization ## Table of Contents 1. [Overview](#overview) 2. [Motivation](#motivation) 3. [Protocol Specification](#protocol-specification) 4. [Security Considerations](#security-considerations) 5. [Gas Cost Analysis](#gas-cost-analysis) 6. [Adoption Strategy](#adoption-strategy) 7. [Reference Implementation](#reference-implementation) 8. [FAQ](#faq) ## Overview ### What is Data URI Compression? The **Data URI Compression Extension** is an optional protocol extension designed by 8004scan to dramatically reduce on-chain gas fees for ERC-8004 agent metadata while maintaining the perfect immutability guarantees of Data URI storage. **Key Innovation**: Add a compression layer between JSON serialization and base64 encoding, reducing data size by 60-70%. ### Problem Statement Standard Data URI storage format: ```text data:application/json;base64, ``` **Issues**: * **Expensive**: 3KB metadata costs ~69,000 gas for on-chain storage * **Limited adoption**: Only 18% of agents use Data URI due to high gas costs * **Prohibitive for production**: Most projects choose mutable IPFS/HTTP instead ### Solution Compressed Data URI format: ```text data:application/json;enc=;base64, ``` **Benefits**: * **60-70% gas reduction**: ~69,000 β†’ ~37,000 gas for typical 3KB metadata * **Perfect immutability**: Data stored on-chain, cannot be changed * **Backward compatible**: Old parsers will error clearly, not silently fail * **Simple adoption**: Single parameter addition to existing Data URI format ## Motivation ### Why Compression? #### Gas Cost Comparison | Storage Method | Immutability | 3KB Metadata Gas Cost | Recommendation | | ---------------------------- | -------------- | -------------------------------- | ---------------- | | **Data URI (Uncompressed)** | βœ…βœ…βœ… Perfect | ~69,000 gas | High gas cost | | **Data URI (Compressed)** ✨ | βœ…βœ…βœ… Perfect | ~37,000 gas | **Recommended** | | **IPFS/Arweave** | βœ…βœ… Strong | ~40,000-70,000 gas (URI storage) | Good balance | | **HTTP/HTTPS** | ❌ None | ~40,000-70,000 gas (URI storage) | Development only | **Insight**: Compression makes Data URI practical for production use, not just high-value scenarios. **Note**: Gas estimates based on calldata cost formula: `Gas = (size_bytes Γ— 16) + 21,000`. Actual costs may vary depending on network conditions and contract implementation. ### Real-World Impact #### Production Agents (4,725 total) * **18%** use Data URI (high-value agents only) * **51%** use IPFS (good immutability, low cost) * **22%** use HTTP/HTTPS (no immutability, lowest cost) **With compression**: * Data URI becomes cost-competitive with IPFS * Agents can achieve perfect immutability at reasonable cost * Expected adoption: 40%+ of production agents ### Use Cases #### 1. Regulatory Compliance Agents **Requirement**: Immutable audit trail **Solution**: Compressed Data URI ensures metadata cannot be tampered with **Gas Reduction**: ~149,000 β†’ ~61,000 gas for 8KB full metadata (~59% reduction) #### 2. Financial Service Agents **Requirement**: Transparency and trust **Solution**: On-chain metadata provides cryptographic proof **Gas Reduction**: ~69,000 β†’ ~37,000 gas for typical 3KB metadata (~46% reduction) #### 3. Long-Term Archive Agents **Requirement**: Guaranteed availability (no IPFS pinning) **Solution**: On-chain storage eliminates external dependencies **Savings**: 60-70% gas reduction ## Protocol Specification ### Formal Specification #### Grammar (ABNF) ```text compressed-data-uri = "data:" media-type compression-params ";base64," base64-data media-type = "application/json" compression-params = ";enc=" algorithm [";level=" compression-level] algorithm = "zstd" / "gzip" / "br" / "lz4" compression-level = 1*2DIGIT ; Algorithm-specific (e.g., 1-22 for zstd) base64-data = ``` #### Example ```text data:application/json;enc=zstd;level=9;base64,KLUv/WD8zQAUfRS4VTYwMDE... ``` **Breakdown**: 1. `data:` - Data URI scheme 2. `application/json` - MIME type (must be JSON) 3. `;enc=zstd` - Compression algorithm (required for compression) 4. `;level=9` - Compression level (optional, algorithm-specific) 5. `;base64` - Base64 encoding flag (required) 6. `,KLUv/...` - Compressed then base64-encoded payload ### Supported Algorithms | Algorithm | Compression Ratio | Speed | Decompression Speed | Default Level | Recommendation | | -------------------- | ----------------- | ---------- | ------------------- | ------------- | ------------------ | | **zstd** (Zstandard) | ⭐⭐⭐⭐⭐ (70%) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 3 | **Best Choice** ✨ | | **br** (Brotli) | ⭐⭐⭐⭐⭐ (72%) | ⭐⭐⭐ | ⭐⭐⭐⭐ | 11 | Highest ratio | | **gzip** (GNU zip) | ⭐⭐⭐ (60%) | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 6 | Best compatibility | | **lz4** (LZ4) | ⭐⭐ (50%) | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 0 | Fastest | **Recommendation**: **Zstd level 9** for optimal balance of compression ratio and speed. ### Compression Level Guidelines #### Zstd (Recommended) ```text Level 1-3: Fast compression, lower ratio (~55-65%) Level 9: Balanced (recommended) (~70%) Level 19: Maximum compression (~75%), 10x slower Level 22: Extreme (rarely needed) (~77%), 100x slower ``` **Recommendation**: Level 9 (default in reference implementation) #### Brotli ```text Level 4: Fast (~65%) Level 11: Maximum (recommended) (~72%) ``` **Note**: Levels 10-11 provide only marginal gains over level 6 but are much slower. #### Gzip ```text Level 6: Default (~60%) Level 9: Maximum (~62%) ``` **Note**: Gzip has minimal ratio improvement at higher levels. #### LZ4 ```text Level 0: Fast mode (default) (~50%) Level 9: High compression (~55%) ``` **Note**: LZ4 prioritizes speed over ratio. ### Processing Pipeline #### Encoding (Creating Compressed Data URI) ```text Agent Metadata (JSON object) ↓ 1. JSON.stringify() with compact separators (no whitespace) ↓ 2. UTF-8 encode β†’ bytes ↓ 3. Compress with algorithm (e.g., zstd level 9) ↓ 4. Base64 encode ↓ 5. Prepend header: "data:application/json;enc=zstd;level=9;base64," ↓ Compressed Data URI (ready for on-chain storage) ``` #### Decoding (Parsing Compressed Data URI) ```text Compressed Data URI ↓ 1. Parse header parameters (detect "enc=zstd") ↓ 2. Extract base64 payload ↓ 3. Base64 decode β†’ compressed bytes ↓ 4. Decompress with detected algorithm (with size limit check) ↓ 5. UTF-8 decode β†’ JSON string ↓ 6. JSON.parse() ↓ Agent Metadata (JSON object) ``` ## Security Considerations ### 1. Zip Bomb Protection ⚠️ **Attack Vector**: Adversary uploads small compressed data that expands to enormous size **Example**: ```text Compressed: 10KB Decompressed: 10GB (1000x expansion) Result: Memory exhaustion, DoS ``` **Defense**: Strict decompression size limits ```python MAX_DECOMPRESSED_SIZE = 100 * 1024 # 100KB hard limit def safe_decompress(data, algorithm): decompressed = decompress_with_algorithm(data, algorithm) if len(decompressed) > MAX_DECOMPRESSED_SIZE: raise SecurityError("Decompressed data exceeds 100KB (possible zip bomb)") return decompressed ``` **8004scan Implementation**: * 100KB decompression limit enforced * Decompression in async workers (isolated) * Security events logged for monitoring ### 2. Algorithm Whitelist **Attack Vector**: Malicious algorithm name causes arbitrary code execution **Defense**: Strict whitelist of allowed algorithms ```python ALLOWED_ALGORITHMS = {"zstd", "gzip", "br", "lz4"} if algorithm not in ALLOWED_ALGORITHMS: raise ValueError(f"Algorithm not allowed: {algorithm}") ``` **8004scan Implementation**: * Only 4 algorithms supported * Reject all unknown algorithms with clear error * No dynamic algorithm loading ### 3. Async Decompression **Problem**: CPU-intensive decompression can block API requests **Solution**: Process in background workers ```python # API endpoint (returns immediately) @router.post("/agents") async def create_agent(agent_uri: str): task_id = parse_agent_metadata.delay(agent_uri) return {"status": "processing", "task_id": task_id} # Celery worker (handles decompression) @celery_app.task def parse_agent_metadata(uri: str): metadata = parse_compressed_data_uri(uri) # Safe here # Store in database... ``` **8004scan Implementation**: * All URI parsing in Celery workers * API never blocks on decompression * Worker isolation prevents DoS on API server ### 4. JSON Validation **Defense**: Always validate decompressed data is valid JSON ```python try: metadata = json.loads(decompressed_data) except json.JSONDecodeError: raise ValueError("Decompressed data is not valid JSON") if not isinstance(metadata, dict): raise ValueError("Metadata must be a JSON object (not array or primitive)") ``` ## Gas Cost Analysis ### Detailed Gas Cost Breakdown **Estimated Gas Costs** (based on calldata pricing): | Data Size | Gas (Uncompressed) | Gas (Compressed @ 60%) | **Gas Reduction** | | --------- | ------------------ | ---------------------- | ----------------- | | **1KB** | ~37,000 | - | - | | **2KB** | ~53,000 | ~29,000 | ~24,000 (45%) | | **3KB** | ~69,000 | ~37,000 | ~32,000 (46%) | | **5KB** | ~101,000 | ~53,000 | ~48,000 (48%) | | **8KB** | ~149,000 | ~77,000 | ~72,000 (48%) | | **10KB** | ~181,000 | ~93,000 | ~88,000 (49%) | **Formula**: ```text Gas = (size_bytes Γ— 16) + 21,000 # 16 gas per calldata byte + base tx cost ``` **Compression ratio assumption**: 60% (conservative estimate - zstd typically achieves 65-75%) **⚠️ Important**: These are theoretical estimates. Actual gas costs and compression ratios need to be measured with real-world on-chain deployment data. ### When to Use Compression | Scenario | Uncompressed Size | Recommendation | | -------------------- | ----------------- | ----------------------------------------------------- | | **Minimal metadata** | < 1KB | ❌ Don't compress (overhead not worth it) | | **Typical agent** | 1-3KB | βš–οΈ Optional (saves ~24,000-32,000 gas) | | **Full metadata** | 3-8KB | βœ… Recommended (saves ~32,000-72,000 gas) | | **Rich metadata** | 8-20KB | βœ…βœ… Strongly recommended (saves ~72,000-176,000 gas) | | **Complex agent** | > 20KB | βœ…βœ… Essential (saves 176,000+ gas) | **Rule of Thumb**: If metadata > 3KB, always use compression. **Note**: Gas savings are estimates based on 60% compression ratio. Actual savings may vary. ### Real-World Cost Examples #### Example 1: Minimal Agent (1.5KB) ```json { "type": "...", "name": "SimpleAgent", "description": "Basic agent with one endpoint", "image": "ipfs://...", "endpoints": [{ "name": "MCP", "endpoint": "..." }] } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 1.5KB | ~45,000 | | Compressed | ~0.6KB | ~30,000 | | **Gas Reduction** | - | **~15,000 (33%)** | **Verdict**: Marginal gas savings, compression optional. #### Example 2: Typical Agent (3KB) ```json { "type": "...", "name": "DataAnalyst Pro", "description": "...", "image": "...", "endpoints": [ {"name": "MCP", "endpoint": "...", "version": "...", "mcpTools": [...]}, {"name": "A2A", "endpoint": "...", "version": "...", "a2aSkills": [...]}, {"name": "agentWallet", "endpoint": "..."} ], "registrations": [...], "supportedTrust": ["reputation", "crypto-economic"] } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 3KB | ~69,000 | | Compressed | ~1.2KB | ~37,000 | | **Gas Reduction** | - | **~32,000 (46%)** | **Verdict**: βœ… Recommended - good gas savings. #### Example 3: Full Metadata (8KB) ```json { "type": "...", "name": "Enterprise Agent", "description": "...", "image": "...", "endpoints": [ {"name": "MCP", "endpoint": "...", "mcpTools": [30 tools], "mcpPrompts": [...]}, {"name": "A2A", "endpoint": "...", "a2aSkills": [50 skills]}, {"name": "OASF", "endpoint": "...", "skills": [100 skills], "domains": [...]}, {"name": "agentWallet", "endpoint": "..."} ], "registrations": [multiple chains], "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"], "active": true, "x402Support": true } ``` | Format | Size | Gas | | ----------------- | ------ | ----------------- | | Uncompressed | 8KB | ~149,000 | | Compressed | ~2.5KB | ~61,000 | | **Gas Reduction** | - | **~88,000 (59%)** | **Verdict**: βœ…βœ… Strongly recommended - major gas savings. ## Adoption Strategy ### Phase 1: Support (Current) **Status**: βœ… Complete **8004scan Capabilities**: * βœ… Parser supports compressed Data URIs * βœ… Documentation published * βœ… Reference implementation available * βœ… Security measures implemented **Developer Actions**: None required - existing agents work unchanged ### Phase 2: Tooling **Status**: 🚧 In Progress **8004scan Will Provide**: * Web-based compression tool (paste JSON β†’ get compressed URI) * CLI tool for batch compression * Frontend SDK integration examples * Gas savings calculator **Developer Actions**: * Use tools to generate compressed URIs * Test with existing agents ### Phase 3: Incentivization **Status**: πŸ“… Planned **8004scan Features**: * πŸ’° Badge on explorer: "Gas-Optimized" for compressed agents * πŸ“Š Analytics dashboard: Compression adoption rate * πŸ† Leaderboard: Most gas-efficient agents * πŸ’‘ UI hints: "Save ~32,000 gas by compressing" on registration **Developer Actions**: * Migrate existing agents to compression * Monitor gas savings ### Phase 4: Standardization **Status**: πŸ“… Future **Community Efforts**: * Propose compression extension to ERC-8004 spec * Submit EIP if adoption > 30% * Coordinate with other explorers **Developer Actions**: * Provide feedback on protocol * Participate in governance ## Reference Implementation The 8004scan reference implementation provides a robust framework for handling compressed metadata. Key features: * **Multi-Algorithm Support**: Full support for zstd, gzip, brotli, and lz4 algorithms. * **Browser Compatibility**: Gzip and deflate support for frontend applications. * **Security First**: Built-in zip bomb protection, algorithm whitelisting, and async processing. ### Quick Start Examples **Python** (Zstd-15 recommended): ```python 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) ``` **TypeScript** (using fflate for gzip): ```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 compressedBytes = Uint8Array.from(atob(data), (c) => c.charCodeAt(0)); const jsonStr = new TextDecoder().decode(decompress(compressedBytes)); const metadata = JSON.parse(jsonStr); ``` **Security Note**: Always implement zip bomb protection (100KB decompression limit) in production. For production deployment, refer to the security considerations and follow the recommended implementation patterns. ## FAQ ### General **Q: Is this an official ERC-8004 feature?** A: No, this is an **optional extension** proposed by 8004scan. The official ERC-8004 spec does not specify compression. However, this extension is designed to be **forward-compatible** with future spec updates. **Q: Will old clients break?** A: Old clients will **fail gracefully** with a clear error message indicating compression is not supported. They will NOT silently misparse the data. **Q: Can I mix compressed and uncompressed agents?** A: Yes, 8004scan supports both formats seamlessly. You can update agents incrementally. ### Technical **Q: Which algorithm should I use?** A: **Zstd level 9** for best balance. Brotli level 11 for maximum compression (slightly better ratio, slower). **Q: Can I use custom compression algorithms?** A: No, only `zstd`, `gzip`, `br`, and `lz4` are allowed for security reasons. **Q: What happens if I exceed 100KB decompressed?** A: Parse will fail with `SecurityError`. Split metadata across multiple agents or use IPFS for large data. **Q: Does compression work with IPFS URIs?** A: This protocol is for **Data URIs only**. IPFS URIs should remain uncompressed (already efficient). ### Gas & Cost **Q: Is compression worth it for 1KB metadata?** A: Marginal gas savings (~15,000-20,000 gas reduction). Optional unless you value immutability highly. **Q: Is compression still worth it at low gas prices?** A: Yes. Compression saves ~24,000-88,000 gas per agent regardless of gas price. The percentage savings (45-59%) remains constant. **Q: Can I update metadata after registration?** A: Yes, call `setAgentURI(agentId, newURI)` on the registry contract. However, this costs additional gas (~45,000 gas). Consider using mutable storage (IPFS/HTTP) if frequent updates are needed. ### Security **Q: Is this safe?** A: Yes, with proper implementation. 8004scan enforces: * 100KB decompression size limit (zip bomb protection) * Algorithm whitelist (no arbitrary code) * Async processing (no API blocking) * JSON validation (data integrity) **Q: What if someone tries a zip bomb?** A: Decompression will fail safely with `SecurityError`. No system impact. **Q: Can metadata be tampered with?** A: No, Data URI metadata is stored on-chain and cryptographically verified by the blockchain. ## Appendix ### Algorithm Comparison #### Test Metadata (3KB JSON) ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Test Agent", ... } ``` | Algorithm | Level | Compressed Size | Ratio | Compression Time | Decompression Time | | --------- | ----- | --------------- | ----- | ---------------- | ------------------ | | zstd | 9 | 1.2KB | 60% | 5ms | 1ms | | zstd | 19 | 1.1KB | 63% | 50ms | 1ms | | brotli | 11 | 1.1KB | 63% | 120ms | 3ms | | gzip | 6 | 1.5KB | 50% | 8ms | 2ms | | gzip | 9 | 1.4KB | 53% | 15ms | 2ms | | lz4 | 0 | 1.8KB | 40% | 2ms | 1ms | **Conclusion**: Zstd level 9 offers best balance (good ratio, fast speed). ### Changelog | Version | Date | Changes | | ------- | ---------- | --------------------------------------------------------------- | | **0.1** | 2025-12-20 | Initial draft - protocol specification and implementation guide | ### Contact & Feedback * **Maintainer**: 8004scan Development Team **Feedback Channels**: * GitHub Issues: Technical bugs and feature requests *(coming soon)* * Discord: Community discussion and support *(coming soon)* * Email: maintainers@altresear.ch --- --- url: /DEVELOPMENT.md --- # Development Guide ## Multi-Site Architecture This project uses a multi-site VitePress architecture to maintain multiple documentation versions: * **Main Site** (v1.1): Current documentation at `/` * **Legacy Site** (pre-v1): Archived documentation at `/legacy-pre-v1/` ## Local Development ### Option 1: Run Main Site Only ```bash npm run dev # or make dev ``` Access at: http://localhost:5173 ### Option 2: Run Legacy Site Only ```bash npm run dev:legacy # or make dev-legacy ``` Access at: http://localhost:5174 ### Option 3: Run Both Sites Simultaneously ```bash make dev-all ``` * Main site: http://localhost:5173 * Legacy site: http://localhost:5174 **To stop both servers:** ```bash # In another terminal make stop-dev ``` Or press `Ctrl+C` in the terminal running `make dev-all`. **Note**: In local development, the `/legacy-pre-v1/` link from the main site will 404. To test legacy docs, use Option 2 or 3 above. ## Building for Production Build both sites and merge them: ```bash npm run build # or make build ``` This will: 1. Build main site β†’ `.vitepress/dist/` 2. Build legacy site β†’ `legacy-pre-v1/.vitepress/dist/` 3. Copy legacy build into main β†’ `.vitepress/dist/legacy-pre-v1/` Preview the merged build: ```bash npm run preview # or make preview ``` Access at: http://localhost:4173 Now the `/legacy-pre-v1/` link will work correctly! ## GitHub Pages Deployment The GitHub Actions workflow (`.github/workflows/deploy.yml`) automatically: 1. Builds both sites 2. Merges them 3. Deploys to GitHub Pages The deployed site will have: * Main site at `https://best-practices.8004scan.io/` * Legacy site at `https://best-practices.8004scan.io/legacy-pre-v1/` ## Directory Structure ```text . β”œβ”€β”€ .vitepress/ # Main site config β”‚ └── config.mts # Main VitePress config (base: "/") β”œβ”€β”€ docs/ # Main site content (v1.1) β”œβ”€β”€ legacy-pre-v1/ # Legacy site β”‚ β”œβ”€β”€ .vitepress/ # Legacy site config β”‚ β”‚ └── config.mts # Legacy VitePress config (base: "/legacy-pre-v1/") β”‚ └── docs/ # Legacy site content (pre-v1) └── index.md # Main site homepage ``` ## Tips * The `base` path in each config must match deployment structure * Main site: `base: "/"` * Legacy site: `base: "/legacy-pre-v1/"` * Links between sites should use absolute URLs in production --- --- url: /MIGRATION_PLAN.md --- # endpoints β†’ services Migration Plan **Status**: In Progress **Started**: 2026-01-29 ## Context Analysis Found **313 occurrences** of "endpoint" in docs directory. Need to categorize and handle appropriately. ## Category Classification ### 1. βœ… NO CHANGE NEEDED - Different Context * **Feedback `endpoint` field** (singular, string) - refers to which service was used * **Service object `endpoint` property** - the URL/identifier within each service * **Function parameters** named `endpoint` * **Prose describing "endpoints" as concept** (communication endpoints, API endpoints) * **Section titles** like "Endpoint Types" (describes service types) ### 2. ⚠️ MUST CHANGE - Agent Metadata Field * **`"endpoints": [`** in JSON examples of agent metadata * **Text explicitly referring to the agent metadata field name** * **Parser code referencing the field** ### 3. πŸ” NEEDS REVIEW - Ambiguous References * Prose text that could be interpreted as referring to the field vs concept * Examples in implementation guides ## Files Requiring Changes ### Priority 1: JSON Examples in Agent Metadata Context #### 1. docs/reference/real-world-examples.md **Status**: ⏳ Pending * Line 40: Example 1 - Basic agent metadata * Line 83: Example 2 - Complete agent with MCP/A2A * Line 138: Example 3 - Multi-protocol agent * Line 170: Example 4 - Empty endpoints array * Line 239: Example 5 - Custom protocols **Action**: Replace `"endpoints": [` with `"services": [` #### 2. docs/extensions/data-uri-compression.md **Status**: ⏳ Pending * Line 382: Small metadata example * Line 402: Medium-size example * Line 428: Large metadata example **Action**: Replace `"endpoints": [` with `"services": [` #### 3. docs/implementation/agent-metadata-parsing.md **Status**: ⏳ Pending * Contains references to parsing "endpoints" field * Examples with `"endpoints": [` **Action**: * Update JSON examples to use `"services"` * Update parsing logic descriptions to mention both field names * Add backward compatibility notes #### 4. docs/implementation/error-codes.md **Status**: ⏳ Pending * Line 922: Error example * Line 952: Another error example * Line 1191: Plural warning example **Action**: Update example schemas to use `"services": [` #### 5. docs/01-agent-metadata-standard.md **Status**: ⏳ Pending (partial - some already done) * Line 614: Example in agentWallet section * Line 693: Example in Human-Facing Endpoints section **Action**: Update remaining inline examples to use `"services"` #### 6. docs/official-specification/erc-8004-official.md **Status**: ⏳ Pending - **CRITICAL** * Line 61: Official spec example uses `"endpoints"`! * Line 111: Text refers to "endpoints" field * Line 113: "Agents MAY advertise their endpoints" **Action**: This is the official spec copy - needs careful review. Should match EIP-8004 exactly. ### Priority 2: Prose Text Requiring Clarification #### docs/01-agent-metadata-standard.md * Line 318-319: "Communication endpoints for interacting with the agent" * **Action**: Add note: "(now called `services` field)" * Line 354: "See Endpoint Types section" * **Action**: Keep as-is (section title describes service types conceptually) #### docs/README.md * Line 23: "AgentURI format - identity, endpoints, trust" * **Action**: Change to "identity, services, trust" or "identity, service endpoints, trust" #### docs/GLOSSARY.md * Line 160: "Points to JSON containing agent identity, endpoints, and capabilities" * **Action**: Change to "services, and capabilities" ### Priority 3: Section Titles #### "Endpoint Types" Section **Current**: Describes MCP, A2A, OASF, etc. **Decision**: * Option A: Rename to "Service Types" * Option B: Keep as "Endpoint Types" (describes types of endpoints/services) * **Recommendation**: Keep as-is, add clarification note at top ## Text Patterns Analysis ### Pattern 1: JSON Field References ```regex "endpoints"\s*:\s*\[ ``` **Count**: ~15 occurrences **Action**: Replace with `"services": [` ### Pattern 2: Field Name in Prose ```text the endpoints field the endpoints array ``` **Action**: Replace with "the services field/array" ### Pattern 3: Concept References (OK) ```text communication endpoints API endpoints service endpoints multiple endpoints ``` **Action**: No change needed (conceptual) ### Pattern 4: Feedback Context (OK) ```text endpoint field (in feedback) which endpoint was used track the endpoint ``` **Action**: No change (different context) ## Implementation Steps ### Step 1: Update JSON Examples (High Priority) * \[ ] docs/reference/real-world-examples.md (5 locations) * \[ ] docs/extensions/data-uri-compression.md (3 locations) * \[ ] docs/implementation/error-codes.md (3 locations) * \[ ] docs/01-agent-metadata-standard.md (2 locations) * \[ ] docs/implementation/agent-metadata-parsing.md ### Step 2: Review Official Spec Copy * \[ ] docs/official-specification/erc-8004-official.md * Check if this is intended to mirror EIP-8004 exactly * If yes: Update only if EIP-8004 was updated * If no: Update to match our recommendations ### Step 3: Update Prose References * \[ ] docs/README.md * \[ ] docs/GLOSSARY.md * \[ ] Add clarification notes where "endpoints" is used conceptually ### Step 4: Add Terminology Section to GLOSSARY.md Add entry explaining: * `services` = top-level field in agent metadata (array) βœ… NEW * `endpoints` = legacy name for services field ⚠️ DEPRECATED * `endpoint` = property within service objects (URL/identifier) βœ… OK * `endpoint` = field in feedback data (which service was used) βœ… OK ### Step 5: Verification * \[ ] Run: `grep -r '"endpoints"\s*:\s*\[' docs/ --exclude-dir=v1 --exclude-dir=legacy-pre-v1` * \[ ] Verify no false positives * \[ ] Check all examples are valid JSON * \[ ] Review prose for consistency ## Special Cases ### Case 1: Official EIP-8004 Specification Copy **File**: `docs/official-specification/erc-8004-official.md` **Issue**: Uses `"endpoints"` but this is supposedly the official spec **Resolution**: 1. Check if this file is meant to be a verbatim copy of EIP-8004 2. If yes: May need to keep `endpoints` if EIP-8004 spec text itself hasn't updated examples 3. If no: Update to match our recommendations 4. Add editor note clarifying the discrepancy ### Case 2: Backward Compatibility Examples Should we show both formats in examples? **Decision**: No - show only `services` in main examples, mention `endpoints` in migration notes ### Case 3: v1/ and legacy-pre-v1/ directories **Decision**: Do NOT modify - these are historical documentation ## Testing Checklist After migration: * \[ ] All JSON examples are valid JSON * \[ ] No broken internal links * \[ ] Grep confirms no remaining `"endpoints": [` in main docs (excluding v1/legacy) * \[ ] GLOSSARY.md has clear terminology section * \[ ] Migration guide is referenced where appropriate * \[ ] CI markdown linting passes ## Rollback Plan If issues found: 1. Git revert to commit before migration 2. Review problematic cases 3. Update plan and retry *** **Next Action**: Begin Step 1 - Update JSON examples in real-world-examples.md --- --- url: /docs/README.md description: Non-normative implementation guidance for ERC-8004 Trustless Agents --- ## Description This documentation provides **official best practices and recommended data profiles** for [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004), maintained and fully supported by the **8004scan team**. These specifications cover offchain JSON formats and implementation patterns based on real-world production usage. > \[!NOTE] > This is **not** the official EIP-8004 specification. These are supplementary best practices maintained by 8004scan to help implementers adopt consistent, interoperable patterns. See [Official Specification](/docs/official-specification/erc-8004-official) for normative requirements. ## Core Data Profiles | Profile | Description | | ------------------------------------------------------------------- | ---------------------------------------------- | | [Conventions](00-CONVENTIONS.md) | RFC 2119 keywords, field types, URI schemes | | [Agent Metadata](01-agent-metadata-standard.md) | AgentURI format - identity, services, trust | | [Feedback Data](02-feedback-standard.md) | Reputation records - values, evidence, payment | | [Validation Data](03-validation-standard.md) | Proofs and attestations - zkML, TEE, staking | | [Attachment Pattern](extensions/04-attachment-pattern-standard.md) | Reusable evidence schema for files | | [Value Decimals Patterns](extensions/05-value-decimals-patterns.md) | Standard patterns for v2.0 value system | ## Quick Start ### Registering an Agent ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", "description": "What my agent does", "image": "https://example.com/logo.png" } ``` See [Agent Metadata Profile](01-agent-metadata-standard.md) for full schema. ### Submitting Feedback ```json { "agentRegistry": "eip155:84532:0x...", "agentId": 42, "value": "4.75", "valueDecimals": 2, "reasoning": "Excellent service" } ``` See [Feedback Data Profile](02-feedback-standard.md) for full schema. ### Requesting Validation ```json { "agentRegistry": "eip155:84532:0x...", "agentId": 56, "validationType": "zkml-proof", "reasoning": "Verify model execution" } ``` See [Validation Data Profile](03-validation-standard.md) for full schema. ## Implementation Guides * [Agent Metadata Parsing](implementation/agent-metadata-parsing.md) - Parser architecture and validation * [Feedback Best Practices](implementation/feedback-best-practices.md) - Evidence collection and privacy * [Validation Best Practices](implementation/validation-best-practices.md) - Proof integration patterns * [Migration Guide: v1.x β†’ v2.0](implementation/migration-v1-to-v2.md) - Upgrade path to the latest spec * [Migration Guide: pre-v1 β†’ v1.x](implementation/migration-v0-4-to-v1-0.md) - Upgrade path from legacy to v1.x ## Extensions * [Value Decimals Patterns](extensions/05-value-decimals-patterns.md) - Best practices for v2.0 flexible metrics * [Data URI Compression](extensions/data-uri-compression.md) - 60-70% gas savings for onchain metadata ## Reference * [Glossary](GLOSSARY.md) - Terms and abbreviations * [Sources](reference/sources.md) - Data sources and methodology * [Official EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) - Normative specification ## Relationship to EIP-8004 | Aspect | EIP-8004 (Official) | 8004scan Best Practices | | --------- | ------------------------- | ------------------------------- | | Defines | Smart contract interfaces | Offchain data patterns | | Scope | Onchain behavior | Best practices (recommended) | | Authority | Ethereum EIP process | 8004scan-maintained specs | | Adoption | MUST for compliance | SHOULD for interoperability | | Support | EIP governance | Full 8004scan support & updates | ## Contributing * [Report an issue](https://github.com/alt-research/8004scan-issue-tracker/issues) * See [CONTRIBUTING.md](/CONTRIBUTING.md) for guidelines --- --- url: /legacy-pre-v1/docs/README.md description: Non-normative implementation guidance for ERC-8004 Trustless Agents --- ## Description This documentation provides **non-normative, community-maintained data profiles and best practices** for [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004), covering offchain JSON formats and implementation patterns. > \[!IMPORTANT] > This is **not** the official EIP-8004 specification. These are supplementary guidelines to help implementers adopt consistent patterns. ## Core Data Profiles | Profile | Description | | ------------------------------------------------------- | ---------------------------------------------- | | [Conventions](00-CONVENTIONS.md) | RFC 2119 keywords, field types, URI schemes | | [Agent Metadata](01-agent-metadata-standard.md) | AgentURI format - identity, endpoints, trust | | [Feedback Data](02-feedback-standard.md) | Reputation records - scores, evidence, payment | | [Validation Data](03-validation-standard.md) | Proofs and attestations - zkML, TEE, staking | | [Attachment Pattern](04-attachment-pattern-standard.md) | Reusable evidence schema for files | ## Quick Start ### Registering an Agent ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", "description": "What my agent does", "image": "https://example.com/logo.png" } ``` See [Agent Metadata Profile](01-agent-metadata-standard.md) for full schema. ### Submitting Feedback ```json { "agentRegistry": "eip155:84532:0x...", "agentId": 42, "score": 95, "reasoning": "Excellent service" } ``` See [Feedback Data Profile](02-feedback-standard.md) for full schema. ### Requesting Validation ```json { "agentRegistry": "eip155:84532:0x...", "agentId": 56, "validationType": "zkml-proof", "reasoning": "Verify model execution" } ``` See [Validation Data Profile](03-validation-standard.md) for full schema. ## Implementation Guides * [Agent Metadata Parsing](implementation/agent-metadata-parsing.md) - Parser architecture and validation * [Feedback Best Practices](implementation/feedback-best-practices.md) - Evidence collection and privacy * [Validation Best Practices](implementation/validation-best-practices.md) - Proof integration patterns ## Extensions * [Data URI Compression](extensions/data-uri-compression.md) - 60-70% gas savings for onchain metadata ## Reference * [Glossary](GLOSSARY.md) - Terms and abbreviations * [Sources](reference/sources.md) - Data sources and methodology * [Official EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) - Normative specification ## Relationship to EIP-8004 | Aspect | EIP-8004 (Official) | These Profiles (Community) | | ------------- | ---------------------------- | ------------------------------- | | **Defines** | Smart contract interfaces | Offchain data patterns | | **Scope** | Onchain behavior (normative) | Metadata recommendations | | **Authority** | Ethereum EIP process | Community-maintained guidelines | | **Adoption** | MUST for compliance | SHOULD for interoperability | ## Contributing * [Report an issue](https://github.com/alt-research/8004scan-issue-tracker/issues) * See [CONTRIBUTING.md](/CONTRIBUTING) for guidelines --- --- url: /v1/docs/README.md description: Non-normative implementation guidance for ERC-8004 Trustless Agents --- ## Description This documentation provides **official best practices and recommended data profiles** for [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004), maintained and fully supported by the **8004scan team**. These specifications cover offchain JSON formats and implementation patterns based on real-world production usage. > \[!NOTE] > This is **not** the official EIP-8004 specification. These are supplementary best practices maintained by 8004scan to help implementers adopt consistent, interoperable patterns. See [Official Specification](/docs/official-specification/erc-8004-official) for normative requirements. ## Core Data Profiles | Profile | Description | | ------------------------------------------------------------------ | ---------------------------------------------- | | [Conventions](00-CONVENTIONS.md) | RFC 2119 keywords, field types, URI schemes | | [Agent Metadata](01-agent-metadata-standard.md) | AgentURI format - identity, endpoints, trust | | [Feedback Data](02-feedback-standard.md) | Reputation records - scores, evidence, payment | | [Validation Data](03-validation-standard.md) | Proofs and attestations - zkML, TEE, staking | | [Attachment Pattern](extensions/04-attachment-pattern-standard.md) | Reusable evidence schema for files | ## Quick Start ### Registering an Agent ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", "description": "What my agent does", "image": "https://example.com/logo.png" } ``` See [Agent Metadata Profile](01-agent-metadata-standard.md) for full schema. ### Submitting Feedback ```json { "agentRegistry": "eip155:84532:0x...", "agentId": 42, "score": 95, "reasoning": "Excellent service" } ``` See [Feedback Data Profile](02-feedback-standard.md) for full schema. ### Requesting Validation ```json { "agentRegistry": "eip155:84532:0x...", "agentId": 56, "validationType": "zkml-proof", "reasoning": "Verify model execution" } ``` See [Validation Data Profile](03-validation-standard.md) for full schema. ## Implementation Guides * [Agent Metadata Parsing](implementation/agent-metadata-parsing.md) - Parser architecture and validation * [Feedback Best Practices](implementation/feedback-best-practices.md) - Evidence collection and privacy * [Validation Best Practices](implementation/validation-best-practices.md) - Proof integration patterns * [Migration Guide: pre-v1 β†’ v1.1](implementation/migration-v0-4-to-v1-0.md) - Upgrade path from legacy to v1.1 ## Extensions * [Data URI Compression](extensions/data-uri-compression.md) - 60-70% gas savings for onchain metadata ## Reference * [Glossary](GLOSSARY.md) - Terms and abbreviations * [Sources](reference/sources.md) - Data sources and methodology * [Official EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) - Normative specification ## Relationship to EIP-8004 | Aspect | EIP-8004 (Official) | 8004scan Best Practices | | --------- | ------------------------- | ------------------------------- | | Defines | Smart contract interfaces | Offchain data patterns | | Scope | Onchain behavior | Best practices (recommended) | | Authority | Ethereum EIP process | 8004scan-maintained specs | | Adoption | MUST for compliance | SHOULD for interoperability | | Support | EIP governance | Full 8004scan support & updates | ## Contributing * [Report an issue](https://github.com/alt-research/8004scan-issue-tracker/issues) * See [CONTRIBUTING.md](/CONTRIBUTING.md) for guidelines --- --- url: /VERSION.md --- # ERC-8004 Documentation Versions We maintain documentation for multiple ERC-8004 specification versions to support both current and legacy implementations. ## Current Versions ### [v1.1 (Latest)](/docs/README) **Released**: January 2026 **Status**: βœ… Current / Recommended The latest ERC-8004 specification with simplified feedback flow, string-based tags, and removed authorization requirements. **Key Features**: * βœ… Simplified tag system (strings instead of bytes32) * βœ… Removed feedbackAuth requirement * βœ… New `endpoint` field support * βœ… Improved URI naming conventions * βœ… Cleaner contract interfaces **Start Here**: [v1.1 Documentation](/docs/README) *** ### [pre-v1 (Legacy Archive)](/legacy-pre-v1/README) **Released**: December 2025 **Status**: ⚠️ Archived / Legacy The previous ERC-8004 specification. Maintained for historical reference and backwards compatibility. **Key Characteristics**: * `bytes32` encoded tags (requires UTF-8 encoding/decoding) * Feedback authorization flow (`feedbackAuth`) * `feedbackUri` naming (lowercase `i`) * Calculated `feedbackIndex` in subgraph **Migrate From pre-v1 (legacy)?**: [Read the migration guide](/docs/implementation/migration-v0-4-to-v1-0.md) **View pre-v1 (legacy) Docs**: [Archive](/legacy-pre-v1/README) *** ## What Changed? | Feature | pre-v1 (legacy) | v1.1 | | ----------------- | --------------- | ----------------- | | **Tags** | `bytes32` (hex) | `string` (direct) | | **Feedback Auth** | Required | Removed | | **URI Naming** | `feedbackUri` | `feedbackURI` | | **Endpoint** | N/A | βœ“ NEW | | **Complexity** | Higher | Lower | **Full details**: [Migration Guide: pre-v1 (legacy) β†’ v1.1](/docs/implementation/migration-v0-4-to-v1-0.md) *** ## Quick Navigation ### New to ERC-8004? β†’ Start with [v1.1 Documentation](/docs/README) ### Using pre-v1 (legacy) and want to upgrade? β†’ Read the [Migration Guide](/docs/implementation/migration-v0-4-to-v1-0.md) ### Need pre-v1 (legacy) docs? β†’ Visit [legacy archive](/legacy-pre-v1/README) ### Questions about spec changes? β†’ See the [Update Guide](https://best-practices.8004scan.io/docs/implementation/migration-v0-4-to-v1-0) *** ## Version Timeline ```text December 2025 β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ pre-v1 β”‚ (Initial release) β”‚ Release β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ January 2026 β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ pre-v1 Frozen β”‚ (Legacy archive) β”‚ (No more updates) β”‚ β”‚ v1.1 Released β”‚ (New standard) β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ (You are here) β–Ό Today ``` *** ## Support * **Documentation Questions**: Check the specific version docs * **Migration Help**: See [Migration Guide](/docs/implementation/migration-v0-4-to-v1-0.md) * **Contract Issues**: [GitHub Issues](https://github.com/erc-8004/erc-8004-contracts/issues) * **General ERC-8004**: [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) *** **Last Updated**: January 9, 2026 --- --- url: /legacy-pre-v1/README.md --- # ERC-8004 pre-v1 Legacy Documentation This is the **archived documentation for the pre-v1 legacy release**, maintained for historical reference. ## Status * **Version**: pre-v1 (legacy) * **Released**: December 2025 * **Status**: Legacy / Archived * **Recommended**: Use [v1.1 documentation](https://best-practices.8004scan.io/) instead ## Key Characteristics ### Contract Changes (pre-v1 legacy β†’ v1.1) | Field | pre-v1 (legacy) | v1.1 | | --------------- | --------------- | ------------------------ | | `tag1` | `bytes32` | `string` | | `tag2` | `bytes32` | `string` | | `feedbackUri` | βœ“ | Renamed to `feedbackURI` | | `endpoint` | βœ— | βœ“ NEW | | `feedbackAuth` | βœ“ Required | Removed | | `feedbackIndex` | Calculated | From event | ### Breaking Changes 1. **Tag Types**: `bytes32` β†’ `string` (direct string, no encoding) 2. **URI Naming**: `feedbackUri` β†’ `feedbackURI` (case change) 3. **FeedbackAuth Removed**: No longer required for feedback submission 4. **New Endpoint Field**: Specifies the service endpoint used 5. **Simplified Contract**: Fewer parameters, cleaner signatures ## Migration Path If you're implementing against pre-v1 (legacy), see the [pre-v1 to v1.x migration guide](https://best-practices.8004scan.io/docs/implementation/migration-v0-4-to-v1-0) for detailed migration instructions. ## Documentation Contents * [Conventions](docs/00-CONVENTIONS.md) * [Agent Metadata Standard](docs/01-agent-metadata-standard.md) * [Feedback Data Standard](docs/02-feedback-standard.md) * [Validation Data Standard](docs/03-validation-standard.md) * [Attachment Pattern Standard](docs/04-attachment-pattern-standard.md) * [Glossary](docs/GLOSSARY.md) ## Why Archive pre-v1 (legacy)? The ERC-8004 specification underwent significant updates in January 2026: * **Simplified API**: Removed complex feedbackAuth flow * **String Tags**: More intuitive than bytes32 hashing * **Better Naming**: Consistent URI naming convention * **Cleaner Contracts**: Fewer parameters, easier to implement ## Links * **Current v1.1 Docs**: https://best-practices.8004scan.io/ * **Contract PR #11**: https://github.com/erc-8004/erc-8004-contracts/pull/11 * **Spec Update**: https://github.com/erc-8004/erc-8004-contracts/blob/main/SpecsJan26Update.md *** **Last Updated**: January 9, 2026 **Archive Created**: January 9, 2026 --- --- url: /legacy-pre-v1.md --- # ERC-8004 pre-v1 Legacy Documentation This is the **archived documentation for the pre-v1 legacy release**, maintained for historical reference. ## Status * **Version**: pre-v1 (legacy) * **Released**: December 2025 * **Status**: Legacy / Archived * **Recommended**: Use [v1.1 documentation](https://best-practices.8004scan.io/) instead ## Key Characteristics ### Contract Changes (pre-v1 legacy β†’ v1.1) | Field | pre-v1 (legacy) | v1.1 | | --------------- | --------------- | ------------------------ | | `tag1` | `bytes32` | `string` | | `tag2` | `bytes32` | `string` | | `feedbackUri` | βœ“ | Renamed to `feedbackURI` | | `endpoint` | βœ— | βœ“ NEW | | `feedbackAuth` | βœ“ Required | Removed | | `feedbackIndex` | Calculated | From event | ### Breaking Changes 1. **Tag Types**: `bytes32` β†’ `string` (direct string, no encoding) 2. **URI Naming**: `feedbackUri` β†’ `feedbackURI` (case change) 3. **FeedbackAuth Removed**: No longer required for feedback submission 4. **New Endpoint Field**: Specifies the service endpoint used 5. **Simplified Contract**: Fewer parameters, cleaner signatures ## Migration Path If you're implementing against pre-v1 (legacy), see the [pre-v1 to v1.x migration guide](https://best-practices.8004scan.io/docs/implementation/migration-v0-4-to-v1-0) for detailed migration instructions. ## Documentation Contents * [Conventions](docs/00-CONVENTIONS.md) * [Agent Metadata Standard](docs/01-agent-metadata-standard.md) * [Feedback Data Standard](docs/02-feedback-standard.md) * [Validation Data Standard](docs/03-validation-standard.md) * [Attachment Pattern Standard](docs/04-attachment-pattern-standard.md) * [Glossary](docs/GLOSSARY.md) ## Why Archive pre-v1 (legacy)? The ERC-8004 specification underwent significant updates in January 2026: * **Simplified API**: Removed complex feedbackAuth flow * **String Tags**: More intuitive than bytes32 hashing * **Better Naming**: Consistent URI naming convention * **Cleaner Contracts**: Fewer parameters, easier to implement ## Links * **Current v1.1 Docs**: https://best-practices.8004scan.io/ * **Contract PR #11**: https://github.com/erc-8004/erc-8004-contracts/pull/11 * **Spec Update**: https://github.com/erc-8004/erc-8004-contracts/blob/main/SpecsJan26Update.md *** **Last Updated**: January 9, 2026 **Archive Created**: January 9, 2026 --- --- url: /SPEC_CONFLICTS_ANALYSIS.md --- # ERC-8004 Specification Conflicts Analysis **Date**: 2026-01-29 **Official Spec**: https://eips.ethereum.org/EIPS/eip-8004 **Analysis Scope**: Documentation alignment with January 2026 EIP-8004 update ## Executive Summary The official EIP-8004 specification changed the field name from `endpoints` to `services` in the Agent Metadata structure (January 2026). While our main documentation (`docs/01-agent-metadata-standard.md`) has been updated with migration notices and compatibility guidance, **multiple example code snippets across the documentation still use the legacy `endpoints` field name**. ## Key Specification Change ### Field Name Migration: `endpoints` β†’ `services` **Official EIP-8004 (Jan 2026)**: ```json { "services": [ { "name": "MCP", "endpoint": "https://..." }, { "name": "A2A", "endpoint": "https://..." } ] } ``` **Legacy Format** (still supported for backward compatibility): ```json { "endpoints": [ { "name": "MCP", "endpoint": "https://..." }, { "name": "A2A", "endpoint": "https://..." } ] } ``` ### Important Distinction * **Agent Metadata**: `services` array (top-level field) - describes all available services * **Feedback Data**: `endpoint` string (single field) - specifies which service endpoint was used This is NOT a conflict - these are different fields in different contexts. ## Current Documentation Status ### βœ… Correctly Updated Files 1. **`docs/01-agent-metadata-standard.md`** * βœ… Has migration notice at top * βœ… Documents both `services` and `endpoints` with preference * βœ… Includes dedicated migration section * βœ… Main schema examples use `services` * ⚠️ BUT: Some examples in "Endpoint Types" section still use `endpoints` 2. **`docs/02-feedback-standard.md`** * βœ… Correctly uses `endpoint` (singular) for feedback data * βœ… No conflicts (different context) ### ⚠️ Files with Legacy `endpoints` in Examples The following files contain JSON examples that still use `"endpoints": [...]` instead of `"services": [...]`: 1. **`docs/extensions/data-uri-compression.md`** * Lines: 382, 402, 428 * Impact: Medium (compression examples guide) * Examples show agent metadata with `endpoints` field 2. **`docs/reference/real-world-examples.md`** * Lines: 40, 83, 138, 170, 239 * Impact: High (real-world reference examples) * All agent metadata examples use legacy format 3. **`docs/implementation/error-codes.md`** * Lines: 922, 952, 1191 * Impact: Low (error code documentation) * Example schemas in error descriptions 4. **`docs/implementation/agent-metadata-parsing.md`** * Contains examples with `endpoints` * Impact: High (parsing implementation guide) 5. **`docs/01-agent-metadata-standard.md`** * Lines: 614, 693 (in endpoint type examples) * Impact: Medium (inconsistency within same doc) ### πŸ“ Text References (Lower Priority) Many files reference "endpoints" in prose text (e.g., "Communication endpoints", "Endpoint Types"). These are generally acceptable as they refer to the concept, not the field name. However, when specifically discussing the JSON field, they should clarify whether referring to: * The top-level `services` array field * Individual `endpoint` properties within service objects * The feedback `endpoint` field ## Detailed Conflict Locations ### High Priority: Update Examples to Use `services` #### 1. `docs/reference/real-world-examples.md` **Location**: Lines 40, 83, 138, 170, 239 **Current**: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent Name", "endpoints": [{ "name": "MCP", "endpoint": "..." }] } ``` **Should be**: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent Name", "services": [{ "name": "MCP", "endpoint": "..." }] } ``` **Rationale**: This is a reference document - examples must follow current spec. #### 2. `docs/implementation/agent-metadata-parsing.md` **Impact**: High - guides parser implementations **Action**: Update all JSON examples to use `services` field, add note about backward compatibility parsing. #### 3. `docs/extensions/data-uri-compression.md` **Location**: Lines 382, 402, 428 **Action**: Update compression examples to use `services` field. ### Medium Priority: Clarify Field References #### 4. `docs/01-agent-metadata-standard.md` **Location**: Section "Endpoint Types" (lines ~614, 693) **Current Issue**: Examples within endpoint type descriptions use legacy `endpoints` field. **Action**: Update inline examples to use `services` for consistency with main schema. #### 5. `docs/implementation/error-codes.md` **Location**: Lines 922, 952, 1191 **Action**: Update example schemas in error descriptions to use `services`. ### Low Priority: Terminology Clarification **Files with "endpoints" in prose**: * `docs/GLOSSARY.md` * `docs/README.md` * `docs/reference/sources.md` **Action**: Add clarification that "endpoints" in text refers to service endpoints (concept), while the JSON field is `services`. ## Recommended Fix Strategy ### Phase 1: Update Core Examples (Immediate) 1. Update all JSON examples in `docs/reference/real-world-examples.md` to use `services` 2. Update examples in `docs/implementation/agent-metadata-parsing.md` 3. Update compression examples in `docs/extensions/data-uri-compression.md` ### Phase 2: Fix Inline Inconsistencies 1. Update remaining examples in `docs/01-agent-metadata-standard.md` "Endpoint Types" section 2. Update error code examples in `docs/implementation/error-codes.md` ### Phase 3: Add Clarifying Notes 1. Add terminology note in `docs/GLOSSARY.md` explaining: * `services` = top-level field in agent metadata (array) * `endpoint` = property within each service object (string) * `endpoint` = field in feedback data (string, different context) ### Backward Compatibility Note All documentation should include a note that: * Parsers MUST support both `services` and `endpoints` field names * When both exist, `services` takes precedence * New implementations SHOULD use `services` * Legacy `endpoints` will continue to work but emit WA031 warning ## Files NOT Requiring Changes ### βœ… Feedback-Related Files * `docs/02-feedback-standard.md` - Uses `endpoint` (singular) correctly * Any file discussing feedback's `endpoint` field ### βœ… v1 and Legacy Documentation * `v1/docs/` - Historical documentation, should remain as-is * `legacy-pre-v1/docs/` - Historical documentation, should remain as-is ## Implementation Checklist * \[ ] Update `docs/reference/real-world-examples.md` examples * \[ ] Update `docs/implementation/agent-metadata-parsing.md` examples * \[ ] Update `docs/extensions/data-uri-compression.md` examples * \[ ] Fix inline examples in `docs/01-agent-metadata-standard.md` * \[ ] Update `docs/implementation/error-codes.md` examples * \[ ] Add terminology clarification in `docs/GLOSSARY.md` * \[ ] Review all prose text for confusing "endpoints" references * \[ ] Add backward compatibility notes where needed ## Testing After Updates 1. **Grep Check**: Verify no remaining `"endpoints": [` in main docs ```bash grep -r '"endpoints"\s*:\s*\[' docs/ --exclude-dir=v1 --exclude-dir=legacy-pre-v1 ``` 2. **Schema Validation**: Ensure updated examples are valid JSON 3. **Link Check**: Verify no broken internal links after updates 4. **Consistency Check**: Confirm all agent metadata examples use `services` ## Additional Notes ### Non-Issues (Clarification) 1. **"Endpoint Types" Section Title**: OK to keep as concept description 2. **Prose References**: "endpoints" in text is generally OK when discussing concept 3. **Individual `endpoint` Property**: OK - this is the field within each service object 4. **Feedback `endpoint` Field**: OK - different context, separate field ### Edge Cases 1. **Architecture Diagrams**: Text labels using "Endpoints" are acceptable 2. **Variable Names in Code**: `endpoints` variable names OK if handling both field names 3. **Historical References**: "endpoints was changed to services" - OK for migration docs *** **Report Generated**: 2026-01-29 **Next Review**: After implementing Phase 1 updates --- --- url: /README.md --- # ERC-8004: Data Profiles and Best Practices **Official best practices from 8004scan** for [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004) offchain data formats and implementation patterns. These specifications are fully maintained and supported by the 8004scan team. ## Documentation **Live Site**: ### Current Version **v2.0** (January 2026) - Latest specification with flexible feedback value system (replaces fixed 0-100 score). #### What's New in v2.0 * **Feedback value system**: `score` (uint8, 0-100) replaced by `value` (int256) + `valueDecimals` (uint8, 0-18) * **Negative feedback**: Support for negative values (disputes, fraud reports) * **Decimal precision**: Up to 18 decimal places for granular ratings * **Flexible scales**: 5-star, 10-point, percentage, or custom rating systems **Upgrading?** See the migration guides: * [v1.x β†’ v2.0 Migration Guide](docs/implementation/migration-v1-to-v2.md) * [pre-v1 β†’ v1.x Migration Guide](docs/implementation/migration-v0-4-to-v1-0.md) ### Core Standards (v2.0) * [Conventions](docs/00-CONVENTIONS.md) - Naming conventions and field types * [Agent Metadata](docs/01-agent-metadata-standard.md) - AgentURI format specification * [Feedback Data](docs/02-feedback-standard.md) - Reputation and feedback records (**v2.0 updates**) * [Validation Data](docs/03-validation-standard.md) - Proofs and attestations * [Attachment Pattern](docs/extensions/04-attachment-pattern-standard.md) - Evidence file schema ### Additional Resources * [Glossary](docs/GLOSSARY.md) - Terms and definitions * [Data URI Compression](docs/extensions/data-uri-compression.md) - Gas optimization extension * [Implementation Guide](docs/implementation/README.md) - Practical guidance * [Version History](VERSION.md) - View all documentation versions ### Previous Versions * **v1.x** (January 2026) - [v1.x documentation](/v1/) * **pre-v1 (legacy)** (December 2025) - [Archived documentation](/legacy-pre-v1/README) ## Getting Started See [QUICKSTART.md](QUICKSTART.md) for local development setup. ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. --- --- url: /v1/README.md --- # ERC-8004: Data Profiles and Best Practices **Official best practices from 8004scan** for [ERC-8004](https://eips.ethereum.org/EIPS/eip-8004) offchain data formats and implementation patterns. These specifications are fully maintained and supported by the 8004scan team. ## Documentation **Live Site**: ### Current Version **v1.1** (January 2026) - Latest specification with simplified feedback flow, string-based tags, and removed authorization requirements. **Upgrading from pre-v1 (legacy)?** See the [Migration Guide: pre-v1 (legacy) β†’ v1.1](docs/implementation/migration-v0-4-to-v1-0.md). ### Core Standards (v1.1) * [Conventions](docs/00-CONVENTIONS.md) - Naming conventions and field types * [Agent Metadata](docs/01-agent-metadata-standard.md) - AgentURI format specification * [Feedback Data](docs/02-feedback-standard.md) - Reputation and feedback records (v1.1 updates) * [Validation Data](docs/03-validation-standard.md) - Proofs and attestations * [Attachment Pattern](docs/extensions/04-attachment-pattern-standard.md) - Evidence file schema ### Additional Resources * [Glossary](docs/GLOSSARY.md) - Terms and definitions * [Data URI Compression](docs/extensions/data-uri-compression.md) - Gas optimization extension * [Implementation Guide](docs/implementation/README.md) - Practical guidance * [Migration Guide](docs/implementation/migration-v0-4-to-v1-0.md) - Upgrade from pre-v1 (legacy) to v1.1 * [Version History](../VERSION.md) - View all documentation versions ### Legacy Versions * **pre-v1 (legacy)** (December 2025) - [Archived documentation](/legacy-pre-v1/README) ## Getting Started See [QUICKSTART.md](../QUICKSTART.md) for local development setup. ## Contributing See [CONTRIBUTING.md](../CONTRIBUTING.md) for guidelines. --- --- url: /docs/implementation/error-codes.md description: Complete runbook-style reference for 8004scan parsing error codes --- # Error Codes Reference This document provides a complete runbook-style reference for all error, warning, and info codes used by 8004scan's parsing system. Each code has a unique anchor for direct linking (e.g., `#EA001`). ## Overview ### Code Format All error codes follow the format ``: | Component | Values | Description | | ------------ | ----------- | --------------------------------------------------------------- | | **Severity** | `E` `W` `I` | Error (critical), Warning (non-critical), Info (recommendation) | | **Object** | `A` `F` | Agent metadata, Feedback data | | **Number** | `001-999` | Sequence number within category | ### Severity Levels | Level | RFC 2119 | Parse Result | User Action | | --------------- | ---------- | ------------------------------ | ----------------------- | | **Error (E)** | MUST fix | Parse fails, agent not indexed | Required to index agent | | **Warning (W)** | SHOULD fix | Parse succeeds with issues | Recommended to fix | | **Info (I)** | MAY fix | Parse succeeds | Optional improvement | ### Linking to Error Codes Each error code can be directly linked: ```text https://best-practices.8004scan.io/docs/implementation/error-codes.html#EA001 https://best-practices.8004scan.io/docs/implementation/error-codes.html#WA070 ``` ### Field Name Migration Note > **Important**: As of January 2026, the official EIP-8004 specification uses `services` instead of `endpoints` for the top-level array field in agent metadata. However: > > * **Error codes referencing `endpoints`**: Still valid - parsers must support both field names for backward compatibility > * **Example code below**: Updated to use `services` (current best practice) > * **Legacy field support**: The `endpoints` field name will continue to work, triggering warning code WA031 > > See [Agent Metadata Standard - Field Migration](../01-agent-metadata-standard.md#field-name-migration-endpoints-to-services) for complete details. *** ## Agent Errors (EA001-EA099) Critical issues that prevent agent metadata parsing. These MUST be fixed for the agent to be indexed. *** ### EA001 #### Empty or invalid URI | Property | Value | | ------------------ | ----------------------------------------- | | Code | `EA001` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | ERC-8004 Reference | `tokenURI()` function (ERC-721 interface) | #### Description The agent's metadata URI is empty, null, or not a valid string. Without a valid URI, there is no metadata to parse. #### Common Causes 1. **Agent registered without metadata**: The `register()` transaction was called but no `agentURI` was set 2. **Subgraph sync issue**: The subgraph returned null for `tokenURI` 3. **Contract misconfiguration**: Custom registry doesn't implement ERC-721 metadata interface correctly #### Diagnostic Steps 1. Check the on-chain `tokenURI(tokenId)` return value: ```solidity // Etherscan > Read Contract > tokenURI tokenURI(123) // Should return a valid URI string ``` 2. Verify the agent was registered: ```solidity ownerOf(tokenId) // Should return a valid address ``` 3. Check subgraph indexing status at the Graph Explorer #### Resolution **Option 1**: Set the agentURI on-chain (if contract supports it): ```solidity registry.setAgentURI(tokenId, "ipfs://Qm..."); ``` **Option 2**: Re-register the agent with a valid URI **Option 3**: If using a custom registry, ensure it implements: ```solidity function tokenURI(uint256 tokenId) external view returns (string memory); ``` #### Example API Response ```json { "parse_status": { "status": "error", "errors": [ { "code": "EA001", "field": "agentURI", "message": "Empty or invalid URI: null" } ] } } ``` *** ### EA002 #### Invalid JSON syntax | Property | Value | | ------------------ | --------------------------------- | | Code | `EA002` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | ERC-8004 Reference | Agent metadata MUST be valid JSON | #### Description The metadata content fetched from the URI is not valid JSON. The parser cannot extract any agent information. #### Common Causes 1. **Malformed JSON**: Syntax errors like missing quotes, trailing commas, or unescaped characters 2. **HTML error page**: Server returned an error page instead of JSON (e.g., 404, 500) 3. **Encoding corruption**: Character encoding issues corrupted the JSON structure 4. **Truncated response**: Network issues caused incomplete data transfer #### Diagnostic Steps 1. Fetch the URI content manually: ```bash curl -s "https://your-agent-uri.com/metadata.json" | jq . ``` 2. Validate JSON syntax: ```bash curl -s "https://..." | python -m json.tool ``` 3. Check Content-Type header: ```bash curl -I "https://..." | grep -i content-type # Expected: application/json ``` #### Resolution 1. **Fix JSON syntax**: Use a JSON linter (jsonlint.com, VSCode) 2. **Check server configuration**: Ensure server returns `Content-Type: application/json` 3. **Escape special characters**: In data URIs, ensure proper escaping 4. **Re-upload to IPFS**: If content was corrupted, re-upload the correct JSON #### Valid JSON Example ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", "description": "Agent description" } ``` #### Common JSON Errors ```json // ❌ Trailing comma (invalid) { "name": "Agent", } // ❌ Single quotes (invalid) { 'name': 'Agent' } // ❌ Unquoted keys (invalid) { name: "Agent" } // ❌ Unescaped newlines in strings (invalid) { "description": "Line 1 Line 2" } ``` *** ### EA003 #### Invalid base64 encoding | Property | Value | | ------------ | -------------------------------- | | Code | `EA003` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Reference | RFC 4648 (Base64 Data Encodings) | #### Description The data URI claims to be base64-encoded (`data:application/json;base64,...`) but contains invalid base64 characters or incorrect padding. #### Common Causes 1. **Incorrect padding**: Base64 strings must be padded with `=` to make length a multiple of 4 2. **Invalid characters**: Non-base64 characters (anything outside A-Z, a-z, 0-9, +, /) 3. **Whitespace**: Line breaks or spaces within the encoded string 4. **URL-safe encoding mismatch**: Using URL-safe base64 (`-_`) with standard decoder #### Diagnostic Steps 1. Extract and test the base64 portion: ```bash # Extract base64 content (after the comma) echo "eyJ0eXBlIjoi..." | base64 -d ``` 2. Check for invalid characters: ```bash echo "eyJ0eXBlIjoi..." | grep -P '[^A-Za-z0-9+/=]' ``` 3. Verify padding: ```python import base64 data = "eyJ0eXBlIjoi..." # Should have length divisible by 4 (with padding) print(len(data) % 4) # Should be 0 ``` #### Resolution 1. **Re-encode correctly**: ```python import base64 import json metadata = {"type": "...", "name": "..."} encoded = base64.b64encode(json.dumps(metadata).encode()).decode() data_uri = f"data:application/json;base64,{encoded}" ``` 2. **Remove whitespace**: Ensure no line breaks in the encoded string 3. **Fix padding**: Add `=` characters if needed: ```python # Fix padding data = data + '=' * (4 - len(data) % 4) if len(data) % 4 else data ``` #### Example ```text # βœ… Valid base64 data URI data:application/json;base64,eyJ0eXBlIjoiaHR0cHM6Ly9laXBzLmV0aGVyZXVtLm9yZy9FSVBzL2VpcC04MDA0I3JlZ2lzdHJhdGlvbi12MSIsIm5hbWUiOiJUZXN0In0= # ❌ Invalid (contains spaces) data:application/json;base64,eyJ0eXBl Ijoi... # ❌ Invalid (missing padding) data:application/json;base64,eyJ0eXBlIjoiaHR0cHM6Ly9laXBz ``` *** ### EA004 #### Decompression security error (possible zip bomb) | Property | Value | | ------------ | ------------------- | | Code | `EA004` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Security | Zip bomb protection | #### Description The compressed data would decompress to more than **100KB**, which is rejected as a security measure against [zip bomb attacks](https://en.wikipedia.org/wiki/Zip_bomb). #### Why This Limit Exists A zip bomb is a malicious compressed file designed to crash or overwhelm systems when decompressed. A small compressed file (few KB) can expand to gigabytes or terabytes of data. #### Common Causes 1. **Actual attack**: Malicious agent attempting to DoS the indexer 2. **Excessive metadata**: Agent metadata far exceeds reasonable size 3. **Embedded large data**: Binary data (images) embedded in JSON #### Resolution 1. **Reduce metadata size**: Agent metadata should typically be 1-10KB 2. **Use external references**: Store large data (images, files) externally: ```json { "image": "ipfs://Qm...", // βœ… External reference "image": "data:image/png;base64,..." // ❌ Embedded (large) } ``` 3. **Use IPFS/HTTP for large metadata**: Instead of data URI compression #### Size Guidelines | Content | Recommended Max Size | | ------------------- | -------------------- | | Total metadata JSON | 50KB | | Compressed data URI | 20KB | | Decompressed limit | 100KB (hard limit) | *** ### EA005 #### Decompression failed | Property | Value | | ------------ | ----------------------------------------------------------------------- | | Code | `EA005` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Reference | [Data URI Compression Extension](../extensions/data-uri-compression.md) | #### Description The compressed data could not be decompressed with the specified algorithm. The `enc=` parameter doesn't match the actual compression format. #### Supported Algorithms | Algorithm | Parameter | Library | | --------- | ---------- | --------- | | Zstandard | `enc=zstd` | zstandard | | Gzip | `enc=gzip` | gzip | | Brotli | `enc=br` | brotli | | LZ4 | `enc=lz4` | lz4 | #### Common Causes 1. **Algorithm mismatch**: URI says `enc=zstd` but data is gzip-compressed 2. **Corrupted data**: Compression stream was truncated or corrupted 3. **Double compression**: Data was compressed twice 4. **Unsupported format**: Using an algorithm not in the supported list #### Diagnostic Steps 1. Check the declared algorithm: ```text data:application/json;enc=zstd;base64,... ^^^^^^^^ ``` 2. Try decompressing with different algorithms: ```python import zstandard, gzip, brotli # Test each algorithm try: zstandard.ZstdDecompressor().decompress(data) except: pass ``` #### Resolution 1. **Verify algorithm**: Ensure `enc=` matches actual compression 2. **Re-compress**: Create a fresh compressed data URI 3. **Test locally**: Verify decompression works before deploying #### Example ```python import zstandard as zstd import base64 import json # Correct compression metadata = {"type": "...", "name": "..."} json_bytes = json.dumps(metadata).encode() cctx = zstd.ZstdCompressor() compressed = cctx.compress(json_bytes) encoded = base64.b64encode(compressed).decode() data_uri = f"data:application/json;enc=zstd;base64,{encoded}" ``` *** ### EA006 #### Unsupported URI format | Property | Value | | ------------------ | ---------------------- | | Code | `EA006` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | ERC-8004 Reference | URI format flexibility | #### Description The URI scheme is not recognized or supported by the parser. #### Supported URI Formats | Format | Example | Notes | | ----------------- | ---------------------------------- | ---------------------------- | | IPFS | `ipfs://Qm...` | Content-addressed, immutable | | Arweave | `ar://...` | Permanent storage | | HTTPS | `https://...` | Standard web URL | | HTTP | `http://...` | ⚠️ Insecure, not recommended | | Data URI (base64) | `data:application/json;base64,...` | Inline, immutable | | Data URI (plain) | `data:application/json,...` | Inline, URL-encoded | #### Common Unsupported Formats ```text # ❌ Unsupported schemes ftp://example.com/metadata.json file:///local/path/metadata.json custom://my-protocol/metadata # ❌ Malformed URIs //example.com/metadata.json (missing scheme) example.com/metadata.json (missing scheme) ``` #### Resolution Convert to a supported format: ```json // βœ… IPFS (recommended for immutability) "ipfs://bafkreiabc123..." // βœ… HTTPS (easy to update) "https://api.myagent.com/metadata.json" // βœ… Data URI (fully onchain) "data:application/json;base64,eyJ0eXBlIjoi..." ``` *** ### EA007 #### IPFS fetch failed | Property | Value | | -------------- | -------------------------------------------------- | | Code | `EA007` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Gateways Tried | ipfs.io, cloudflare-ipfs.com, gateway.pinata.cloud | #### Description Failed to fetch content from all IPFS gateways. The content may not be pinned or available. #### Common Causes 1. **Content not pinned**: The CID exists but no node is serving it 2. **Gateway timeout**: All gateways timed out (>10s each) 3. **Invalid CID**: The CID format is incorrect 4. **Network issues**: Temporary gateway unavailability #### Diagnostic Steps 1. Test CID accessibility: ```bash # Try multiple gateways curl -I "https://ipfs.io/ipfs/YOUR_CID" curl -I "https://cloudflare-ipfs.com/ipfs/YOUR_CID" curl -I "https://gateway.pinata.cloud/ipfs/YOUR_CID" ``` 2. Verify CID format: ```bash # CIDv0 starts with Qm (46 chars) # CIDv1 starts with bafy... or bafk... ``` 3. Check pinning status on your pinning service dashboard #### Resolution 1. **Pin content**: Use a pinning service (Pinata, Infura, web3.storage) ```bash # Using Pinata CLI pinata pin ./metadata.json ``` 2. **Verify pinning**: Check that at least one gateway can serve the content 3. **Consider alternatives**: For critical agents, also host on HTTPS as backup #### Recommended Pinning Services | Service | Free Tier | Notes | | ------------------------------------ | --------- | ----------------- | | [Pinata](https://pinata.cloud) | 1GB | Popular, reliable | | [web3.storage](https://web3.storage) | 5GB | Filecoin-backed | | [Infura](https://infura.io) | Limited | Enterprise-grade | | [Filebase](https://filebase.com) | 5GB | Multi-protocol | *** ### EA008 #### HTTP fetch failed | Property | Value | | ------------ | ---------- | | Code | `EA008` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Timeout | 10 seconds | #### Description Failed to fetch content from the HTTP/HTTPS URL. Server may be down, URL may be invalid, or there may be SSL/TLS issues. #### Common Causes 1. **Server unavailable**: 5xx errors, server down 2. **Resource not found**: 404 error 3. **SSL certificate issues**: Expired or invalid certificate 4. **Timeout**: Server didn't respond within 10 seconds 5. **CORS/Access issues**: Server blocks requests from indexer IP #### Diagnostic Steps 1. Test URL accessibility: ```bash curl -v "https://your-url.com/metadata.json" ``` 2. Check HTTP status: ```bash curl -I "https://your-url.com/metadata.json" # Should return: HTTP/2 200 ``` 3. Verify SSL certificate: ```bash openssl s_client -connect your-url.com:443 -servername your-url.com ``` #### Resolution 1. **Fix server issues**: Ensure server is running and healthy 2. **Verify URL**: Check for typos, ensure path is correct 3. **Fix SSL**: Renew certificate, ensure proper chain 4. **Use CDN**: For better reliability and global availability 5. **Consider IPFS**: For immutable, decentralized hosting #### Recommended Practices | Practice | Benefit | | ------------------ | ------------------------------------- | | Use HTTPS | Security, required for most use cases | | Use CDN | Reliability, speed | | Set proper headers | `Content-Type: application/json` | | Monitor uptime | Detect issues early | *** ### EA009 #### Arweave fetch failed | Property | Value | | ------------ | ----------- | | Code | `EA009` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Gateway | arweave.net | #### Description Failed to fetch content from Arweave gateway. Transaction may not be confirmed or ID may be invalid. #### Common Causes 1. **Transaction not confirmed**: Arweave transactions can take minutes to hours 2. **Invalid transaction ID**: Typo or incorrect format 3. **Gateway issues**: Temporary unavailability #### Diagnostic Steps 1. Check transaction status: ```bash curl "https://arweave.net/tx/YOUR_TX_ID/status" ``` 2. Try fetching content: ```bash curl "https://arweave.net/YOUR_TX_ID" ``` #### Resolution 1. **Wait for confirmation**: New transactions need time to propagate 2. **Verify transaction ID**: Check for typos 3. **Use alternative gateway**: `https://ar-io.net/YOUR_TX_ID` *** ### EA010 #### Non-dict metadata root | Property | Value | | ------------------ | ------------------------------ | | Code | `EA010` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | ERC-8004 Reference | Metadata MUST be a JSON object | #### Description The parsed JSON is not an object (dict). ERC-8004 metadata must be a JSON object with key-value pairs, not an array or primitive value. #### Common Causes 1. **Array instead of object**: `[{"name": "..."}]` instead of `{"name": "..."}` 2. **Primitive value**: Just a string `"hello"` or number `123` 3. **Null value**: The JSON is literally `null` #### Resolution Ensure metadata is a JSON object: ```json // ❌ Invalid: Array [{"name": "Agent", "description": "..."}] // ❌ Invalid: Primitive "Agent metadata" // βœ… Valid: Object { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent", "description": "..." } ``` *** ## Agent Warnings (WA001-WA099) Issues that don't prevent parsing but may affect functionality or interoperability. These SHOULD be fixed. *** ### WA001 #### Missing required field: type | Property | Value | | ------------------- | -------------------- | | Code | `WA001` | | Severity | Warning | | Field | `type` | | Parse Result | Succeeds | | ERC-8004 Compliance | SHOULD (recommended) | #### Description The `type` field is missing from metadata. This field identifies the metadata schema version and helps parsers understand the format. #### ERC-8004 Specification Per the [Agent Metadata Profile](../01-agent-metadata-standard.md#type-recommended): > The `type` field is SHOULD (recommended) for schema identification. Omitting it reduces interoperability with explorers and tools. #### Impact * Explorers may not recognize the metadata format * Schema validation may fail * Future compatibility issues if format changes #### Resolution Add the type field: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", "description": "..." } ``` #### API Response Example ```json { "parse_status": { "status": "warning", "warnings": [ { "code": "WA001", "field": "type", "message": "Missing required field: type" } ] } } ``` *** ### WA002 #### Invalid type field value | Property | Value | | -------------- | --------------------------------------------------------- | | Code | `WA002` | | Severity | Warning | | Field | `type` | | Parse Result | Succeeds | | Expected Value | `https://eips.ethereum.org/EIPS/eip-8004#registration-v1` | #### Description The `type` field exists but doesn't match the expected ERC-8004 schema URL. #### Resolution Use the standard type value: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" } ``` *** ### WA003 #### Missing required field: name | Property | Value | | ------------------- | -------------------- | | Code | `WA003` | | Severity | Warning | | Field | `name` | | Parse Result | Succeeds | | ERC-8004 Compliance | SHOULD (recommended) | #### Description The `name` field is missing. This is a SHOULD field per ERC-8004 and is essential for agent display in explorers. #### Impact * Agent displays as "Unknown" or "Unnamed" in explorers * Poor user experience when browsing agents * Reduced discoverability #### Resolution ```json { "name": "My Agent Name" } ``` #### Best Practices | Practice | Example | | -------------- | -------------------- | | Be descriptive | "DataAnalyst Pro" βœ… | | Avoid generic | "Agent #123" ❌ | | Keep it short | 3-50 characters | *** ### WA004 #### Missing required field: description | Property | Value | | ------------------- | -------------------- | | Code | `WA004` | | Severity | Warning | | Field | `description` | | Parse Result | Succeeds | | ERC-8004 Compliance | SHOULD (recommended) | #### Description The `description` field is missing. Users won't understand what your agent does. #### Resolution ```json { "description": "A specialized AI agent that performs advanced data analysis on blockchain transactions, providing insights and anomaly detection." } ``` *** ### WA005 #### Invalid image URL format | Property | Value | | ------------------- | ----------------------- | | Code | `WA005` | | Severity | Warning | | Field | `image` | | Parse Result | Succeeds | | ERC-8004 Compliance | SHOULD use absolute URI | #### Description The `image` field contains a URL that doesn't start with a valid scheme. #### Valid Schemes | Scheme | Example | | ---------- | ------------------------------------------- | | `https://` | `https://cdn.example.com/logo.png` | | `http://` | `http://example.com/logo.png` (⚠️ insecure) | | `ipfs://` | `ipfs://Qm.../logo.png` | | `ar://` | `ar://tx_id` | | `data:` | `data:image/png;base64,...` | #### Invalid Examples ```json // ❌ Invalid: relative path { "image": "/images/logo.png" } // ❌ Invalid: missing scheme { "image": "www.example.com/logo.png" } // ❌ Invalid: local file { "image": "file:///path/to/logo.png" } ``` #### Resolution Use an absolute URL with a valid scheme: ```json { "image": "https://cdn.example.com/agents/logo.png" } ``` *** ### WA006 #### services field is not an array | Property | Value | | ------------------- | ------------------------ | | Code | `WA006` | | Severity | Warning | | Field | `services` | | Parse Result | Succeeds | | ERC-8004 Compliance | MUST be array if present | #### Description The `services` (or legacy `endpoints`) field exists but is not an array. #### Resolution ```json { "services": [ { "name": "MCP", "endpoint": "https://..." }, { "name": "A2A", "endpoint": "https://..." } ] } ``` *** ### WA007 #### Service object is not valid | Property | Value | | ------------ | ---------- | | Code | `WA007` | | Severity | Warning | | Field | `services` | | Parse Result | Succeeds | #### Description An item in the `services` (or legacy `endpoints`) array is not an object. #### Resolution Each service must be an object: ```json { "services": [ { "name": "MCP", "endpoint": "https://..." } // βœ… Object ] } ``` *** ### WA008 #### Service missing 'endpoint' URL field | Property | Value | | ------------ | ---------- | | Code | `WA008` | | Severity | Warning | | Field | `services` | | Parse Result | Succeeds | #### Description A service object is missing the `endpoint` field (the actual URL). #### Resolution ```json { "name": "MCP", "endpoint": "https://your-agent.com/mcp" // Required } ``` *** ### WA009 #### Service has empty 'endpoint' URL value | Property | Value | | ------------ | ---------- | | Code | `WA009` | | Severity | Warning | | Field | `services` | | Parse Result | Succeeds | #### Description A service has an empty string `""` for the `endpoint` field. #### Impact Clients won't be able to connect to this service. *** ### WA010 #### registrations field is not an array | Property | Value | | ------------ | --------------- | | Code | `WA010` | | Severity | Warning | | Field | `registrations` | | Parse Result | Succeeds | #### Description The `registrations` field exists but is not an array. *** ### WA011 #### Registration object is not valid | Property | Value | | ------------ | --------------- | | Code | `WA011` | | Severity | Warning | | Field | `registrations` | | Parse Result | Succeeds | #### Description An item in the `registrations` array is not an object. *** ### WA012 #### Missing agentRegistry field | Property | Value | | ------------------- | ----------------------------- | | Code | `WA012` | | Severity | Warning | | Field | `registrations` | | Parse Result | Succeeds | | ERC-8004 Compliance | MUST if registrations present | #### Description A registration is missing the required `agentRegistry` field. #### Resolution ```json { "registrations": [ { "agentId": 1, "agentRegistry": "eip155:84532:0x8004a6090Cd10A7288092483047B097295Fb8847" } ] } ``` *** ### WA013 #### Invalid agentRegistry format (should be CAIP-2) | Property | Value | | ------------ | ---------------------------------------------------------------------------------------- | | Code | `WA013` | | Severity | Warning | | Field | `registrations` | | Parse Result | Succeeds | | Reference | [CAIP-2 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) | #### Description The `agentRegistry` field is not in CAIP-2 format. #### Expected Format ```text {namespace}:{chainId}:{contractAddress} ``` #### Examples | Chain | CAIP-2 Format | | ---------------- | --------------------------------------------------------- | | Ethereum Mainnet | `eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847` | | Base Sepolia | `eip155:84532:0x8004a6090Cd10A7288092483047B097295Fb8847` | | Arbitrum One | `eip155:42161:0x8004a6090Cd10A7288092483047B097295Fb8847` | *** ### WA014 #### supportedTrust field is not an array | Property | Value | | ------------ | ---------------- | | Code | `WA014` | | Severity | Warning | | Field | `supportedTrust` | | Parse Result | Succeeds | #### Description The `supportedTrust` field exists but is not an array. *** ### WA015 #### active field is not boolean | Property | Value | | ------------ | -------- | | Code | `WA015` | | Severity | Warning | | Field | `active` | | Parse Result | Succeeds | #### Description The `active` field should be a boolean (`true` or `false`), not a string or number. #### Resolution ```json { "active": true // βœ… Boolean } ``` ```json { "active": "true" // ❌ String } ``` *** ### WA016 #### x402Support field is not boolean | Property | Value | | ------------ | ------------- | | Code | `WA016` | | Severity | Warning | | Field | `x402Support` | | Parse Result | Succeeds | #### Description The `x402Support` field should be a boolean. *** ### WA020 #### Found 'endpoint' (singular), should be 'services' | Property | Value | | ------------ | --------------------- | | Code | `WA020` | | Severity | Warning | | Field | `endpoint` | | Parse Result | Succeeds | | Type | Common typo detection | #### Description The field `endpoint` (singular) was found but the spec uses `services` (plural). #### Resolution Rename `endpoint` to `services` and ensure it's an array: ```json { "services": [...] // βœ… Plural, array } ``` *** ### WA021 #### Found 'registration' (singular), should be 'registrations' | Property | Value | | ------------ | --------------------- | | Code | `WA021` | | Severity | Warning | | Field | `registration` | | Parse Result | Succeeds | | Type | Common typo detection | #### Description The field `registration` (singular) was found but the spec uses `registrations` (plural). *** ### WA030 #### agentWallet must be CAIP-10 format | Property | Value | | ------------ | ------------------------------------------------------------------------------------------ | | Code | `WA030` | | Severity | Warning | | Field | `agentWallet` | | Parse Result | Succeeds | | Reference | [CAIP-10 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) | #### Description The `agentWallet` endpoint is not in CAIP-10 format. #### Expected Format ```text {namespace}:{chainId}:{address} ``` #### Example ```json { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ``` *** ### WA031 #### Using legacy 'endpoints' field (recommend migrating to 'services') | Property | Value | | ------------------- | ---------------------------------------- | | Code | `WA031` | | Severity | Warning | | Field | `services` | | Parse Result | Succeeds | | ERC-8004 Compliance | Legacy field name (still supported) | | Added | Jan 2026 (EIP-8004 field name migration) | #### Description The agent metadata uses the legacy `endpoints` field name instead of the current `services` field name. While both are supported for backward compatibility, `services` is the official field name per EIP-8004 January 2026 update. #### Background In January 2026, the official EIP-8004 specification updated the field name from `endpoints` to `services` to better align with industry terminology. The change only affects the top-level array field name; individual service objects still use the `endpoint` property for their URLs. #### Impact * **Parsing**: No impact - metadata parses successfully * **Compatibility**: Full backward compatibility maintained * **Recommendation**: Migrate to `services` for consistency with current spec #### Resolution Update the field name from `endpoints` to `services`: ```diff { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", - "endpoints": [ + "services": [ { "name": "MCP", "endpoint": "https://mcp.myagent.com", "version": "2025-06-18" } ] } ``` **Important**: Only the array field name changes. Individual service object properties remain unchanged: * βœ… `"endpoint"` property within service objects - **Correct** (unchanged) * βœ… `"services"` top-level array field - **Recommended** (new name) * ⚠️ `"endpoints"` top-level array field - **Legacy** (triggers WA031) #### Migration Timeline | Phase | Date | Status | | -------------------- | -------- | -------------------------------- | | Spec Updated | Jan 2026 | βœ… Complete | | Parser Support | Jan 2026 | βœ… Complete (supports both) | | Deprecation Timeline | TBD | No immediate deprecation planned | > **Note**: There is no immediate deprecation timeline. Both `services` and `endpoints` will be supported indefinitely. This warning is purely informational to encourage migration to the current spec. #### See Also * [Agent Metadata Standard - Field Migration](/docs/01-agent-metadata-standard#field-name-migration-endpoints-to-services) * [Migration Guide (v1.x β†’ v2.0)](/docs/implementation/migration-v1-to-v2) * WA020 - Common typo: using singular `endpoint` instead of plural *** ### WA050 #### base64 URI contains plain JSON (malformed) | Property | Value | | ------------ | ------------------ | | Code | `WA050` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | | Type | Malformed data URI | #### Description The URI declares `;base64` encoding but the content is actually plain JSON. #### Example ```text # ❌ Claims base64 but content is plain JSON data:application/json;base64,{"name":"Agent"} # βœ… Either remove ;base64 data:application/json,{"name":"Agent"} # βœ… Or actually base64-encode data:application/json;base64,eyJuYW1lIjoiQWdlbnQifQ== ``` *** ### WA051 #### Non-standard base64 data URI format | Property | Value | | ------------ | ---------- | | Code | `WA051` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The data URI uses a non-standard format but was successfully parsed. #### Standard Format ```text data:application/json;base64, ``` *** ### WA052 #### Non-standard plain data URI format | Property | Value | | ------------ | ---------- | | Code | `WA052` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The plain data URI uses a non-standard format. #### Standard Format ```text data:application/json, ``` *** ### WA053 #### Plain JSON without URI scheme | Property | Value | | ------------ | ---------- | | Code | `WA053` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The metadata appears to be raw JSON without a URI scheme. #### Resolution Wrap in a data URI: ```text data:application/json,{"name":"Agent",...} ``` *** ### WA054 #### UTF-8 decode error in base64 content | Property | Value | | ------------ | ---------- | | Code | `WA054` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The base64-decoded content is not valid UTF-8. #### Resolution Ensure your JSON is UTF-8 encoded before base64 encoding. *** ### WA055 #### Invalid JSON in base64 content | Property | Value | | ------------ | ---------- | | Code | `WA055` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The base64-decoded content is not valid JSON. *** ### WA056 #### Invalid JSON in plain data URI | Property | Value | | ------------ | ---------- | | Code | `WA056` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The plain data URI content is not valid JSON. *** ### WA070 #### Metadata content does not match on-chain agentHash | Property | Value | | ------------ | --------------------------------------------------------------------------- | | Code | `WA070` | | Severity | Warning | | Field | `agentHash` | | Parse Result | Succeeds | | Reference | [agentHash Extension](../01-agent-metadata-standard.md#agenthash-extension) | #### Description The computed hash of the metadata doesn't match the `agentHash` stored on-chain via the registry's `setMetadata()` function. #### What This Means * The metadata content has changed since the owner set the hash * For HTTP/HTTPS URIs, this could indicate content tampering * Owner may have updated metadata but forgot to update the hash #### 8004scan Extension This uses the `agentHash` on-chain metadata key, which is an 8004scan-recommended extension for HTTP/HTTPS URI integrity verification. ```solidity // Set agentHash on-chain bytes32 hash = keccak256(abi.encodePacked(canonicalJson)); registry.setMetadata(agentId, "agentHash", abi.encode(hash)); ``` #### Resolution 1. **If you updated metadata intentionally**: Update the on-chain hash 2. **If you didn't update**: Investigate potential content modification 3. **Compute new hash**: ```python import json from web3 import Web3 metadata = {...} canonical = json.dumps(metadata, sort_keys=True, separators=(',', ':')) hash = Web3.keccak(text=canonical).hex() ``` #### API Response Example ```json { "parse_status": { "warnings": [ { "code": "WA070", "field": "agentHash", "message": "Metadata content does not match on-chain agentHash", "expected_hash": "0x1234567890ab...", "actual_hash": "0xabcdef123456..." } ] } } ``` *** ### WA071 #### Metadata content has changed since last sync | Property | Value | | ------------ | ------------------------ | | Code | `WA071` | | Severity | Warning | | Field | `_contentIntegrity` | | Parse Result | Succeeds | | Type | Backend change detection | #### Description The metadata content differs from the previously indexed version. This is a backend integrity check, not an ERC-8004 spec field. #### What This Means For HTTP/HTTPS URIs, the content at the URL has changed since the last sync. #### Note This is expected if you intentionally updated your metadata. The warning helps detect unintended changes. *** ### WA080 #### Conflict between on-chain and off-chain metadata | Property | Value | | ------------ | -------------------------------------- | | Code | `WA080` | | Severity | Warning | | Field | Variable (e.g., `agent_wallet`) | | Parse Result | Succeeds (using higher-priority value) | | Type | Metadata conflict | #### Description On-chain metadata (from `MetadataSet` events) conflicts with off-chain metadata (from AgentURI JSON). The values are different, and the on-chain value takes precedence. #### What This Means You have set different values for the same field in: * On-chain: `setMetadata(agentId, "agentWallet", ...)` * Off-chain: AgentURI JSON file #### Common Causes 1. **Metadata not synchronized**: Updated on-chain but not off-chain (or vice versa) 2. **Migration in progress**: Moving from off-chain to on-chain metadata 3. **Accidental override**: Unintentionally set a conflicting value #### Resolution Choose one authoritative source and update the other to match: **Option 1**: Use on-chain metadata (recommended) ```solidity // On-chain metadata takes precedence automatically // Update off-chain JSON to match: { "agentWallet": "eip155:1:0x..." // Match on-chain value } ``` **Option 2**: Use off-chain metadata ```solidity // Clear on-chain metadata registry.setMetadata(agentId, "agentWallet", "0x"); // Empty value ``` #### Note This warning indicates **data inconsistency**, not a critical error. The agent will be indexed successfully using the on-chain value. *** ### WA081 #### Contract state conflicts with on-chain metadata | Property | Value | | ------------ | ------------------------------------- | | Code | `WA081` | | Severity | Warning | | Field | Variable (e.g., `agent_wallet`) | | Parse Result | Succeeds (using contract state value) | | Type | Metadata conflict | #### Description Contract state (from getter functions like `agentWallet()`) conflicts with on-chain metadata (from `MetadataSet` events). The values are different, and the contract state takes precedence. #### What This Means The contract's authoritative state differs from the indexed metadata: * Contract state: `agentWallet()` getter returns value A * On-chain metadata: `setMetadata("agentWallet", value B)` #### Common Causes 1. **Stale metadata**: On-chain metadata not updated after contract state change 2. **Indexing issue**: Subgraph returned outdated contract state 3. **Empty metadata value**: Metadata set to `0x` (empty) but contract has valid value #### Resolution **Most Common**: Empty metadata value (not a real conflict) ```solidity // If you see this with offchain_value: "" // This is likely an empty value issue (fixed in latest parser) // No action needed - contract state is correct ``` **If real conflict exists**: ```solidity // Update on-chain metadata to match contract state bytes memory value = abi.encode(contractState); registry.setMetadata(agentId, "agentWallet", value); ``` #### Note Contract state is the **highest priority source**. This warning helps identify data inconsistencies but doesn't affect agent indexing. #### Related See [Onchain Metadata Handling](onchain-metadata-handling.md) for complete merging algorithm. *** ### WA082 #### ~~agentWallet in on-chain metadata is deprecated~~ (REMOVED) | Property | Value | | -------- | ---------------------- | | Code | `WA082` | | Status | **REMOVED** (Feb 2026) | | Severity | ~~Warning~~ N/A | | Field | `agentWallet` | | Added | Jan 2026 (ERC-8004 v2) | | Removed | Feb 2026 | #### Description > **This error code has been removed and is no longer generated.** The original description was incorrect. After reviewing the ERC-8004 contract implementation: ```solidity // In IdentityRegistryUpgradeable.sol: // setMetadata() explicitly FORBIDS setting agentWallet require(keccak256(bytes(metadataKey)) != RESERVED_AGENT_WALLET_KEY_HASH, "reserved key"); // setAgentWallet() stores the wallet in _metadata (on-chain storage) $._metadata[agentId]["agentWallet"] = abi.encodePacked(newWallet); emit MetadataSet(agentId, "agentWallet", "agentWallet", abi.encodePacked(newWallet)); ``` **Key insight**: The `setAgentWallet()` function itself stores the wallet address in on-chain metadata (`_metadata` mapping) and emits a `MetadataSet` event. Therefore: * `agentWallet` appearing in on-chain metadata (from `MetadataSet` events) is the **correct** behavior * It's impossible to set `agentWallet` via `setMetadata()` - the contract rejects it as a reserved key * The only way to set `agentWallet` on-chain is via `setAgentWallet()` or during `register()` #### Why This Was Removed The parser was incorrectly flagging all agents with on-chain `agentWallet` as using deprecated functionality, when in fact they were using the contract correctly via `setAgentWallet()`. #### See Also * **WA083**: Still valid - flags `agentWallet` in off-chain metadata (agentURI JSON), which IS deprecated *** ### WA083 #### agentWallet in off-chain metadata is deprecated | Property | Value | | ------------ | ---------------------- | | Code | `WA083` | | Severity | Warning | | Field | `agentWallet` | | Parse Result | Succeeds | | Type | Deprecated field usage | | Added | Jan 2026 (ERC-8004 v2) | #### Description The agent has `agentWallet` in the off-chain metadata (agentURI content). In ERC-8004 v2, `agentWallet` should only be set on-chain via the `setAgentWallet()` function. #### What This Means Off-chain `agentWallet` declarations are now treated as **discovery hints only**. The authoritative value is always the contract state set via `setAgentWallet()`. #### Resolution 1. Remove `agentWallet` field from your agent metadata JSON 2. Ensure wallet is set on-chain via `setAgentWallet()` ```diff { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", - "agentWallet": "eip155:1:0x742d35Cc...", "services": [...] } ``` #### Note The off-chain value is ignored for payment purposes. Contract state is authoritative. *** ## Agent Info (IA001-IA099) Recommendations and best practices. These MAY be addressed but are not required. *** ### IA001 #### Missing recommended field: image | Property | Value | | ------------------- | -------------- | | Code | `IA001` | | Severity | Info | | Field | `image` | | Parse Result | Succeeds | | ERC-8004 Compliance | MAY (optional) | #### Description The `image` field is not present. Agents without images display with a default placeholder. #### Resolution ```json { "image": "ipfs://Qm.../logo.png" } ``` *** ### IA002 #### Missing services array (agent won't be reachable) | Property | Value | | ------------ | ---------- | | Code | `IA002` | | Severity | Info | | Field | `services` | | Parse Result | Succeeds | #### Description No `services` array defined. Clients cannot connect to this agent. *** ### IA003 #### Empty services array (agent won't be reachable) | Property | Value | | ------------ | ---------- | | Code | `IA003` | | Severity | Info | | Field | `services` | | Parse Result | Succeeds | #### Description The `services` array exists but is empty. *** ### IA004 #### Missing registrations array (no on-chain link) | Property | Value | | ------------ | --------------- | | Code | `IA004` | | Severity | Info | | Field | `registrations` | | Parse Result | Succeeds | #### Description No `registrations` array. Explorers can't verify the bidirectional link between metadata and on-chain identity. *** ### IA005 #### Empty registrations array (no on-chain link) | Property | Value | | ------------ | --------------- | | Code | `IA005` | | Severity | Info | | Field | `registrations` | | Parse Result | Succeeds | #### Description The `registrations` array exists but is empty. *** ### IA006 #### Missing agentId (expected for first-time deployments) | Property | Value | | ------------ | --------------- | | Code | `IA006` | | Severity | Info | | Field | `registrations` | | Parse Result | Succeeds | #### Description A registration is missing `agentId`. This is normal for first-time deployments since you don't know the tokenId before registration. #### Resolution Update metadata after registration to include the assigned `agentId`. *** ### IA007 #### agentId is null (expected for first-time deployments) | Property | Value | | ------------ | --------------- | | Code | `IA007` | | Severity | Info | | Field | `registrations` | | Parse Result | Succeeds | #### Description The `agentId` is explicitly set to `null`. Same as IA006. *** ### IA008 #### Empty supportedTrust array (discovery-only mode) | Property | Value | | ------------ | ---------------- | | Code | `IA008` | | Severity | Info | | Field | `supportedTrust` | | Parse Result | Succeeds | #### Description Agent has no trust models configured. Operating in discovery-only mode. *** ### IA009 #### Unknown trust model (may be future extension) | Property | Value | | ------------ | ---------------- | | Code | `IA009` | | Severity | Info | | Field | `supportedTrust` | | Parse Result | Succeeds | #### Description A trust model in the array is not in the known set. #### Known Models * `reputation` * `crypto-economic` * `tee-attestation` * `social-graph` *** ### IA010 #### Found 'supportedTrusts' (plural), spec uses 'supportedTrust' | Property | Value | | ------------ | ----------------- | | Code | `IA010` | | Severity | Info | | Field | `supportedTrusts` | | Parse Result | Succeeds | #### Description Common typo. The spec uses singular `supportedTrust`. *** ### IA020 #### MCP service missing version field | Property | Value | | ------------------- | --------------------------- | | Code | `IA020` | | Severity | Info | | Field | `MCP` | | Parse Result | Succeeds | | ERC-8004 Compliance | Version is SHOULD, not MUST | #### Description MCP service doesn't specify a version. #### Recommendation ```json { "name": "MCP", "endpoint": "https://...", "version": "2025-06-18" } ``` *** ### IA021 #### MCP version is not in date format (YYYY-MM-DD) | Property | Value | | ------------ | ------------------------------------------------------------------ | | Code | `IA021` | | Severity | Info | | Field | `MCP` | | Parse Result | Succeeds | | Valid Format | `YYYY-MM-DD` (e.g., `2025-06-18`, `2025-11-25`, `2026-01-29`) | | Reference | [MCP Specification](https://modelcontextprotocol.io/specification) | #### Description MCP uses date-based versioning. The version field should be in `YYYY-MM-DD` format representing the protocol specification date. Any valid date from 2024 onwards is accepted. **Valid examples:** * `"2025-06-18"` - June 2025 spec * `"2025-11-25"` - November 2025 spec (latest as of writing) * `"2026-01-29"` - Future spec date **Invalid examples:** * `"1.0.0"` - Not a date format * `"2025/06/18"` - Wrong separator * `"25-06-18"` - Year not in 4-digit format *** ### IA022 #### A2A service missing version field | Property | Value | | ------------ | -------- | | Code | `IA022` | | Severity | Info | | Field | `A2A` | | Parse Result | Succeeds | #### Description A2A service doesn't specify a version. *** ### IA023 #### A2A version is not in semver format | Property | Value | | ------------ | ---------------------------------------- | | Code | `IA023` | | Severity | Info | | Field | `A2A` | | Parse Result | Succeeds | | Valid Format | Semver: `X.Y.Z` or `X.Y` (e.g., `0.3.0`) | #### Description A2A uses semantic versioning. The version field should be in semver format (`major.minor.patch` or `major.minor`). **Valid examples:** * `"0.3.0"` - Current A2A spec version * `"1.0.0"` - Future major version * `"0.4"` - Without patch number **Invalid examples:** * `"v0.3.0"` - Avoid 'v' prefix for A2A * `"latest"` - Not a version number *** ### IA024 #### A2A service should use .well-known/agent-card.json path | Property | Value | | ------------ | -------- | | Code | `IA024` | | Severity | Info | | Field | `A2A` | | Parse Result | Succeeds | #### Description A2A service doesn't use the recommended well-known path. #### Recommendation ```text https://your-agent.com/.well-known/agent-card.json ``` *** ### IA025 #### OASF service has neither skills nor domains | Property | Value | | ------------ | -------- | | Code | `IA025` | | Severity | Info | | Field | `OASF` | | Parse Result | Succeeds | #### Description OASF service exists but has no skills or domains defined. *** ### IA026 #### OASF version is not in semver format | Property | Value | | ------------ | ------------------------------------------------------------ | | Code | `IA026` | | Severity | Info | | Field | `OASF` | | Parse Result | Succeeds | | Valid Format | Semver with optional 'v' prefix: `X.Y.Z`, `vX.Y.Z`, or `X.Y` | | Reference | [OASF Releases](https://github.com/agntcy/oasf/releases) | #### Description OASF uses semantic versioning. The version field should be in semver format, with an optional 'v' prefix. Multiple major version lines are supported (0.7.x, 0.8.x, etc.). **Valid examples:** * `"0.8.0"` - Without 'v' prefix * `"v0.8.0"` - With 'v' prefix * `"0.8.3"` - Latest 0.8.x version * `"0.7.4"` - 0.7.x version line * `"1.0.0"` - Future major version **Invalid examples:** * `"latest"` - Not a version number * `"0.8"` - Missing patch number (while technically valid semver, full version preferred) *** ### IA027 #### Unknown OASF skill category | Property | Value | | ------------ | ------------------------------------------------ | | Code | `IA027` | | Severity | Info | | Field | `OASF` | | Parse Result | Succeeds | | Reference | [OASF Taxonomy](https://github.com/agntcy/oasf/) | #### Description A skill in the OASF service is not in the known taxonomy. *** ### IA028 #### Unknown OASF domain category | Property | Value | | ------------ | -------- | | Code | `IA028` | | Severity | Info | | Field | `OASF` | | Parse Result | Succeeds | #### Description A domain in the OASF service is not in the known taxonomy. *** ### IA040 #### HTTP/HTTPS URI is not content-addressed | Property | Value | | ------------ | ---------- | | Code | `IA040` | | Severity | Info | | Field | `agentURI` | | Parse Result | Succeeds | #### Description Agent uses a mutable HTTP/HTTPS URL for metadata. Content at HTTP URLs can change without notice. #### Why This Matters * No built-in integrity verification * Content can change between fetches * Harder to audit historical state #### Recommendations 1. **Use IPFS**: `ipfs://Qm...` for immutable content 2. **Set agentHash**: On-chain integrity verification 3. **Use data URIs**: For small metadata (`data:application/json,...`) *** ### IA041 #### URL-decoded plain data URI | Property | Value | | ------------ | ---------- | | Code | `IA041` | | Severity | Info | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The data URI content was URL-encoded and had to be decoded. *** ### IA050 #### Field value from contract state (on-chain metadata empty or not set) | Property | Value | | ------------ | -------- | | Code | `IA050` | | Severity | Info | | Field | Dynamic | | Parse Result | Succeeds | #### Description A metadata field is using the value from contract state because the on-chain metadata for this field is empty or not set. This is **not an error** - ERC-8004 contracts don't provide a `deleteMetadata()` function, so setting a field to empty (`0x` or `""`) is the standard way to indicate "not set". When this happens, the contract state value (if available) is used as the fallback. #### Common Scenarios **Scenario 1: Empty `agentWallet` on-chain metadata** * On-chain metadata: `{"key": "agentWallet", "value": "0x"}` * Contract state: `agentWallet = 0x461a...` (from `setAgentWallet()`) * Result: Uses contract state value * Info: `IA050` on field `agent_wallet` **Scenario 2: `agentWallet` not set in on-chain metadata** * On-chain metadata: No `agentWallet` entry * Contract state: `agentWallet = 0x461a...` * Result: Uses contract state value * Info: `IA050` on field `agent_wallet` #### Why This Happens ERC-8004 metadata hierarchy (highest to lowest priority): 1. **Contract state** (hardcoded fields: `agentWallet`, `owner`) 2. **On-chain metadata** (via `setMetadata()`) 3. **Off-chain metadata** (from `agentURI`) When on-chain metadata is empty, contract state takes precedence without conflict. #### Resolution **No action needed** - this is informational only. The field value is correct. If you want to explicitly set the value in on-chain metadata: ```solidity // Set agentWallet in on-chain metadata (optional) registry.setMetadata(tokenId, "agentWallet", "0x461a76074596f080dfba414532ab51280611b8e6"); ``` However, `agentWallet` cannot be set via `setMetadata()` - it's a reserved field that must be set via `setAgentWallet()` with signature verification. #### See Also * **WA081**: Contract state conflicts with on-chain metadata (when both are non-empty) * **Metadata Handling Guide**: `/docs/implementation/onchain-metadata-handling.md` *** ## Feedback Errors (EF001-EF099) Critical issues in feedback parsing. *** ### EF001 #### Invalid timestamp format | Property | Value | | ------------ | ----------------- | | Code | `EF001` | | Severity | Error | | Field | `timestamp` | | Parse Result | Uses current time | #### Description The timestamp field cannot be parsed as a Unix timestamp. #### Expected Format Unix timestamp in seconds (integer). *** ### EF002 #### Failed to fetch offchain data | Property | Value | | ------------ | --------------- | | Code | `EF002` | | Severity | Error | | Field | `feedbackURI` | | Parse Result | Partial success | #### Description Could not fetch the feedback's offchain data from `feedbackURI`. *** ## Feedback Warnings (WF001-WF099) *** ### WF001 #### Invalid timestamp (using current time) | Property | Value | | ------------ | ----------- | | Code | `WF001` | | Severity | Warning | | Field | `timestamp` | | Parse Result | Succeeds | #### Description Revocation timestamp invalid. Using current time as fallback. *** ### WF002 #### Feedback hash mismatch | Property | Value | | ------------ | -------------- | | Code | `WF002` | | Severity | Warning | | Field | `feedbackHash` | | Parse Result | Succeeds | #### Description The computed hash of offchain data doesn't match `feedbackHash` on-chain. *** ### WF003 #### Tag stored as hash (original not available) | Property | Value | | ------------ | -------- | | Code | `WF003` | | Severity | Warning | | Field | `tag` | | Parse Result | Succeeds | #### Description The indexed `tag1` is stored as a keccak256 hash and the original value wasn't in offchain data. #### Why This Happens Indexed string parameters in Solidity events are stored as hashes. The original value should be provided in `feedbackURI` data. *** ## Related Documentation * [Agent Metadata Standard](../01-agent-metadata-standard.md) - Full schema specification * [Agent Metadata Parsing](./agent-metadata-parsing.md) - Parsing implementation guide * [Feedback Best Practices](./feedback-best-practices.md) - Feedback handling * [Data URI Compression](../extensions/data-uri-compression.md) - Compression extension *** **Last Updated**: 2026-02-06 --- --- url: /v1/docs/implementation/error-codes.md description: Complete runbook-style reference for 8004scan parsing error codes --- # Error Codes Reference This document provides a complete runbook-style reference for all error, warning, and info codes used by 8004scan's parsing system. Each code has a unique anchor for direct linking (e.g., `#EA001`). ## Overview ### Code Format All error codes follow the format ``: | Component | Values | Description | | ------------ | ----------- | --------------------------------------------------------------- | | **Severity** | `E` `W` `I` | Error (critical), Warning (non-critical), Info (recommendation) | | **Object** | `A` `F` | Agent metadata, Feedback data | | **Number** | `001-999` | Sequence number within category | ### Severity Levels | Level | RFC 2119 | Parse Result | User Action | | --------------- | ---------- | ------------------------------ | ----------------------- | | **Error (E)** | MUST fix | Parse fails, agent not indexed | Required to index agent | | **Warning (W)** | SHOULD fix | Parse succeeds with issues | Recommended to fix | | **Info (I)** | MAY fix | Parse succeeds | Optional improvement | ### Linking to Error Codes Each error code can be directly linked: ```text https://best-practices.8004scan.io/docs/implementation/error-codes.html#EA001 https://best-practices.8004scan.io/docs/implementation/error-codes.html#WA070 ``` *** ## Agent Errors (EA001-EA099) Critical issues that prevent agent metadata parsing. These MUST be fixed for the agent to be indexed. *** ### EA001 #### Empty or invalid URI | Property | Value | | ------------------ | ----------------------------------------- | | Code | `EA001` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | ERC-8004 Reference | `tokenURI()` function (ERC-721 interface) | #### Description The agent's metadata URI is empty, null, or not a valid string. Without a valid URI, there is no metadata to parse. #### Common Causes 1. **Agent registered without metadata**: The `register()` transaction was called but no `agentURI` was set 2. **Subgraph sync issue**: The subgraph returned null for `tokenURI` 3. **Contract misconfiguration**: Custom registry doesn't implement ERC-721 metadata interface correctly #### Diagnostic Steps 1. Check the on-chain `tokenURI(tokenId)` return value: ```solidity // Etherscan > Read Contract > tokenURI tokenURI(123) // Should return a valid URI string ``` 2. Verify the agent was registered: ```solidity ownerOf(tokenId) // Should return a valid address ``` 3. Check subgraph indexing status at the Graph Explorer #### Resolution **Option 1**: Set the agentURI on-chain (if contract supports it): ```solidity registry.setAgentURI(tokenId, "ipfs://Qm..."); ``` **Option 2**: Re-register the agent with a valid URI **Option 3**: If using a custom registry, ensure it implements: ```solidity function tokenURI(uint256 tokenId) external view returns (string memory); ``` #### Example API Response ```json { "parse_status": { "status": "error", "errors": [ { "code": "EA001", "field": "agentURI", "message": "Empty or invalid URI: null" } ] } } ``` *** ### EA002 #### Invalid JSON syntax | Property | Value | | ------------------ | --------------------------------- | | Code | `EA002` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | ERC-8004 Reference | Agent metadata MUST be valid JSON | #### Description The metadata content fetched from the URI is not valid JSON. The parser cannot extract any agent information. #### Common Causes 1. **Malformed JSON**: Syntax errors like missing quotes, trailing commas, or unescaped characters 2. **HTML error page**: Server returned an error page instead of JSON (e.g., 404, 500) 3. **Encoding corruption**: Character encoding issues corrupted the JSON structure 4. **Truncated response**: Network issues caused incomplete data transfer #### Diagnostic Steps 1. Fetch the URI content manually: ```bash curl -s "https://your-agent-uri.com/metadata.json" | jq . ``` 2. Validate JSON syntax: ```bash curl -s "https://..." | python -m json.tool ``` 3. Check Content-Type header: ```bash curl -I "https://..." | grep -i content-type # Expected: application/json ``` #### Resolution 1. **Fix JSON syntax**: Use a JSON linter (jsonlint.com, VSCode) 2. **Check server configuration**: Ensure server returns `Content-Type: application/json` 3. **Escape special characters**: In data URIs, ensure proper escaping 4. **Re-upload to IPFS**: If content was corrupted, re-upload the correct JSON #### Valid JSON Example ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", "description": "Agent description" } ``` #### Common JSON Errors ```json // ❌ Trailing comma (invalid) { "name": "Agent", } // ❌ Single quotes (invalid) { 'name': 'Agent' } // ❌ Unquoted keys (invalid) { name: "Agent" } // ❌ Unescaped newlines in strings (invalid) { "description": "Line 1 Line 2" } ``` *** ### EA003 #### Invalid base64 encoding | Property | Value | | ------------ | -------------------------------- | | Code | `EA003` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Reference | RFC 4648 (Base64 Data Encodings) | #### Description The data URI claims to be base64-encoded (`data:application/json;base64,...`) but contains invalid base64 characters or incorrect padding. #### Common Causes 1. **Incorrect padding**: Base64 strings must be padded with `=` to make length a multiple of 4 2. **Invalid characters**: Non-base64 characters (anything outside A-Z, a-z, 0-9, +, /) 3. **Whitespace**: Line breaks or spaces within the encoded string 4. **URL-safe encoding mismatch**: Using URL-safe base64 (`-_`) with standard decoder #### Diagnostic Steps 1. Extract and test the base64 portion: ```bash # Extract base64 content (after the comma) echo "eyJ0eXBlIjoi..." | base64 -d ``` 2. Check for invalid characters: ```bash echo "eyJ0eXBlIjoi..." | grep -P '[^A-Za-z0-9+/=]' ``` 3. Verify padding: ```python import base64 data = "eyJ0eXBlIjoi..." # Should have length divisible by 4 (with padding) print(len(data) % 4) # Should be 0 ``` #### Resolution 1. **Re-encode correctly**: ```python import base64 import json metadata = {"type": "...", "name": "..."} encoded = base64.b64encode(json.dumps(metadata).encode()).decode() data_uri = f"data:application/json;base64,{encoded}" ``` 2. **Remove whitespace**: Ensure no line breaks in the encoded string 3. **Fix padding**: Add `=` characters if needed: ```python # Fix padding data = data + '=' * (4 - len(data) % 4) if len(data) % 4 else data ``` #### Example ```text # βœ… Valid base64 data URI data:application/json;base64,eyJ0eXBlIjoiaHR0cHM6Ly9laXBzLmV0aGVyZXVtLm9yZy9FSVBzL2VpcC04MDA0I3JlZ2lzdHJhdGlvbi12MSIsIm5hbWUiOiJUZXN0In0= # ❌ Invalid (contains spaces) data:application/json;base64,eyJ0eXBl Ijoi... # ❌ Invalid (missing padding) data:application/json;base64,eyJ0eXBlIjoiaHR0cHM6Ly9laXBz ``` *** ### EA004 #### Decompression security error (possible zip bomb) | Property | Value | | ------------ | ------------------- | | Code | `EA004` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Security | Zip bomb protection | #### Description The compressed data would decompress to more than **100KB**, which is rejected as a security measure against [zip bomb attacks](https://en.wikipedia.org/wiki/Zip_bomb). #### Why This Limit Exists A zip bomb is a malicious compressed file designed to crash or overwhelm systems when decompressed. A small compressed file (few KB) can expand to gigabytes or terabytes of data. #### Common Causes 1. **Actual attack**: Malicious agent attempting to DoS the indexer 2. **Excessive metadata**: Agent metadata far exceeds reasonable size 3. **Embedded large data**: Binary data (images) embedded in JSON #### Resolution 1. **Reduce metadata size**: Agent metadata should typically be 1-10KB 2. **Use external references**: Store large data (images, files) externally: ```json { "image": "ipfs://Qm...", // βœ… External reference "image": "data:image/png;base64,..." // ❌ Embedded (large) } ``` 3. **Use IPFS/HTTP for large metadata**: Instead of data URI compression #### Size Guidelines | Content | Recommended Max Size | | ------------------- | -------------------- | | Total metadata JSON | 50KB | | Compressed data URI | 20KB | | Decompressed limit | 100KB (hard limit) | *** ### EA005 #### Decompression failed | Property | Value | | ------------ | ----------------------------------------------------------------------- | | Code | `EA005` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Reference | [Data URI Compression Extension](../extensions/data-uri-compression.md) | #### Description The compressed data could not be decompressed with the specified algorithm. The `enc=` parameter doesn't match the actual compression format. #### Supported Algorithms | Algorithm | Parameter | Library | | --------- | ---------- | --------- | | Zstandard | `enc=zstd` | zstandard | | Gzip | `enc=gzip` | gzip | | Brotli | `enc=br` | brotli | | LZ4 | `enc=lz4` | lz4 | #### Common Causes 1. **Algorithm mismatch**: URI says `enc=zstd` but data is gzip-compressed 2. **Corrupted data**: Compression stream was truncated or corrupted 3. **Double compression**: Data was compressed twice 4. **Unsupported format**: Using an algorithm not in the supported list #### Diagnostic Steps 1. Check the declared algorithm: ```text data:application/json;enc=zstd;base64,... ^^^^^^^^ ``` 2. Try decompressing with different algorithms: ```python import zstandard, gzip, brotli # Test each algorithm try: zstandard.ZstdDecompressor().decompress(data) except: pass ``` #### Resolution 1. **Verify algorithm**: Ensure `enc=` matches actual compression 2. **Re-compress**: Create a fresh compressed data URI 3. **Test locally**: Verify decompression works before deploying #### Example ```python import zstandard as zstd import base64 import json # Correct compression metadata = {"type": "...", "name": "..."} json_bytes = json.dumps(metadata).encode() cctx = zstd.ZstdCompressor() compressed = cctx.compress(json_bytes) encoded = base64.b64encode(compressed).decode() data_uri = f"data:application/json;enc=zstd;base64,{encoded}" ``` *** ### EA006 #### Unsupported URI format | Property | Value | | ------------------ | ---------------------- | | Code | `EA006` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | ERC-8004 Reference | URI format flexibility | #### Description The URI scheme is not recognized or supported by the parser. #### Supported URI Formats | Format | Example | Notes | | ----------------- | ---------------------------------- | ---------------------------- | | IPFS | `ipfs://Qm...` | Content-addressed, immutable | | Arweave | `ar://...` | Permanent storage | | HTTPS | `https://...` | Standard web URL | | HTTP | `http://...` | ⚠️ Insecure, not recommended | | Data URI (base64) | `data:application/json;base64,...` | Inline, immutable | | Data URI (plain) | `data:application/json,...` | Inline, URL-encoded | #### Common Unsupported Formats ```text # ❌ Unsupported schemes ftp://example.com/metadata.json file:///local/path/metadata.json custom://my-protocol/metadata # ❌ Malformed URIs //example.com/metadata.json (missing scheme) example.com/metadata.json (missing scheme) ``` #### Resolution Convert to a supported format: ```json // βœ… IPFS (recommended for immutability) "ipfs://bafkreiabc123..." // βœ… HTTPS (easy to update) "https://api.myagent.com/metadata.json" // βœ… Data URI (fully onchain) "data:application/json;base64,eyJ0eXBlIjoi..." ``` *** ### EA007 #### IPFS fetch failed | Property | Value | | -------------- | -------------------------------------------------- | | Code | `EA007` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Gateways Tried | ipfs.io, cloudflare-ipfs.com, gateway.pinata.cloud | #### Description Failed to fetch content from all IPFS gateways. The content may not be pinned or available. #### Common Causes 1. **Content not pinned**: The CID exists but no node is serving it 2. **Gateway timeout**: All gateways timed out (>10s each) 3. **Invalid CID**: The CID format is incorrect 4. **Network issues**: Temporary gateway unavailability #### Diagnostic Steps 1. Test CID accessibility: ```bash # Try multiple gateways curl -I "https://ipfs.io/ipfs/YOUR_CID" curl -I "https://cloudflare-ipfs.com/ipfs/YOUR_CID" curl -I "https://gateway.pinata.cloud/ipfs/YOUR_CID" ``` 2. Verify CID format: ```bash # CIDv0 starts with Qm (46 chars) # CIDv1 starts with bafy... or bafk... ``` 3. Check pinning status on your pinning service dashboard #### Resolution 1. **Pin content**: Use a pinning service (Pinata, Infura, web3.storage) ```bash # Using Pinata CLI pinata pin ./metadata.json ``` 2. **Verify pinning**: Check that at least one gateway can serve the content 3. **Consider alternatives**: For critical agents, also host on HTTPS as backup #### Recommended Pinning Services | Service | Free Tier | Notes | | ------------------------------------ | --------- | ----------------- | | [Pinata](https://pinata.cloud) | 1GB | Popular, reliable | | [web3.storage](https://web3.storage) | 5GB | Filecoin-backed | | [Infura](https://infura.io) | Limited | Enterprise-grade | | [Filebase](https://filebase.com) | 5GB | Multi-protocol | *** ### EA008 #### HTTP fetch failed | Property | Value | | ------------ | ---------- | | Code | `EA008` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Timeout | 10 seconds | #### Description Failed to fetch content from the HTTP/HTTPS URL. Server may be down, URL may be invalid, or there may be SSL/TLS issues. #### Common Causes 1. **Server unavailable**: 5xx errors, server down 2. **Resource not found**: 404 error 3. **SSL certificate issues**: Expired or invalid certificate 4. **Timeout**: Server didn't respond within 10 seconds 5. **CORS/Access issues**: Server blocks requests from indexer IP #### Diagnostic Steps 1. Test URL accessibility: ```bash curl -v "https://your-url.com/metadata.json" ``` 2. Check HTTP status: ```bash curl -I "https://your-url.com/metadata.json" # Should return: HTTP/2 200 ``` 3. Verify SSL certificate: ```bash openssl s_client -connect your-url.com:443 -servername your-url.com ``` #### Resolution 1. **Fix server issues**: Ensure server is running and healthy 2. **Verify URL**: Check for typos, ensure path is correct 3. **Fix SSL**: Renew certificate, ensure proper chain 4. **Use CDN**: For better reliability and global availability 5. **Consider IPFS**: For immutable, decentralized hosting #### Recommended Practices | Practice | Benefit | | ------------------ | ------------------------------------- | | Use HTTPS | Security, required for most use cases | | Use CDN | Reliability, speed | | Set proper headers | `Content-Type: application/json` | | Monitor uptime | Detect issues early | *** ### EA009 #### Arweave fetch failed | Property | Value | | ------------ | ----------- | | Code | `EA009` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | Gateway | arweave.net | #### Description Failed to fetch content from Arweave gateway. Transaction may not be confirmed or ID may be invalid. #### Common Causes 1. **Transaction not confirmed**: Arweave transactions can take minutes to hours 2. **Invalid transaction ID**: Typo or incorrect format 3. **Gateway issues**: Temporary unavailability #### Diagnostic Steps 1. Check transaction status: ```bash curl "https://arweave.net/tx/YOUR_TX_ID/status" ``` 2. Try fetching content: ```bash curl "https://arweave.net/YOUR_TX_ID" ``` #### Resolution 1. **Wait for confirmation**: New transactions need time to propagate 2. **Verify transaction ID**: Check for typos 3. **Use alternative gateway**: `https://ar-io.net/YOUR_TX_ID` *** ### EA010 #### Non-dict metadata root | Property | Value | | ------------------ | ------------------------------ | | Code | `EA010` | | Severity | Error | | Field | `agentURI` | | Parse Result | **Fails** | | ERC-8004 Reference | Metadata MUST be a JSON object | #### Description The parsed JSON is not an object (dict). ERC-8004 metadata must be a JSON object with key-value pairs, not an array or primitive value. #### Common Causes 1. **Array instead of object**: `[{"name": "..."}]` instead of `{"name": "..."}` 2. **Primitive value**: Just a string `"hello"` or number `123` 3. **Null value**: The JSON is literally `null` #### Resolution Ensure metadata is a JSON object: ```json // ❌ Invalid: Array [{"name": "Agent", "description": "..."}] // ❌ Invalid: Primitive "Agent metadata" // βœ… Valid: Object { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent", "description": "..." } ``` *** ## Agent Warnings (WA001-WA099) Issues that don't prevent parsing but may affect functionality or interoperability. These SHOULD be fixed. *** ### WA001 #### Missing required field: type | Property | Value | | ------------------- | -------------------- | | Code | `WA001` | | Severity | Warning | | Field | `type` | | Parse Result | Succeeds | | ERC-8004 Compliance | SHOULD (recommended) | #### Description The `type` field is missing from metadata. This field identifies the metadata schema version and helps parsers understand the format. #### ERC-8004 Specification Per the [Agent Metadata Profile](../01-agent-metadata-standard.md#type-recommended): > The `type` field is SHOULD (recommended) for schema identification. Omitting it reduces interoperability with explorers and tools. #### Impact * Explorers may not recognize the metadata format * Schema validation may fail * Future compatibility issues if format changes #### Resolution Add the type field: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "My Agent", "description": "..." } ``` #### API Response Example ```json { "parse_status": { "status": "warning", "warnings": [ { "code": "WA001", "field": "type", "message": "Missing required field: type" } ] } } ``` *** ### WA002 #### Invalid type field value | Property | Value | | -------------- | --------------------------------------------------------- | | Code | `WA002` | | Severity | Warning | | Field | `type` | | Parse Result | Succeeds | | Expected Value | `https://eips.ethereum.org/EIPS/eip-8004#registration-v1` | #### Description The `type` field exists but doesn't match the expected ERC-8004 schema URL. #### Resolution Use the standard type value: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1" } ``` *** ### WA003 #### Missing required field: name | Property | Value | | ------------------- | -------------------- | | Code | `WA003` | | Severity | Warning | | Field | `name` | | Parse Result | Succeeds | | ERC-8004 Compliance | SHOULD (recommended) | #### Description The `name` field is missing. This is a SHOULD field per ERC-8004 and is essential for agent display in explorers. #### Impact * Agent displays as "Unknown" or "Unnamed" in explorers * Poor user experience when browsing agents * Reduced discoverability #### Resolution ```json { "name": "My Agent Name" } ``` #### Best Practices | Practice | Example | | -------------- | -------------------- | | Be descriptive | "DataAnalyst Pro" βœ… | | Avoid generic | "Agent #123" ❌ | | Keep it short | 3-50 characters | *** ### WA004 #### Missing required field: description | Property | Value | | ------------------- | -------------------- | | Code | `WA004` | | Severity | Warning | | Field | `description` | | Parse Result | Succeeds | | ERC-8004 Compliance | SHOULD (recommended) | #### Description The `description` field is missing. Users won't understand what your agent does. #### Resolution ```json { "description": "A specialized AI agent that performs advanced data analysis on blockchain transactions, providing insights and anomaly detection." } ``` *** ### WA005 #### Invalid image URL format | Property | Value | | ------------------- | ----------------------- | | Code | `WA005` | | Severity | Warning | | Field | `image` | | Parse Result | Succeeds | | ERC-8004 Compliance | SHOULD use absolute URI | #### Description The `image` field contains a URL that doesn't start with a valid scheme. #### Valid Schemes | Scheme | Example | | ---------- | ------------------------------------------- | | `https://` | `https://cdn.example.com/logo.png` | | `http://` | `http://example.com/logo.png` (⚠️ insecure) | | `ipfs://` | `ipfs://Qm.../logo.png` | | `ar://` | `ar://tx_id` | | `data:` | `data:image/png;base64,...` | #### Invalid Examples ```json // ❌ Invalid: relative path { "image": "/images/logo.png" } // ❌ Invalid: missing scheme { "image": "www.example.com/logo.png" } // ❌ Invalid: local file { "image": "file:///path/to/logo.png" } ``` #### Resolution Use an absolute URL with a valid scheme: ```json { "image": "https://cdn.example.com/agents/logo.png" } ``` *** ### WA006 #### endpoints field is not an array | Property | Value | | ------------------- | ------------------------ | | Code | `WA006` | | Severity | Warning | | Field | `endpoints` | | Parse Result | Succeeds | | ERC-8004 Compliance | MUST be array if present | #### Description The `endpoints` field exists but is not an array. #### Resolution ```json { "endpoints": [ { "name": "MCP", "endpoint": "https://..." }, { "name": "A2A", "endpoint": "https://..." } ] } ``` *** ### WA007 #### Endpoint object is not valid | Property | Value | | ------------ | ----------- | | Code | `WA007` | | Severity | Warning | | Field | `endpoints` | | Parse Result | Succeeds | #### Description An item in the `endpoints` array is not an object. #### Resolution Each endpoint must be an object: ```json { "endpoints": [ { "name": "MCP", "endpoint": "https://..." } // βœ… Object ] } ``` *** ### WA008 #### Missing endpoint URL field | Property | Value | | ------------ | ----------- | | Code | `WA008` | | Severity | Warning | | Field | `endpoints` | | Parse Result | Succeeds | #### Description An endpoint object is missing the `endpoint` field (the actual URL). #### Resolution ```json { "name": "MCP", "endpoint": "https://your-agent.com/mcp" // Required } ``` *** ### WA009 #### Empty endpoint URL value | Property | Value | | ------------ | ----------- | | Code | `WA009` | | Severity | Warning | | Field | `endpoints` | | Parse Result | Succeeds | #### Description An endpoint has an empty string `""` for the `endpoint` field. #### Impact Clients won't be able to connect to this endpoint. *** ### WA010 #### registrations field is not an array | Property | Value | | ------------ | --------------- | | Code | `WA010` | | Severity | Warning | | Field | `registrations` | | Parse Result | Succeeds | #### Description The `registrations` field exists but is not an array. *** ### WA011 #### Registration object is not valid | Property | Value | | ------------ | --------------- | | Code | `WA011` | | Severity | Warning | | Field | `registrations` | | Parse Result | Succeeds | #### Description An item in the `registrations` array is not an object. *** ### WA012 #### Missing agentRegistry field | Property | Value | | ------------------- | ----------------------------- | | Code | `WA012` | | Severity | Warning | | Field | `registrations` | | Parse Result | Succeeds | | ERC-8004 Compliance | MUST if registrations present | #### Description A registration is missing the required `agentRegistry` field. #### Resolution ```json { "registrations": [ { "agentId": 1, "agentRegistry": "eip155:84532:0x8004a6090Cd10A7288092483047B097295Fb8847" } ] } ``` *** ### WA013 #### Invalid agentRegistry format (should be CAIP-2) | Property | Value | | ------------ | ---------------------------------------------------------------------------------------- | | Code | `WA013` | | Severity | Warning | | Field | `registrations` | | Parse Result | Succeeds | | Reference | [CAIP-2 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) | #### Description The `agentRegistry` field is not in CAIP-2 format. #### Expected Format ```text {namespace}:{chainId}:{contractAddress} ``` #### Examples | Chain | CAIP-2 Format | | ---------------- | --------------------------------------------------------- | | Ethereum Mainnet | `eip155:1:0x8004a6090Cd10A7288092483047B097295Fb8847` | | Base Sepolia | `eip155:84532:0x8004a6090Cd10A7288092483047B097295Fb8847` | | Arbitrum One | `eip155:42161:0x8004a6090Cd10A7288092483047B097295Fb8847` | *** ### WA014 #### supportedTrust field is not an array | Property | Value | | ------------ | ---------------- | | Code | `WA014` | | Severity | Warning | | Field | `supportedTrust` | | Parse Result | Succeeds | #### Description The `supportedTrust` field exists but is not an array. *** ### WA015 #### active field is not boolean | Property | Value | | ------------ | -------- | | Code | `WA015` | | Severity | Warning | | Field | `active` | | Parse Result | Succeeds | #### Description The `active` field should be a boolean (`true` or `false`), not a string or number. #### Resolution ```json { "active": true // βœ… Boolean } ``` ```json { "active": "true" // ❌ String } ``` *** ### WA016 #### x402Support field is not boolean | Property | Value | | ------------ | ------------- | | Code | `WA016` | | Severity | Warning | | Field | `x402Support` | | Parse Result | Succeeds | #### Description The `x402Support` field should be a boolean. *** ### WA020 #### Found 'endpoint' (singular), should be 'endpoints' | Property | Value | | ------------ | --------------------- | | Code | `WA020` | | Severity | Warning | | Field | `endpoint` | | Parse Result | Succeeds | | Type | Common typo detection | #### Description The field `endpoint` (singular) was found but the spec uses `endpoints` (plural). #### Resolution Rename `endpoint` to `endpoints` and ensure it's an array: ```json { "endpoints": [...] // βœ… Plural, array } ``` *** ### WA021 #### Found 'registration' (singular), should be 'registrations' | Property | Value | | ------------ | --------------------- | | Code | `WA021` | | Severity | Warning | | Field | `registration` | | Parse Result | Succeeds | | Type | Common typo detection | #### Description The field `registration` (singular) was found but the spec uses `registrations` (plural). *** ### WA030 #### agentWallet must be CAIP-10 format | Property | Value | | ------------ | ------------------------------------------------------------------------------------------ | | Code | `WA030` | | Severity | Warning | | Field | `agentWallet` | | Parse Result | Succeeds | | Reference | [CAIP-10 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) | #### Description The `agentWallet` endpoint is not in CAIP-10 format. #### Expected Format ```text {namespace}:{chainId}:{address} ``` #### Example ```json { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ``` *** ### WA050 #### base64 URI contains plain JSON (malformed) | Property | Value | | ------------ | ------------------ | | Code | `WA050` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | | Type | Malformed data URI | #### Description The URI declares `;base64` encoding but the content is actually plain JSON. #### Example ```text # ❌ Claims base64 but content is plain JSON data:application/json;base64,{"name":"Agent"} # βœ… Either remove ;base64 data:application/json,{"name":"Agent"} # βœ… Or actually base64-encode data:application/json;base64,eyJuYW1lIjoiQWdlbnQifQ== ``` *** ### WA051 #### Non-standard base64 data URI format | Property | Value | | ------------ | ---------- | | Code | `WA051` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The data URI uses a non-standard format but was successfully parsed. #### Standard Format ```text data:application/json;base64, ``` *** ### WA052 #### Non-standard plain data URI format | Property | Value | | ------------ | ---------- | | Code | `WA052` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The plain data URI uses a non-standard format. #### Standard Format ```text data:application/json, ``` *** ### WA053 #### Plain JSON without URI scheme | Property | Value | | ------------ | ---------- | | Code | `WA053` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The metadata appears to be raw JSON without a URI scheme. #### Resolution Wrap in a data URI: ```text data:application/json,{"name":"Agent",...} ``` *** ### WA054 #### UTF-8 decode error in base64 content | Property | Value | | ------------ | ---------- | | Code | `WA054` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The base64-decoded content is not valid UTF-8. #### Resolution Ensure your JSON is UTF-8 encoded before base64 encoding. *** ### WA055 #### Invalid JSON in base64 content | Property | Value | | ------------ | ---------- | | Code | `WA055` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The base64-decoded content is not valid JSON. *** ### WA056 #### Invalid JSON in plain data URI | Property | Value | | ------------ | ---------- | | Code | `WA056` | | Severity | Warning | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The plain data URI content is not valid JSON. *** ### WA070 #### Metadata content does not match on-chain agentHash | Property | Value | | ------------ | --------------------------------------------------------------------------- | | Code | `WA070` | | Severity | Warning | | Field | `agentHash` | | Parse Result | Succeeds | | Reference | [agentHash Extension](../01-agent-metadata-standard.md#agenthash-extension) | #### Description The computed hash of the metadata doesn't match the `agentHash` stored on-chain via the registry's `setMetadata()` function. #### What This Means * The metadata content has changed since the owner set the hash * For HTTP/HTTPS URIs, this could indicate content tampering * Owner may have updated metadata but forgot to update the hash #### 8004scan Extension This uses the `agentHash` on-chain metadata key, which is an 8004scan-recommended extension for HTTP/HTTPS URI integrity verification. ```solidity // Set agentHash on-chain bytes32 hash = keccak256(abi.encodePacked(canonicalJson)); registry.setMetadata(agentId, "agentHash", abi.encode(hash)); ``` #### Resolution 1. **If you updated metadata intentionally**: Update the on-chain hash 2. **If you didn't update**: Investigate potential content modification 3. **Compute new hash**: ```python import json from web3 import Web3 metadata = {...} canonical = json.dumps(metadata, sort_keys=True, separators=(',', ':')) hash = Web3.keccak(text=canonical).hex() ``` #### API Response Example ```json { "parse_status": { "warnings": [ { "code": "WA070", "field": "agentHash", "message": "Metadata content does not match on-chain agentHash", "expected_hash": "0x1234567890ab...", "actual_hash": "0xabcdef123456..." } ] } } ``` *** ### WA071 #### Metadata content has changed since last sync | Property | Value | | ------------ | ------------------------ | | Code | `WA071` | | Severity | Warning | | Field | `_contentIntegrity` | | Parse Result | Succeeds | | Type | Backend change detection | #### Description The metadata content differs from the previously indexed version. This is a backend integrity check, not an ERC-8004 spec field. #### What This Means For HTTP/HTTPS URIs, the content at the URL has changed since the last sync. #### Note This is expected if you intentionally updated your metadata. The warning helps detect unintended changes. *** ## Agent Info (IA001-IA099) Recommendations and best practices. These MAY be addressed but are not required. *** ### IA001 #### Missing recommended field: image | Property | Value | | ------------------- | -------------- | | Code | `IA001` | | Severity | Info | | Field | `image` | | Parse Result | Succeeds | | ERC-8004 Compliance | MAY (optional) | #### Description The `image` field is not present. Agents without images display with a default placeholder. #### Resolution ```json { "image": "ipfs://Qm.../logo.png" } ``` *** ### IA002 #### Missing endpoints array (agent won't be reachable) | Property | Value | | ------------ | ----------- | | Code | `IA002` | | Severity | Info | | Field | `endpoints` | | Parse Result | Succeeds | #### Description No `endpoints` array defined. Clients cannot connect to this agent. *** ### IA003 #### Empty endpoints array (agent won't be reachable) | Property | Value | | ------------ | ----------- | | Code | `IA003` | | Severity | Info | | Field | `endpoints` | | Parse Result | Succeeds | #### Description The `endpoints` array exists but is empty. *** ### IA004 #### Missing registrations array (no on-chain link) | Property | Value | | ------------ | --------------- | | Code | `IA004` | | Severity | Info | | Field | `registrations` | | Parse Result | Succeeds | #### Description No `registrations` array. Explorers can't verify the bidirectional link between metadata and on-chain identity. *** ### IA005 #### Empty registrations array (no on-chain link) | Property | Value | | ------------ | --------------- | | Code | `IA005` | | Severity | Info | | Field | `registrations` | | Parse Result | Succeeds | #### Description The `registrations` array exists but is empty. *** ### IA006 #### Missing agentId (expected for first-time deployments) | Property | Value | | ------------ | --------------- | | Code | `IA006` | | Severity | Info | | Field | `registrations` | | Parse Result | Succeeds | #### Description A registration is missing `agentId`. This is normal for first-time deployments since you don't know the tokenId before registration. #### Resolution Update metadata after registration to include the assigned `agentId`. *** ### IA007 #### agentId is null (expected for first-time deployments) | Property | Value | | ------------ | --------------- | | Code | `IA007` | | Severity | Info | | Field | `registrations` | | Parse Result | Succeeds | #### Description The `agentId` is explicitly set to `null`. Same as IA006. *** ### IA008 #### Empty supportedTrust array (discovery-only mode) | Property | Value | | ------------ | ---------------- | | Code | `IA008` | | Severity | Info | | Field | `supportedTrust` | | Parse Result | Succeeds | #### Description Agent has no trust models configured. Operating in discovery-only mode. *** ### IA009 #### Unknown trust model (may be future extension) | Property | Value | | ------------ | ---------------- | | Code | `IA009` | | Severity | Info | | Field | `supportedTrust` | | Parse Result | Succeeds | #### Description A trust model in the array is not in the known set. #### Known Models * `reputation` * `crypto-economic` * `tee-attestation` * `social-graph` *** ### IA010 #### Found 'supportedTrusts' (plural), spec uses 'supportedTrust' | Property | Value | | ------------ | ----------------- | | Code | `IA010` | | Severity | Info | | Field | `supportedTrusts` | | Parse Result | Succeeds | #### Description Common typo. The spec uses singular `supportedTrust`. *** ### IA020 #### MCP endpoint missing version field | Property | Value | | ------------------- | --------------------------- | | Code | `IA020` | | Severity | Info | | Field | `MCP` | | Parse Result | Succeeds | | ERC-8004 Compliance | Version is SHOULD, not MUST | #### Description MCP endpoint doesn't specify a version. #### Recommendation ```json { "name": "MCP", "endpoint": "https://...", "version": "2025-06-18" } ``` *** ### IA021 #### MCP version is not in date format (YYYY-MM-DD) | Property | Value | | ------------ | ------------------------------------------------------------------ | | Code | `IA021` | | Severity | Info | | Field | `MCP` | | Parse Result | Succeeds | | Valid Format | `YYYY-MM-DD` (e.g., `2025-06-18`, `2025-11-25`, `2026-01-29`) | | Reference | [MCP Specification](https://modelcontextprotocol.io/specification) | #### Description MCP uses date-based versioning. The version field should be in `YYYY-MM-DD` format representing the protocol specification date. Any valid date from 2024 onwards is accepted. *** ### IA022 #### A2A endpoint missing version field | Property | Value | | ------------ | -------- | | Code | `IA022` | | Severity | Info | | Field | `A2A` | | Parse Result | Succeeds | #### Description A2A endpoint doesn't specify a version. *** ### IA023 #### A2A version is not in semver format | Property | Value | | ------------ | ---------------------------------------- | | Code | `IA023` | | Severity | Info | | Field | `A2A` | | Parse Result | Succeeds | | Valid Format | Semver: `X.Y.Z` or `X.Y` (e.g., `0.3.0`) | #### Description A2A version is not the standard version. *** ### IA024 #### A2A endpoint should use .well-known/agent-card.json path | Property | Value | | ------------ | -------- | | Code | `IA024` | | Severity | Info | | Field | `A2A` | | Parse Result | Succeeds | #### Description A2A endpoint doesn't use the recommended well-known path. #### Recommendation ```text https://your-agent.com/.well-known/agent-card.json ``` *** ### IA025 #### OASF endpoint has neither skills nor domains | Property | Value | | ------------ | -------- | | Code | `IA025` | | Severity | Info | | Field | `OASF` | | Parse Result | Succeeds | #### Description OASF endpoint exists but has no skills or domains defined. *** ### IA026 #### OASF version is not in semver format | Property | Value | | ------------ | ------------------------------------------------------------ | | Code | `IA026` | | Severity | Info | | Field | `OASF` | | Parse Result | Succeeds | | Valid Format | Semver with optional 'v' prefix: `X.Y.Z`, `vX.Y.Z`, or `X.Y` | | Reference | [OASF Releases](https://github.com/agntcy/oasf/releases) | #### Description OASF uses semantic versioning. The version field should be in semver format, with an optional 'v' prefix. Multiple major version lines are supported (0.7.x, 0.8.x, etc.). *** ### IA027 #### Unknown OASF skill category | Property | Value | | ------------ | ------------------------------------------------ | | Code | `IA027` | | Severity | Info | | Field | `OASF` | | Parse Result | Succeeds | | Reference | [OASF Taxonomy](https://github.com/agntcy/oasf/) | #### Description A skill in the OASF endpoint is not in the known taxonomy. *** ### IA028 #### Unknown OASF domain category | Property | Value | | ------------ | -------- | | Code | `IA028` | | Severity | Info | | Field | `OASF` | | Parse Result | Succeeds | #### Description A domain in the OASF endpoint is not in the known taxonomy. *** ### IA040 #### HTTP/HTTPS URI is not content-addressed | Property | Value | | ------------ | ---------- | | Code | `IA040` | | Severity | Info | | Field | `agentURI` | | Parse Result | Succeeds | #### Description Agent uses a mutable HTTP/HTTPS URL for metadata. Content at HTTP URLs can change without notice. #### Why This Matters * No built-in integrity verification * Content can change between fetches * Harder to audit historical state #### Recommendations 1. **Use IPFS**: `ipfs://Qm...` for immutable content 2. **Set agentHash**: On-chain integrity verification 3. **Use data URIs**: For small metadata (`data:application/json,...`) *** ### IA041 #### URL-decoded plain data URI | Property | Value | | ------------ | ---------- | | Code | `IA041` | | Severity | Info | | Field | `agentURI` | | Parse Result | Succeeds | #### Description The data URI content was URL-encoded and had to be decoded. *** ## Feedback Errors (EF001-EF099) Critical issues in feedback parsing. *** ### EF001 #### Invalid timestamp format | Property | Value | | ------------ | ----------------- | | Code | `EF001` | | Severity | Error | | Field | `timestamp` | | Parse Result | Uses current time | #### Description The timestamp field cannot be parsed as a Unix timestamp. #### Expected Format Unix timestamp in seconds (integer). *** ### EF002 #### Failed to fetch offchain data | Property | Value | | ------------ | --------------- | | Code | `EF002` | | Severity | Error | | Field | `feedbackURI` | | Parse Result | Partial success | #### Description Could not fetch the feedback's offchain data from `feedbackURI`. *** ## Feedback Warnings (WF001-WF099) *** ### WF001 #### Invalid timestamp (using current time) | Property | Value | | ------------ | ----------- | | Code | `WF001` | | Severity | Warning | | Field | `timestamp` | | Parse Result | Succeeds | #### Description Revocation timestamp invalid. Using current time as fallback. *** ### WF002 #### Feedback hash mismatch | Property | Value | | ------------ | -------------- | | Code | `WF002` | | Severity | Warning | | Field | `feedbackHash` | | Parse Result | Succeeds | #### Description The computed hash of offchain data doesn't match `feedbackHash` on-chain. *** ### WF003 #### Tag stored as hash (original not available) | Property | Value | | ------------ | -------- | | Code | `WF003` | | Severity | Warning | | Field | `tag` | | Parse Result | Succeeds | #### Description The indexed `tag1` is stored as a keccak256 hash and the original value wasn't in offchain data. #### Why This Happens Indexed string parameters in Solidity events are stored as hashes. The original value should be provided in `feedbackURI` data. *** ## Related Documentation * [Agent Metadata Standard](../01-agent-metadata-standard.md) - Full schema specification * [Agent Metadata Parsing](./agent-metadata-parsing.md) - Parsing implementation guide * [Feedback Best Practices](./feedback-best-practices.md) - Feedback handling * [Data URI Compression](../extensions/data-uri-compression.md) - Compression extension *** **Last Updated**: 2026-01-15 --- --- url: /docs/extensions/README.md --- # Extensions This directory contains optional extensions and enhancements to the ERC-8004 offchain data standards. ## What are Extensions? Extensions are **optional, community-proposed** additions that build on the core ERC-8004 standards defined in the parent [docs directory](../README.md). They provide practical solutions to specific use cases without modifying the base specification. ## Available Extensions ### 1. Attachment Pattern Standard **File**: [04-attachment-pattern-standard.md](04-attachment-pattern-standard.md) Defines a reusable schema for including evidence files, receipts, and supporting documents in: * Feedback records (Reputation Registry) * Validation requests/responses (Validation Registry) **When to use**: Whenever your feedback or validation data needs to reference external files. **Key fields**: `name`, `uri`, `mimeType`, `size`, `description` (optional), `uploadedAt` (optional) *** ### 2. Value Decimals Patterns **File**: [05-value-decimals-patterns.md](05-value-decimals-patterns.md) Provides standard patterns and best practices for the flexible `value` + `valueDecimals` system introduced in v2.0. **When to use**: When defining feedback metrics such as uptime, success rates, financial yields, latency, or custom rating scales. **Key patterns**: Percentages, Binary Flags, Financial Metrics, Time/Latency, Subjective Ratings. *** ### 3. Data URI Compression Extension **File**: [data-uri-compression.md](data-uri-compression.md) Provides a protocol for gas-efficient onchain metadata storage using compression. **Scope**: Applies only to **Data URI-based metadata** (not IPFS or HTTPS) **Algorithms supported**: zstd, gzip, brotli, lz4 **Expected savings**: 40-70% reduction in gas costs for onchain metadata storage **When to use**: When registering agent metadata directly onchain and storage costs are a concern *** ### 3. Compression Benchmarks **File**: [compression-test-results.md](compression-test-results.md) Real-world benchmark data from 4,916 production agents showing actual compression ratios and gas savings. **Data source**: 8004scan production database (Base Sepolia + Ethereum Sepolia) **Key finding**: Most agents (99.4%) use metadata < 2KB, saving ~4,500-6,000 gas per registration with compression ### 4. Solana Chain Support **File**: [solana-support.md](solana-support.md) Defines how ERC-8004 standards apply to the Solana blockchain, covering address formats (base58), signature algorithms (Ed25519), NFT standards (Metaplex Core), content hashing (SHA-256 / SEAL v1), authentication (SIWS), and ATOM trust metrics. **Key differences from EVM**: Case-sensitive base58 addresses (32-44 chars), longer transaction signatures (87-88 chars), no `0x` prefix on hashes, and on-chain trust scoring via the ATOM engine. *** ## Using Extensions Together ### Scenario 1: Agent Metadata with Evidence Files ```text Agent Registration β”œβ”€β”€ AgentURI (Data URI, compressed) └── Metadata JSON └── Includes feedback evidence (uses Attachment Pattern) ``` Process: 1. Use [Agent Metadata Profile](../01-agent-metadata-standard.md) for base structure 2. Apply [Data URI Compression](data-uri-compression.md) to optimize storage 3. Use [Attachment Pattern](04-attachment-pattern-standard.md) for evidence files *** ### Scenario 2: Feedback with Supporting Documents ```text Feedback Record β”œβ”€β”€ feedbackURI (any storage: IPFS, HTTPS, or Data URI) └── Feedback JSON └── attachments (uses Attachment Pattern) └── Evidence files (PDFs, screenshots, etc.) ``` Process: 1. Use [Feedback Profile](../02-feedback-standard.md) for base structure 2. Use [Attachment Pattern](04-attachment-pattern-standard.md) for evidence 3. If using Data URI: apply [Data URI Compression](data-uri-compression.md) *** ## Extension Development Guidelines Future extensions should follow these principles: * **Non-breaking**: Extensions must not modify core standard requirements * **Optional**: Should be adoptable independently * **Documented**: Include use cases, examples, and compatibility notes * **Evaluated**: Include benchmarks or testing results where applicable *** ## Related Documentation * **Core Standards**: See [Data Profiles Overview](../README.md) * **Official Spec**: [ERC-8004 at EIPS.ethereum.org](https://eips.ethereum.org/EIPS/eip-8004) * **Best Practices**: See [Implementation Guides](../implementation/README.md) --- --- url: /v1/docs/extensions/README.md --- # Extensions This directory contains optional extensions and enhancements to the ERC-8004 offchain data standards. ## What are Extensions? Extensions are **optional, community-proposed** additions that build on the core ERC-8004 standards defined in the parent [docs directory](../README.md). They provide practical solutions to specific use cases without modifying the base specification. ## Available Extensions ### 1. Attachment Pattern Standard **File**: [04-attachment-pattern-standard.md](04-attachment-pattern-standard.md) Defines a reusable schema for including evidence files, receipts, and supporting documents in: * Feedback records (Reputation Registry) * Validation requests/responses (Validation Registry) **When to use**: Whenever your feedback or validation data needs to reference external files. **Key fields**: `name`, `uri`, `mimeType`, `size`, `description` (optional), `uploadedAt` (optional) *** ### 2. Data URI Compression Extension **File**: [data-uri-compression.md](data-uri-compression.md) Provides a protocol for gas-efficient onchain metadata storage using compression. **Scope**: Applies only to **Data URI-based metadata** (not IPFS or HTTPS) **Algorithms supported**: zstd, gzip, brotli, lz4 **Expected savings**: 40-70% reduction in gas costs for onchain metadata storage **When to use**: When registering agent metadata directly onchain and storage costs are a concern *** ### 3. Compression Benchmarks **File**: [compression-test-results.md](compression-test-results.md) Real-world benchmark data from 4,916 production agents showing actual compression ratios and gas savings. **Data source**: 8004scan production database (Base Sepolia + Ethereum Sepolia) **Key finding**: Most agents (99.4%) use metadata < 2KB, saving ~4,500-6,000 gas per registration with compression *** ## Using Extensions Together ### Scenario 1: Agent Metadata with Evidence Files ```text Agent Registration β”œβ”€β”€ AgentURI (Data URI, compressed) └── Metadata JSON └── Includes feedback evidence (uses Attachment Pattern) ``` Process: 1. Use [Agent Metadata Profile](../01-agent-metadata-standard.md) for base structure 2. Apply [Data URI Compression](data-uri-compression.md) to optimize storage 3. Use [Attachment Pattern](04-attachment-pattern-standard.md) for evidence files *** ### Scenario 2: Feedback with Supporting Documents ```text Feedback Record β”œβ”€β”€ feedbackURI (any storage: IPFS, HTTPS, or Data URI) └── Feedback JSON └── attachments (uses Attachment Pattern) └── Evidence files (PDFs, screenshots, etc.) ``` Process: 1. Use [Feedback Profile](../02-feedback-standard.md) for base structure 2. Use [Attachment Pattern](04-attachment-pattern-standard.md) for evidence 3. If using Data URI: apply [Data URI Compression](data-uri-compression.md) *** ## Extension Development Guidelines Future extensions should follow these principles: * **Non-breaking**: Extensions must not modify core standard requirements * **Optional**: Should be adoptable independently * **Documented**: Include use cases, examples, and compatibility notes * **Evaluated**: Include benchmarks or testing results where applicable *** ## Related Documentation * **Core Standards**: See [Data Profiles Overview](../README.md) * **Official Spec**: [ERC-8004 at EIPS.ethereum.org](https://eips.ethereum.org/EIPS/eip-8004) * **Best Practices**: See [Implementation Guides](../implementation/README.md) --- --- url: /docs/implementation/feedback-best-practices.md description: Practical guide for creating effective agent feedback --- ## Description Practical guide for creating effective agent feedback **Audience**: Agent users, developers, validators ## Overview This guide provides best practices for creating high-quality feedback on ERC-8004 agents, helping build trust and improve the ecosystem. **What You'll Learn**: * βœ… Write clear, actionable feedback * βœ… Use the v2.0 `value` + `valueDecimals` system * βœ… Provide effective evidence using attachments * βœ… Choose appropriate feedback types * βœ… Handle privacy and sensitive data * βœ… Use protocol-specific fields (A2A, MCP, x402) ## Feedback Principles ### 1. Be Specific and Actionable ❌ **Bad**: "Agent doesn't work" βœ… **Good**: ```json { "value": "2", "valueDecimals": 0, "reasoning": "Agent failed to analyze wallet 0x1234... Transaction parsing error at block 18500000. Expected JSON response but received HTML error page.", "reproducible": true } ``` **Why**: Specific feedback helps agent developers identify and fix issues. ### 2. Provide Evidence ❌ **Bad**: Trust me, it's broken βœ… **Good**: Include screenshots, logs, or API responses ```json { "value": "2", "valueDecimals": 0, "reasoning": "Agent returned error when analyzing wallet", "attachments": [ { "name": "Error Screenshot", "uri": "ipfs://bafkreiabc...", "mimeType": "image/png", "description": "Screenshot showing '500 Internal Server Error' at 2025-12-20 14:30 UTC" }, { "name": "Error Logs", "uri": "ipfs://bafkreixyz...", "mimeType": "application/json", "description": "Full API response logs with stack trace" } ] } ``` ### 3. Be Fair and Constructive ❌ **Bad**: "This agent is garbage" βœ… **Good**: ```json { "value": "3", "valueDecimals": 0, "reasoning": "Agent successfully analyzed 80% of test cases (8/10). Failed on complex multi-sig transactions. Response time was excellent (~2s average). Recommend adding multi-sig support.", "tag1": "needs-improvement", "tag2": "fast-response" } ``` ## Feedback Type Guide (5-Star Scale) ### Positive Feedback (4-5 Stars) **When to Use**: * Agent performed as expected * Results were accurate * Response time was acceptable * Good user experience **Example**: ```json { "agentRegistry": "eip155:11155111:0x8004...", "agentId": 123, "clientAddress": "eip155:11155111:0x742d...", "createdAt": "2025-12-20T10:00:00Z", "value": "5", "valueDecimals": 0, "reasoning": "Excellent blockchain analytics. Analyzed 1000+ transactions in under 5 seconds. Detected 3 suspicious patterns I missed manually. Highly recommend.", "tag1": "fast", "tag2": "accurate" } ``` ### Mixed Feedback (2-3 Stars) **When to Use**: * Agent works but has limitations * Some features good, others need improvement * Acceptable but not great **Example**: ```json { "value": "3", "valueDecimals": 0, "reasoning": "Good for simple queries, but struggles with complex analysis. Free tier works well. Premium features overpriced at 0.1 ETH per report. UI is intuitive.", "tag1": "good-ui", "tag2": "expensive", "attachments": [ { "name": "Feature Comparison", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "description": "Comparison with similar agents showing price/feature gaps" } ] } ``` ### Negative Feedback (0-1 Stars or Negative) **When to Use**: * Agent failed to deliver * Critical bugs or errors * Safety/security concerns * Misleading claims **Example**: ```json { "value": "-1", "valueDecimals": 0, "reasoning": "Agent claimed '99% uptime' but was offline for 6 hours during critical market event. No refund offered despite x402 payment. Support unresponsive.", "tag1": "unreliable", "tag2": "dispute", "attachments": [ { "name": "Downtime Logs", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Ping logs showing 6-hour offline period" }, { "name": "Payment Receipt", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "x402 payment proof" } ] } ``` **Important**: Always provide evidence for negative feedback to prevent abuse. ## Scoring Guidelines (v2.0) Using the standard **5-Star Rating** pattern (`valueDecimals = 0`): | Value | Meaning | When to Use | | ------ | -------------- | -------------------------------------------- | | **5** | Outstanding | Exceeded expectations, highly recommend | | **4** | Good | Met expectations, would use again | | **3** | Acceptable | Works but has issues, neutral recommendation | | **2** | Below Average | Significant problems, not recommended | | **1** | Poor | Failed to deliver, do not use | | **0** | Very Poor | Completely non-functional | | **<0** | Dispute / Scam | Fraud, malicious behavior, or dispute | **Tips**: * Use `valueDecimals: 1` for half-stars (e.g., `45` = 4.5 stars). * Use `tag1` to define the metric type if not using a general rating (e.g., `tag1: "uptime"`). ## Attachment Pattern Best Practices ### Supported File Types | Type | MIME Type | Use Case | Example | | ---------- | ----------------------------- | ---------------------------- | --------------------------- | | **PDF** | `application/pdf` | Audit reports, documentation | Security audit report | | **Images** | `image/png`, `image/jpeg` | Screenshots, diagrams | Error screenshots | | **JSON** | `application/json` | API responses, test results | Agent API response logs | | **Text** | `text/plain`, `text/markdown` | Logs, notes | Detailed test notes | | **CSV** | `text/csv` | Benchmark data | Performance benchmarks | | **Video** | `video/mp4`, `video/webm` | Screen recordings | Demo of bug reproduction | | **ZIP** | `application/zip` | Multiple files | Complete test suite results | ### Attachment Examples #### Example 1: Security Audit Report ```json { "reasoning": "Passed third-party security audit with 0 critical findings", "attachments": [ { "name": "Security Audit Report", "uri": "ipfs://bafkreifjv...", "mimeType": "application/pdf", "size": 2048000, "description": "Automated scan using Slither v0.9.6 + manual review by certified auditor. Scanned 5 smart contracts and 2 API endpoints. Report dated 2025-12-15.", "uploadedAt": "2025-12-16T10:00:00Z" } ] } ``` #### Example 2: Performance Benchmarks ```json { "reasoning": "Tested performance under load. Results show excellent scalability.", "attachments": [ { "name": "Benchmark Results", "uri": "ipfs://bafkreiabc...", "mimeType": "text/csv", "size": 50000, "description": "1000 API calls on Sepolia testnet. Average response time: 1.2s. 99.9% uptime over 7 days. Test environment: AWS t3.medium instance.", "uploadedAt": "2025-12-16T12:00:00Z" }, { "name": "Load Test Graph", "uri": "ipfs://bafkreixyz...", "mimeType": "image/png", "size": 150000, "description": "Response time vs concurrent requests graph. Shows linear scaling up to 100 concurrent users." } ] } ``` #### Example 3: Bug Reproduction ```json { "value": "2", "valueDecimals": 0, "reasoning": "Agent crashes when processing ERC-4337 account abstraction wallets", "attachments": [ { "name": "Bug Reproduction Steps", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "size": 5000, "description": "Step-by-step reproduction guide with test wallet address and transaction hash" }, { "name": "Error Video", "uri": "ipfs://bafkrei...", "mimeType": "video/mp4", "size": 5000000, "description": "Screen recording showing agent crash when analyzing wallet 0x1234... at timestamp 00:42" }, { "name": "API Logs", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "size": 20000, "description": "Complete API request/response logs showing 500 error with stack trace" } ] } ``` ### Attachment Upload Methods #### Method 1: IPFS Upload (Recommended) ```bash # Using IPFS CLI ipfs add security-audit.pdf # Returns: added QmXXX... security-audit.pdf # Using Pinata API curl -X POST "https://api.pinata.cloud/pinning/pinFileToIPFS" \ -H "Authorization: Bearer YOUR_JWT" \ -F "file=@security-audit.pdf" ``` **Attachment**: ```json { "name": "Security Audit Report", "uri": "ipfs://QmXXX...", "mimeType": "application/pdf" } ``` #### Method 2: Inline JSON (Small Data) For small datasets (<100KB), embed directly: ```json { "reasoning": "Benchmark results attached", "attachments": [ { "name": "Performance Metrics", "uri": "data:application/json;base64,eyJhdmdSZXNwb25zZVRpbWUiOjEuMiwicDk5IjoyLjV9", "mimeType": "application/json", "description": "Key metrics: avg 1.2s, p99 2.5s" } ] } ``` #### Method 3: HTTPS URL (Centralized but Fast) ```json { "name": "Test Results Dashboard", "uri": "https://example.com/test-results/agent-123-2025-12-20.html", "mimeType": "text/html", "description": "Interactive dashboard with real-time test results (requires login)" } ``` ⚠️ **Caution**: HTTPS URLs can change or disappear. Prefer IPFS for permanence. ## Protocol-Specific Fields ### A2A Protocol Feedback When providing feedback after A2A (Agent-to-Agent) interactions: ```json { "value": "5", "valueDecimals": 0, "reasoning": "Excellent A2A collaboration. Agent responded within SLA and provided structured data.", "skill": "analytical_skills/data_analysis/blockchain_analysis", "domain": "technology/blockchain", "context": "Analyzed blockchain transaction patterns", "tag1": "a2a-compatible", "tag2": "fast-response" } ``` ### MCP Protocol Feedback For MCP tool/prompt feedback: ```json { "value": "4", "valueDecimals": 0, "reasoning": "MCP tools work well. analyze_wallet tool is accurate.", "capability": "tools", "name": "analyze_wallet", "tag1": "mcp", "tag2": "tools" } ``` ### x402 Payment Feedback When using x402 payment protocol: ```json { "value": "5", "valueDecimals": 0, "reasoning": "Fair pricing via x402. Paid 0.01 ETH for premium analysis. Worth it.", "proofOfPayment": { "protocol": "x402", "amount": "10000000000000000", "currency": "ETH", "txHash": "0xabc123...", "chainId": 1, "timestamp": "2025-12-20T10:00:00Z" }, "tag1": "good-value", "tag2": "x402-compatible" } ``` ## Privacy and Security ### DO Include βœ… General performance metrics βœ… Anonymized test data βœ… Public blockchain addresses (if relevant) βœ… Error messages (sanitized) βœ… Public API endpoints ### DO NOT Include ❌ Private keys or seed phrases ❌ API keys or access tokens ❌ Personal identifiable information (PII) ❌ Confidential business data ❌ Internal system details (if security-sensitive) **Example of Sanitization**: ```json // ❌ BAD { "reasoning": "API key sk-1234abcd exposed in logs" } // βœ… GOOD { "reasoning": "API credentials exposed in error response (redacted for security)", "attachments": [ { "name": "Sanitized Logs", "uri": "ipfs://...", "description": "Error logs with sensitive data redacted" } ] } ``` ## Feedback Templates ### Template 1: Service Quality Feedback ```json { "agentRegistry": "eip155:11155111:0x...", "agentId": 123, "clientAddress": "eip155:11155111:0x...", "createdAt": "2025-12-20T10:00:00Z", "value": "4", "valueDecimals": 0, "reasoning": "[What you experienced, specific examples, overall impression]", "tag1": "tag1", "tag2": "tag2" } ``` ### Template 2: Detailed Technical Feedback ```json { "agentRegistry": "eip155:11155111:0x...", "agentId": 123, "clientAddress": "eip155:11155111:0x...", "createdAt": "2025-12-20T10:00:00Z", "value": "3", "valueDecimals": 0, "reasoning": "[Detailed technical analysis]", "tag1": "performance", "tag2": "accuracy", "attachments": [ { "name": "Benchmark Results", "uri": "ipfs://...", "mimeType": "application/json", "description": "Performance test results (1000 requests over 24 hours)" } ] } ``` ### Template 3: Payment/Value Feedback ```json { "value": "5", "valueDecimals": 0, "reasoning": "Excellent value for money. Premium tier justifies cost.", "proofOfPayment": { "protocol": "x402", "amount": "10000000000000000", "currency": "ETH", "txHash": "0x..." }, "tag1": "good-value", "tag2": "x402-compatible" } ``` ## Common Mistakes to Avoid ### Mistake 1: Vague Feedback ❌ **Bad**: "Doesn't work" βœ… **Good**: "analyze\_wallet tool returns 500 error for wallets with >1000 transactions. Tested with 0x1234..." ### Mistake 2: No Evidence for Claims ❌ **Bad**: "Agent is a scam, stole my data" βœ… **Good**: Include proof (logs, transaction hashes, screenshots) ### Mistake 3: Emotional/Abusive Language ❌ **Bad**: "This garbage agent is a complete waste of time run by idiots" βœ… **Good**: "Agent did not meet advertised SLA (99% uptime). Measured 92% uptime over 7 days. Request refund." ### Mistake 4: Irrelevant Tags ❌ **Bad**: `tag1: "agent"`, `tag2: "feedback"` βœ… **Good**: `tag1: "slow-response"`, `tag2: "expensive"` ## FAQ **Q: Should I leave feedback after every interaction?** A: No, prioritize feedback for: * Exceptional experiences (very good or very bad) * First-time use of an agent * After major updates * When explicitly requested by agent owner **Q: Can I update feedback later?** A: Depends on implementation. 8004scan supports feedback updates via new transactions. **Q: What if agent owner disputes my feedback?** A: Provide evidence via attachments. On-chain feedback is immutable, but reputation systems may weight evidence. **Q: Should I give feedback for test interactions?** A: Yes, but use tags like `tag1: "test"` to distinguish from production use. ## Resources * [Feedback Standard](../02-feedback-standard.md) * [Validation Best Practices](validation-best-practices.md) * [Value Decimals Patterns](../extensions/05-value-decimals-patterns.md) --- --- url: /legacy-pre-v1/docs/implementation/feedback-best-practices.md description: Practical guide for creating effective agent feedback --- ## Description Practical guide for creating effective agent feedback **Audience**: Agent users, developers, validators ## Overview This guide provides best practices for creating high-quality feedback on ERC-8004 agents, helping build trust and improve the ecosystem. **What You'll Learn**: * βœ… Write clear, actionable feedback * βœ… Provide effective evidence using attachments * βœ… Choose appropriate feedback types * βœ… Handle privacy and sensitive data * βœ… Use protocol-specific fields (A2A, MCP, x402) ## Feedback Principles ### 1. Be Specific and Actionable ❌ **Bad**: "Agent doesn't work" βœ… **Good**: ```json { "feedbackType": "negative", "score": 2, "reasoning": "Agent failed to analyze wallet 0x1234... Transaction parsing error at block 18500000. Expected JSON response but received HTML error page.", "reproducible": true } ``` **Why**: Specific feedback helps agent developers identify and fix issues. ### 2. Provide Evidence ❌ **Bad**: Trust me, it's broken βœ… **Good**: Include screenshots, logs, or API responses ```json { "feedbackType": "negative", "score": 2, "reasoning": "Agent returned error when analyzing wallet", "attachments": [ { "name": "Error Screenshot", "uri": "ipfs://bafkreiabc...", "mimeType": "image/png", "description": "Screenshot showing '500 Internal Server Error' at 2025-12-20 14:30 UTC" }, { "name": "Error Logs", "uri": "ipfs://bafkreixyz...", "mimeType": "application/json", "description": "Full API response logs with stack trace" } ] } ``` ### 3. Be Fair and Constructive ❌ **Bad**: "This agent is garbage" βœ… **Good**: ```json { "feedbackType": "mixed", "score": 3, "reasoning": "Agent successfully analyzed 80% of test cases (8/10). Failed on complex multi-sig transactions. Response time was excellent (~2s average). Recommend adding multi-sig support.", "tags": ["needs-improvement", "fast-response"] } ``` ## Feedback Type Guide ### Positive Feedback (score: 4-5) **When to Use**: * Agent performed as expected * Results were accurate * Response time was acceptable * Good user experience **Example**: ```json { "agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847", "agentId": 123, "clientAddress": "eip155:11155111:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7", "createdAt": "2025-12-20T10:00:00Z", "feedbackType": "positive", "score": 5, "reasoning": "Excellent blockchain analytics. Analyzed 1000+ transactions in under 5 seconds. Detected 3 suspicious patterns I missed manually. Highly recommend.", "tags": ["fast", "accurate", "recommended"] } ``` ### Mixed Feedback (score: 2-4) **When to Use**: * Agent works but has limitations * Some features good, others need improvement * Acceptable but not great **Example**: ```json { "feedbackType": "mixed", "score": 3, "reasoning": "Good for simple queries, but struggles with complex analysis. Free tier works well. Premium features overpriced at 0.1 ETH per report. UI is intuitive.", "tags": ["good-ui", "expensive", "limited-features"], "attachments": [ { "name": "Feature Comparison", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "description": "Comparison with similar agents showing price/feature gaps" } ] } ``` ### Negative Feedback (score: 0-2) **When to Use**: * Agent failed to deliver * Critical bugs or errors * Safety/security concerns * Misleading claims **Example**: ```json { "feedbackType": "negative", "score": 1, "reasoning": "Agent claimed '99% uptime' but was offline for 6 hours during critical market event. No refund offered despite x402 payment. Support unresponsive.", "tags": ["unreliable", "poor-support", "false-advertising"], "attachments": [ { "name": "Downtime Logs", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Ping logs showing 6-hour offline period (2025-12-15 08:00-14:00 UTC)" }, { "name": "Payment Receipt", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "x402 payment proof (0.05 ETH for 24h service)" } ] } ``` **Important**: Always provide evidence for negative feedback to prevent abuse. ## Scoring Guidelines | Score | Meaning | When to Use | | ----- | ----------------- | -------------------------------------------- | | **5** | Outstanding | Exceeded expectations, highly recommend | | **4** | Good | Met expectations, would use again | | **3** | Acceptable | Works but has issues, neutral recommendation | | **2** | Below Average | Significant problems, not recommended | | **1** | Poor | Failed to deliver, do not use | | **0** | Completely Failed | Agent non-functional or malicious | **Tips**: * Reserve 5β˜… for truly exceptional experiences * Use 3β˜… as baseline for "works as advertised" * Only use 0β˜… for serious issues (scams, malware, data breaches) ## Attachment Pattern Best Practices ### Supported File Types | Type | MIME Type | Use Case | Example | | ---------- | ----------------------------- | ---------------------------- | --------------------------- | | **PDF** | `application/pdf` | Audit reports, documentation | Security audit report | | **Images** | `image/png`, `image/jpeg` | Screenshots, diagrams | Error screenshots | | **JSON** | `application/json` | API responses, test results | Agent API response logs | | **Text** | `text/plain`, `text/markdown` | Logs, notes | Detailed test notes | | **CSV** | `text/csv` | Benchmark data | Performance benchmarks | | **Video** | `video/mp4`, `video/webm` | Screen recordings | Demo of bug reproduction | | **ZIP** | `application/zip` | Multiple files | Complete test suite results | ### Attachment Examples #### Example 1: Security Audit Report ```json { "reasoning": "Passed third-party security audit with 0 critical findings", "attachments": [ { "name": "Security Audit Report", "uri": "ipfs://bafkreifjv...", "mimeType": "application/pdf", "size": 2048000, "description": "Automated scan using Slither v0.9.6 + manual review by certified auditor. Scanned 5 smart contracts and 2 API endpoints. Report dated 2025-12-15.", "uploadedAt": "2025-12-16T10:00:00Z" } ] } ``` #### Example 2: Performance Benchmarks ```json { "reasoning": "Tested performance under load. Results show excellent scalability.", "attachments": [ { "name": "Benchmark Results", "uri": "ipfs://bafkreiabc...", "mimeType": "text/csv", "size": 50000, "description": "1000 API calls on Sepolia testnet. Average response time: 1.2s. 99.9% uptime over 7 days. Test environment: AWS t3.medium instance.", "uploadedAt": "2025-12-16T12:00:00Z" }, { "name": "Load Test Graph", "uri": "ipfs://bafkreixyz...", "mimeType": "image/png", "size": 150000, "description": "Response time vs concurrent requests graph. Shows linear scaling up to 100 concurrent users." } ] } ``` #### Example 3: Bug Reproduction ```json { "feedbackType": "negative", "score": 2, "reasoning": "Agent crashes when processing ERC-4337 account abstraction wallets", "attachments": [ { "name": "Bug Reproduction Steps", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "size": 5000, "description": "Step-by-step reproduction guide with test wallet address and transaction hash" }, { "name": "Error Video", "uri": "ipfs://bafkrei...", "mimeType": "video/mp4", "size": 5000000, "description": "Screen recording showing agent crash when analyzing wallet 0x1234... at timestamp 00:42" }, { "name": "API Logs", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "size": 20000, "description": "Complete API request/response logs showing 500 error with stack trace" } ] } ``` ### Attachment Upload Methods #### Method 1: IPFS Upload (Recommended) ```bash # Using IPFS CLI ipfs add security-audit.pdf # Returns: added QmXXX... security-audit.pdf # Using Pinata API curl -X POST "https://api.pinata.cloud/pinning/pinFileToIPFS" \ -H "Authorization: Bearer YOUR_JWT" \ -F "file=@security-audit.pdf" ``` **Attachment**: ```json { "name": "Security Audit Report", "uri": "ipfs://QmXXX...", "mimeType": "application/pdf" } ``` #### Method 2: Inline JSON (Small Data) For small datasets (<100KB), embed directly: ```json { "reasoning": "Benchmark results attached", "attachments": [ { "name": "Performance Metrics", "uri": "data:application/json;base64,eyJhdmdSZXNwb25zZVRpbWUiOjEuMiwicDk5IjoyLjV9", "mimeType": "application/json", "description": "Key metrics: avg 1.2s, p99 2.5s" } ] } ``` #### Method 3: HTTPS URL (Centralized but Fast) ```json { "name": "Test Results Dashboard", "uri": "https://example.com/test-results/agent-123-2025-12-20.html", "mimeType": "text/html", "description": "Interactive dashboard with real-time test results (requires login)" } ``` ⚠️ **Caution**: HTTPS URLs can change or disappear. Prefer IPFS for permanence. ## Protocol-Specific Fields ### A2A Protocol Feedback When providing feedback after A2A (Agent-to-Agent) interactions: ```json { "feedbackType": "positive", "score": 5, "reasoning": "Excellent A2A collaboration. Agent responded within SLA and provided structured data.", "a2aInteraction": { "requestId": "req-uuid-1234", "responseTime": 1.8, "skillsUsed": ["analytical_skills/data_analysis/blockchain_analysis"], "protocol": "A2A v0.3.0" }, "tags": ["a2a-compatible", "fast-response"] } ``` ### MCP Protocol Feedback For MCP tool/prompt feedback: ```json { "feedbackType": "positive", "score": 4, "reasoning": "MCP tools work well. analyze_wallet tool is accurate. summarize_trends prompt is helpful.", "mcpFeedback": { "toolsUsed": ["analyze_wallet", "detect_anomalies"], "promptsUsed": ["What are the risks?"], "serverVersion": "2025-06-18", "issues": ["analyze_wallet sometimes times out on large wallets"] } } ``` ### x402 Payment Feedback When using x402 payment protocol: ```json { "feedbackType": "positive", "score": 5, "reasoning": "Fair pricing via x402. Paid 0.01 ETH for premium analysis. Worth it.", "paymentProof": { "protocol": "x402", "amount": "10000000000000000", "currency": "ETH", "transactionHash": "0xabc123...", "chainId": 1, "timestamp": "2025-12-20T10:00:00Z" }, "costEffectiveness": "excellent" } ``` ## Privacy and Security ### DO Include βœ… General performance metrics βœ… Anonymized test data βœ… Public blockchain addresses (if relevant) βœ… Error messages (sanitized) βœ… Public API endpoints ### DO NOT Include ❌ Private keys or seed phrases ❌ API keys or access tokens ❌ Personal identifiable information (PII) ❌ Confidential business data ❌ Internal system details (if security-sensitive) **Example of Sanitization**: ```json // ❌ BAD { "reasoning": "API key sk-1234abcd exposed in logs" } // βœ… GOOD { "reasoning": "API credentials exposed in error response (redacted for security)", "attachments": [ { "name": "Sanitized Logs", "uri": "ipfs://...", "description": "Error logs with sensitive data redacted" } ] } ``` ## Feedback Authorization ### Anonymous Feedback ```json { "clientAddress": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7", "feedbackType": "positive", "score": 5, "reasoning": "Great agent!", "authorization": { "signature": "0xabc123...", "message": "I approve this feedback for agent 123 on 2025-12-20", "signer": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } } ``` ### Validator-Endorsed Feedback For feedback from trusted validators: ```json { "clientAddress": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7", "feedbackType": "positive", "score": 5, "reasoning": "Agent passed comprehensive security validation", "validatorEndorsement": { "validatorAddress": "eip155:1:0x1234...", "validatorTier": "platform", "endorsementType": "security-audit", "signature": "0xdef456..." }, "attachments": [ { "name": "Validator Report", "uri": "ipfs://...", "mimeType": "application/pdf" } ] } ``` ## Feedback Templates ### Template 1: Service Quality Feedback ```json { "agentRegistry": "eip155:11155111:0x...", "agentId": 123, "clientAddress": "eip155:11155111:0x...", "createdAt": "2025-12-20T10:00:00Z", "feedbackType": "positive|mixed|negative", "score": 4, "reasoning": "[What you experienced, specific examples, overall impression]", "tags": ["tag1", "tag2"], "reproducible": true|false } ``` ### Template 2: Detailed Technical Feedback ```json { "agentRegistry": "eip155:11155111:0x...", "agentId": 123, "clientAddress": "eip155:11155111:0x...", "createdAt": "2025-12-20T10:00:00Z", "feedbackType": "mixed", "score": 3, "reasoning": "[Detailed technical analysis]", "tags": ["performance", "accuracy"], "attachments": [ { "name": "Benchmark Results", "uri": "ipfs://...", "mimeType": "application/json", "description": "Performance test results (1000 requests over 24 hours)" } ], "reproducible": true, "testEnvironment": { "network": "sepolia", "toolsUsed": ["postman", "k6"], "duration": "24h" } } ``` ### Template 3: Payment/Value Feedback ```json { "feedbackType": "positive", "score": 5, "reasoning": "Excellent value for money. Premium tier justifies cost.", "paymentProof": { "protocol": "x402", "amount": "10000000000000000", "currency": "ETH", "transactionHash": "0x..." }, "costEffectiveness": "excellent", "tags": ["good-value", "x402-compatible"] } ``` ## Common Mistakes to Avoid ### Mistake 1: Vague Feedback ❌ **Bad**: "Doesn't work" βœ… **Good**: "analyze\_wallet tool returns 500 error for wallets with >1000 transactions. Tested with 0x1234..." ### Mistake 2: No Evidence for Claims ❌ **Bad**: "Agent is a scam, stole my data" βœ… **Good**: Include proof (logs, transaction hashes, screenshots) ### Mistake 3: Emotional/Abusive Language ❌ **Bad**: "This garbage agent is a complete waste of time run by idiots" βœ… **Good**: "Agent did not meet advertised SLA (99% uptime). Measured 92% uptime over 7 days. Request refund." ### Mistake 4: Irrelevant Tags ❌ **Bad**: `["agent", "feedback", "blockchain", "ai", "test"]` βœ… **Good**: `["slow-response", "accurate-results", "expensive"]` ## FAQ **Q: Should I leave feedback after every interaction?** A: No, prioritize feedback for: * Exceptional experiences (very good or very bad) * First-time use of an agent * After major updates * When explicitly requested by agent owner **Q: Can I update feedback later?** A: Depends on implementation. 8004scan supports feedback updates via new transactions. **Q: What if agent owner disputes my feedback?** A: Provide evidence via attachments. On-chain feedback is immutable, but reputation systems may weight evidence. **Q: Should I give feedback for test interactions?** A: Yes, but use tags like `["test", "dev-environment"]` to distinguish from production use. ## Resources * [Feedback Standard](../02-feedback-standard.md) * [Validation Best Practices](validation-best-practices.md) * 8004scan Feedback UI *(coming soon)* --- --- url: /v1/docs/implementation/feedback-best-practices.md description: Practical guide for creating effective agent feedback --- ## Description Practical guide for creating effective agent feedback **Audience**: Agent users, developers, validators ## Overview This guide provides best practices for creating high-quality feedback on ERC-8004 agents, helping build trust and improve the ecosystem. **What You'll Learn**: * βœ… Write clear, actionable feedback * βœ… Provide effective evidence using attachments * βœ… Choose appropriate feedback types * βœ… Handle privacy and sensitive data * βœ… Use protocol-specific fields (A2A, MCP, x402) ## Feedback Principles ### 1. Be Specific and Actionable ❌ **Bad**: "Agent doesn't work" βœ… **Good**: ```json { "feedbackType": "negative", "score": 2, "reasoning": "Agent failed to analyze wallet 0x1234... Transaction parsing error at block 18500000. Expected JSON response but received HTML error page.", "reproducible": true } ``` **Why**: Specific feedback helps agent developers identify and fix issues. ### 2. Provide Evidence ❌ **Bad**: Trust me, it's broken βœ… **Good**: Include screenshots, logs, or API responses ```json { "feedbackType": "negative", "score": 2, "reasoning": "Agent returned error when analyzing wallet", "attachments": [ { "name": "Error Screenshot", "uri": "ipfs://bafkreiabc...", "mimeType": "image/png", "description": "Screenshot showing '500 Internal Server Error' at 2025-12-20 14:30 UTC" }, { "name": "Error Logs", "uri": "ipfs://bafkreixyz...", "mimeType": "application/json", "description": "Full API response logs with stack trace" } ] } ``` ### 3. Be Fair and Constructive ❌ **Bad**: "This agent is garbage" βœ… **Good**: ```json { "feedbackType": "mixed", "score": 3, "reasoning": "Agent successfully analyzed 80% of test cases (8/10). Failed on complex multi-sig transactions. Response time was excellent (~2s average). Recommend adding multi-sig support.", "tags": ["needs-improvement", "fast-response"] } ``` ## Feedback Type Guide ### Positive Feedback (score: 4-5) **When to Use**: * Agent performed as expected * Results were accurate * Response time was acceptable * Good user experience **Example**: ```json { "agentRegistry": "eip155:11155111:0x8004a6090Cd10A7288092483047B097295Fb8847", "agentId": 123, "clientAddress": "eip155:11155111:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7", "createdAt": "2025-12-20T10:00:00Z", "feedbackType": "positive", "score": 5, "reasoning": "Excellent blockchain analytics. Analyzed 1000+ transactions in under 5 seconds. Detected 3 suspicious patterns I missed manually. Highly recommend.", "tags": ["fast", "accurate", "recommended"] } ``` ### Mixed Feedback (score: 2-4) **When to Use**: * Agent works but has limitations * Some features good, others need improvement * Acceptable but not great **Example**: ```json { "feedbackType": "mixed", "score": 3, "reasoning": "Good for simple queries, but struggles with complex analysis. Free tier works well. Premium features overpriced at 0.1 ETH per report. UI is intuitive.", "tags": ["good-ui", "expensive", "limited-features"], "attachments": [ { "name": "Feature Comparison", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "description": "Comparison with similar agents showing price/feature gaps" } ] } ``` ### Negative Feedback (score: 0-2) **When to Use**: * Agent failed to deliver * Critical bugs or errors * Safety/security concerns * Misleading claims **Example**: ```json { "feedbackType": "negative", "score": 1, "reasoning": "Agent claimed '99% uptime' but was offline for 6 hours during critical market event. No refund offered despite x402 payment. Support unresponsive.", "tags": ["unreliable", "poor-support", "false-advertising"], "attachments": [ { "name": "Downtime Logs", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Ping logs showing 6-hour offline period (2025-12-15 08:00-14:00 UTC)" }, { "name": "Payment Receipt", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "x402 payment proof (0.05 ETH for 24h service)" } ] } ``` **Important**: Always provide evidence for negative feedback to prevent abuse. ## Scoring Guidelines | Score | Meaning | When to Use | | ----- | ----------------- | -------------------------------------------- | | **5** | Outstanding | Exceeded expectations, highly recommend | | **4** | Good | Met expectations, would use again | | **3** | Acceptable | Works but has issues, neutral recommendation | | **2** | Below Average | Significant problems, not recommended | | **1** | Poor | Failed to deliver, do not use | | **0** | Completely Failed | Agent non-functional or malicious | **Tips**: * Reserve 5β˜… for truly exceptional experiences * Use 3β˜… as baseline for "works as advertised" * Only use 0β˜… for serious issues (scams, malware, data breaches) ## Attachment Pattern Best Practices ### Supported File Types | Type | MIME Type | Use Case | Example | | ---------- | ----------------------------- | ---------------------------- | --------------------------- | | **PDF** | `application/pdf` | Audit reports, documentation | Security audit report | | **Images** | `image/png`, `image/jpeg` | Screenshots, diagrams | Error screenshots | | **JSON** | `application/json` | API responses, test results | Agent API response logs | | **Text** | `text/plain`, `text/markdown` | Logs, notes | Detailed test notes | | **CSV** | `text/csv` | Benchmark data | Performance benchmarks | | **Video** | `video/mp4`, `video/webm` | Screen recordings | Demo of bug reproduction | | **ZIP** | `application/zip` | Multiple files | Complete test suite results | ### Attachment Examples #### Example 1: Security Audit Report ```json { "reasoning": "Passed third-party security audit with 0 critical findings", "attachments": [ { "name": "Security Audit Report", "uri": "ipfs://bafkreifjv...", "mimeType": "application/pdf", "size": 2048000, "description": "Automated scan using Slither v0.9.6 + manual review by certified auditor. Scanned 5 smart contracts and 2 API endpoints. Report dated 2025-12-15.", "uploadedAt": "2025-12-16T10:00:00Z" } ] } ``` #### Example 2: Performance Benchmarks ```json { "reasoning": "Tested performance under load. Results show excellent scalability.", "attachments": [ { "name": "Benchmark Results", "uri": "ipfs://bafkreiabc...", "mimeType": "text/csv", "size": 50000, "description": "1000 API calls on Sepolia testnet. Average response time: 1.2s. 99.9% uptime over 7 days. Test environment: AWS t3.medium instance.", "uploadedAt": "2025-12-16T12:00:00Z" }, { "name": "Load Test Graph", "uri": "ipfs://bafkreixyz...", "mimeType": "image/png", "size": 150000, "description": "Response time vs concurrent requests graph. Shows linear scaling up to 100 concurrent users." } ] } ``` #### Example 3: Bug Reproduction ```json { "feedbackType": "negative", "score": 2, "reasoning": "Agent crashes when processing ERC-4337 account abstraction wallets", "attachments": [ { "name": "Bug Reproduction Steps", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "size": 5000, "description": "Step-by-step reproduction guide with test wallet address and transaction hash" }, { "name": "Error Video", "uri": "ipfs://bafkrei...", "mimeType": "video/mp4", "size": 5000000, "description": "Screen recording showing agent crash when analyzing wallet 0x1234... at timestamp 00:42" }, { "name": "API Logs", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "size": 20000, "description": "Complete API request/response logs showing 500 error with stack trace" } ] } ``` ### Attachment Upload Methods #### Method 1: IPFS Upload (Recommended) ```bash # Using IPFS CLI ipfs add security-audit.pdf # Returns: added QmXXX... security-audit.pdf # Using Pinata API curl -X POST "https://api.pinata.cloud/pinning/pinFileToIPFS" \ -H "Authorization: Bearer YOUR_JWT" \ -F "file=@security-audit.pdf" ``` **Attachment**: ```json { "name": "Security Audit Report", "uri": "ipfs://QmXXX...", "mimeType": "application/pdf" } ``` #### Method 2: Inline JSON (Small Data) For small datasets (<100KB), embed directly: ```json { "reasoning": "Benchmark results attached", "attachments": [ { "name": "Performance Metrics", "uri": "data:application/json;base64,eyJhdmdSZXNwb25zZVRpbWUiOjEuMiwicDk5IjoyLjV9", "mimeType": "application/json", "description": "Key metrics: avg 1.2s, p99 2.5s" } ] } ``` #### Method 3: HTTPS URL (Centralized but Fast) ```json { "name": "Test Results Dashboard", "uri": "https://example.com/test-results/agent-123-2025-12-20.html", "mimeType": "text/html", "description": "Interactive dashboard with real-time test results (requires login)" } ``` ⚠️ **Caution**: HTTPS URLs can change or disappear. Prefer IPFS for permanence. ## Protocol-Specific Fields ### A2A Protocol Feedback When providing feedback after A2A (Agent-to-Agent) interactions: ```json { "feedbackType": "positive", "score": 5, "reasoning": "Excellent A2A collaboration. Agent responded within SLA and provided structured data.", "a2aInteraction": { "requestId": "req-uuid-1234", "responseTime": 1.8, "skillsUsed": ["analytical_skills/data_analysis/blockchain_analysis"], "protocol": "A2A v0.3.0" }, "tags": ["a2a-compatible", "fast-response"] } ``` ### MCP Protocol Feedback For MCP tool/prompt feedback: ```json { "feedbackType": "positive", "score": 4, "reasoning": "MCP tools work well. analyze_wallet tool is accurate. summarize_trends prompt is helpful.", "mcpFeedback": { "toolsUsed": ["analyze_wallet", "detect_anomalies"], "promptsUsed": ["What are the risks?"], "serverVersion": "2025-06-18", "issues": ["analyze_wallet sometimes times out on large wallets"] } } ``` ### x402 Payment Feedback When using x402 payment protocol: ```json { "feedbackType": "positive", "score": 5, "reasoning": "Fair pricing via x402. Paid 0.01 ETH for premium analysis. Worth it.", "paymentProof": { "protocol": "x402", "amount": "10000000000000000", "currency": "ETH", "transactionHash": "0xabc123...", "chainId": 1, "timestamp": "2025-12-20T10:00:00Z" }, "costEffectiveness": "excellent" } ``` ## Privacy and Security ### DO Include βœ… General performance metrics βœ… Anonymized test data βœ… Public blockchain addresses (if relevant) βœ… Error messages (sanitized) βœ… Public API endpoints ### DO NOT Include ❌ Private keys or seed phrases ❌ API keys or access tokens ❌ Personal identifiable information (PII) ❌ Confidential business data ❌ Internal system details (if security-sensitive) **Example of Sanitization**: ```json // ❌ BAD { "reasoning": "API key sk-1234abcd exposed in logs" } // βœ… GOOD { "reasoning": "API credentials exposed in error response (redacted for security)", "attachments": [ { "name": "Sanitized Logs", "uri": "ipfs://...", "description": "Error logs with sensitive data redacted" } ] } ``` ## Feedback Authorization ### Anonymous Feedback ```json { "clientAddress": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7", "feedbackType": "positive", "score": 5, "reasoning": "Great agent!", "authorization": { "signature": "0xabc123...", "message": "I approve this feedback for agent 123 on 2025-12-20", "signer": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } } ``` ### Validator-Endorsed Feedback For feedback from trusted validators: ```json { "clientAddress": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7", "feedbackType": "positive", "score": 5, "reasoning": "Agent passed comprehensive security validation", "validatorEndorsement": { "validatorAddress": "eip155:1:0x1234...", "validatorTier": "platform", "endorsementType": "security-audit", "signature": "0xdef456..." }, "attachments": [ { "name": "Validator Report", "uri": "ipfs://...", "mimeType": "application/pdf" } ] } ``` ## Feedback Templates ### Template 1: Service Quality Feedback ```json { "agentRegistry": "eip155:11155111:0x...", "agentId": 123, "clientAddress": "eip155:11155111:0x...", "createdAt": "2025-12-20T10:00:00Z", "feedbackType": "positive|mixed|negative", "score": 4, "reasoning": "[What you experienced, specific examples, overall impression]", "tags": ["tag1", "tag2"], "reproducible": true|false } ``` ### Template 2: Detailed Technical Feedback ```json { "agentRegistry": "eip155:11155111:0x...", "agentId": 123, "clientAddress": "eip155:11155111:0x...", "createdAt": "2025-12-20T10:00:00Z", "feedbackType": "mixed", "score": 3, "reasoning": "[Detailed technical analysis]", "tags": ["performance", "accuracy"], "attachments": [ { "name": "Benchmark Results", "uri": "ipfs://...", "mimeType": "application/json", "description": "Performance test results (1000 requests over 24 hours)" } ], "reproducible": true, "testEnvironment": { "network": "sepolia", "toolsUsed": ["postman", "k6"], "duration": "24h" } } ``` ### Template 3: Payment/Value Feedback ```json { "feedbackType": "positive", "score": 5, "reasoning": "Excellent value for money. Premium tier justifies cost.", "paymentProof": { "protocol": "x402", "amount": "10000000000000000", "currency": "ETH", "transactionHash": "0x..." }, "costEffectiveness": "excellent", "tags": ["good-value", "x402-compatible"] } ``` ## Common Mistakes to Avoid ### Mistake 1: Vague Feedback ❌ **Bad**: "Doesn't work" βœ… **Good**: "analyze\_wallet tool returns 500 error for wallets with >1000 transactions. Tested with 0x1234..." ### Mistake 2: No Evidence for Claims ❌ **Bad**: "Agent is a scam, stole my data" βœ… **Good**: Include proof (logs, transaction hashes, screenshots) ### Mistake 3: Emotional/Abusive Language ❌ **Bad**: "This garbage agent is a complete waste of time run by idiots" βœ… **Good**: "Agent did not meet advertised SLA (99% uptime). Measured 92% uptime over 7 days. Request refund." ### Mistake 4: Irrelevant Tags ❌ **Bad**: `["agent", "feedback", "blockchain", "ai", "test"]` βœ… **Good**: `["slow-response", "accurate-results", "expensive"]` ## FAQ **Q: Should I leave feedback after every interaction?** A: No, prioritize feedback for: * Exceptional experiences (very good or very bad) * First-time use of an agent * After major updates * When explicitly requested by agent owner **Q: Can I update feedback later?** A: Depends on implementation. 8004scan supports feedback updates via new transactions. **Q: What if agent owner disputes my feedback?** A: Provide evidence via attachments. On-chain feedback is immutable, but reputation systems may weight evidence. **Q: Should I give feedback for test interactions?** A: Yes, but use tags like `["test", "dev-environment"]` to distinguish from production use. ## Resources * [Feedback Standard](../02-feedback-standard.md) * [Validation Best Practices](validation-best-practices.md) * 8004scan Feedback UI *(coming soon)* --- --- url: /docs/02-feedback-standard.md description: Recommended offchain data format for ERC-8004 feedback records --- ## Description Recommended offchain data profile for ERC-8004 feedback records This document provides implementation-agnostic guidance for structuring feedback data referenced by the `feedbackURI` field in ERC-8004 Reputation Registry contracts. > **Version Info**: This document describes the **v2.0 specification** (January 2026). For previous versions: > > * [v1.x documentation](/v1/docs/02-feedback-standard) > * [pre-v1 (legacy) documentation](/legacy-pre-v1/docs/02-feedback-standard) ## Document Purpose This profile document offers **practical, non-normative recommendations** for feedback data formats used with ERC-8004 Reputation Registries, based on real-world usage patterns and community feedback. ## Relationship to EIP-8004 > **Important**: This is **not** part of the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification. **Official EIP-8004** defines: * Reputation Registry smart contract interface * Onchain fields: `value`, `valueDecimals`, `tag1`, `tag2`, `endpoint`, `feedbackURI`, `feedbackHash` * The `feedbackURI` field is OPTIONAL > **v2.0 Breaking Change**: The `score` field (uint8, 0-100) has been replaced by `value` (int128) + `valueDecimals` (uint8, 0-18). See [Key Changes in v2.0](#key-changes-in-v20-january-2026) for details. **This profile** suggests: * Offchain JSON structure for feedback data * Protocol-specific field patterns (A2A, MCP) * Evidence attachment guidelines * Payment proof integration (x402) The official EIP makes `feedbackURI` **optional**. When provided, this profile recommends patterns for its content. ### Key Changes in v2.0 (January 2026) | Field | v1.x | v2.0 | | --------------------- | ---------------------- | ------------------------------------------------ | | **Score/Value** | `score` (uint8, 0-100) | `value` (int128) + `valueDecimals` (uint8, 0-18) | | **Negative Rating** | Not supported | Supported (value can be negative) | | **Decimal Precision** | Integer only | Up to 18 decimal places | | **Range** | 0-100 | Unlimited (int128) | > **Why v2.0?** The v1.x `score` field was limited to 0-100 integer values, which prevented many useful metric types. v2.0 introduces `value` (int128) + `valueDecimals` (uint8) which supports: > > * **Arbitrary metrics**: Response time (ms), uptime (%), revenues ($), block freshness, etc. > * **Decimal precision**: 99.77% uptime β†’ `value=9977, valueDecimals=2` > * **Large values**: Response time 1100ms β†’ `value=1100, valueDecimals=0` > * **Negative feedback**: Disputes, fraud reports (e.g., -5 for bad service) > * **Flexible rating scales**: 5-star, 10-point, percentage, or custom systems ### Key Changes in v1.x (vs pre-v1) | Field | pre-v1 (legacy) | v1.x | | ----------------- | --------------- | ------------- | | **Tag Types** | `bytes32` | `string` | | **URI Naming** | `feedbackUri` | `feedbackURI` | | **FeedbackAuth** | Required | Removed | | **Endpoint** | β€” | NEW | | **feedbackIndex** | Calculated | From event | See [migration guide](implementation/migration-v0-4-to-v1-0.md) for upgrading from pre-v1 (legacy). See [v1.x to v2.0 migration guide](implementation/migration-v1-to-v2.md) for upgrading from v1.x. ## Terminology This document follows conventions defined in [Conventions](00-CONVENTIONS.md). For attachment file patterns, see [Attachment Pattern Standard](extensions/04-attachment-pattern-standard.md). ## Intended Audience * Service clients giving feedback * Registry implementers building indexers and explorers ## Table of Contents 1. [Overview](#overview) 2. [Recommended Feedback Profile](#recommended-feedback-profile) 3. [Attachment Pattern](#attachment-pattern) 4. [Protocol-Specific Fields](#protocol-specific-fields) 5. [Payment Proof Integration](#payment-proof-integration) 6. [Authorization (Deprecated)](#authorization-deprecated-in-v11) 7. [Examples](#examples) 8. [Best Practices](#best-practices) ## Overview ### Onchain vs Offchain Data **Onchain** (Reputation Registry contract): * `value` (int128) - REQUIRED - Feedback value (can be negative) * `valueDecimals` (uint8, 0-18) - REQUIRED - Decimal precision for value * `tag1`, `tag2` (string) - OPTIONAL (direct strings, no encoding) * `endpoint` (string) - OPTIONAL, specifies the service endpoint * `feedbackURI` (string) - OPTIONAL * `feedbackHash` (bytes32) - OPTIONAL * `feedbackIndex` (uint64) - **From event emission** (no longer calculated) > **v2.0 Note**: The actual rating is calculated as `value / 10^valueDecimals`. For example: > > * `value=5`, `valueDecimals=0` β†’ Rating: 5 (5-star rating) > * `value=450`, `valueDecimals=2` β†’ Rating: 4.50 (4.5 out of 5) > * `value=-100`, `valueDecimals=0` β†’ Rating: -100 (negative feedback) **Onchain Events** (for indexers): * `NewFeedback`: `agentId` (indexed), `clientAddress` (indexed), `feedbackIndex`, `value`, `valueDecimals`, `indexedTag1` (indexed), `tag1`, `tag2`, `endpoint`, `feedbackURI`, `feedbackHash` * `FeedbackRevoked`: `agentId` (indexed), `clientAddress` (indexed), `feedbackIndex` (indexed) * `ResponseAppended`: `agentId` (indexed), `clientAddress` (indexed), `feedbackIndex`, `responder` (indexed), `responseURI`, `responseHash` > **Note for Indexers**: The `indexed` parameters can be efficiently filtered in event queries. Non-indexed parameters require full log scanning. > > **Important (v1.1.1 update)**: `tag1` is now emitted **twice** in `NewFeedback`: > > * `indexedTag1` (indexed): Topic-hashed for efficient filtering > * `tag1` (non-indexed): Actual string value for direct access > > This allows both efficient filtering AND direct value retrieval without decoding. **Offchain** (referenced by `feedbackUri`): * Detailed feedback context and reasoning * Proof of payment (x402 protocol) * Protocol-specific fields (A2A/MCP) * Evidence attachments * Custom extensions > **Non-normative**: The `feedbackUri` field is **optional** per EIP-8004. However, providing rich offchain data improves trust, transparency, and enables better discovery and dispute resolution. ## Recommended Feedback Profile ### Suggested Schema ```jsonc { // ============ MUST FIELDS (per official spec) ============ "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2026-01-20T12:00:00Z", // v2.0: value + valueDecimals (replaces score) "value": "5", // BigDecimal as string (can be negative) "valueDecimals": 0, // Decimal precision (0-18) // ============ ALL OPTIONAL FIELDS (per official spec) ============ "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.agent.example.com/v1", // A2A / OASF fields "skill": "analytical_skills/data_analysis", // as-defined-by-A2A-or-OASF "domain": "technology/blockchain", // as-defined-by-OASF (NEW in v1.1) "context": "Analyzed blockchain transaction data for portfolio optimization", "task": "Generate daily analytics report with recommendations", // MCP fields "capability": "tools", // prompts, resources, tools, or completions "name": "blockchain_analyzer", // x402 payment proof "proofOfPayment": { "fromAddress": "0x742d35Cc...", "toAddress": "0x8004...", "chainId": "84532", "txHash": "0xabc123..." }, // ============ BEST PRACTICES EXTENSIONS (this profile) ============ "reasoning": "Excellent portfolio analysis service.", "attachments": [ { "name": "Service Receipt", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 50000 } ], // Other custom fields " ... ": { " ... " } } ``` > \[!NOTE] > This schema follows the official EIP-8004 spec structure. Fields marked "MUST" are required by the spec; fields marked "OPTIONAL" are defined by the spec but not required. "Best Practices Extensions" are additional recommendations from this profile. > > **v2.0 Changes**: > > * The `score` field has been replaced by `value` + `valueDecimals` > * `value` is a BigDecimal string that can be negative > * The `feedbackAuth` field was removed in v1.x (feedback is permissionless) ### Recommended Fields | Field | Type | Constraints | Description | | --------------- | ------ | ---------------------- | ---------------------------------------------------- | | `agentRegistry` | string | CAIP-10 format | Agent's identity registry address | | `agentId` | number | uint128, β‰₯ 0 | Agent token ID | | `clientAddress` | string | CAIP-10 format | Client's wallet address | | `createdAt` | string | ISO 8601 UTC | Feedback creation timestamp | | `value` | string | BigDecimal (int128) | Feedback value (can be negative, must match onchain) | | `valueDecimals` | number | 0–18 inclusive (uint8) | Decimal precision for value | **CAIP Format References**: * **CAIP-10** (Contract Address): `eip155:84532:0x8004C269...` β†’ [Conventions](00-CONVENTIONS.md#caip-10-for-contract-addresses) * **CAIP-10** (Account ID): `eip155:84532:0x742d35Cc...` β†’ [Conventions](00-CONVENTIONS.md#caip-10-account-address-format) ### Recommended Optional Fields | Field | Type | Description | | ----------- | ------ | --------------------------------------------------- | | `reasoning` | string | Human-readable explanation of the feedback score | | `tag1` | string | Primary category tag (direct string, not encoded) | | `tag2` | string | Secondary category tag (direct string) | | `endpoint` | string | Service endpoint used for interaction (NEW in v1.1) | > **Note**: In v1.1, `tag1` and `tag2` are **direct strings** on-chain. No encoding/decoding needed. The `endpoint` field is optional but recommended for tracking which specific service endpoint was used. ## Attachment Pattern ### Overview The attachment pattern allows clients to provide evidence, receipts, or supporting documents with their feedback. **For complete attachment schema and guidelines**, see [Attachment Pattern Guidelines](extensions/04-attachment-pattern-standard.md). ### Quick Reference Attachments use the following structure: ```typescript interface AttachmentFile { name: string; // Display name (required) uri: string; // File location (required) mimeType: string; // MIME type (required) size: number; // File size in bytes (required) description?: string; // Optional context uploadedAt?: string; // Optional timestamp (ISO 8601 UTC) } ``` **Example**: ```json { "attachments": [ { "name": "Service Receipt", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 50000, "description": "Invoice and deliverables", "uploadedAt": "2025-12-20T15:00:00Z" } ] } ``` ### Common Use Cases **1. Service Receipts**: Proof of service completion **2. Communication Logs**: Chat transcripts showing responsiveness **3. Work Product**: Deliverables and analysis reports **4. Screenshots**: Visual evidence of results **Supported File Types**: PDFs, images, videos, JSON, CSV, text files, and more. See [Attachment Pattern Guidelines](extensions/04-attachment-pattern-standard.md) for: * Detailed field specifications * Security considerations * Best practices * Implementation requirements ```json { "name": "Analysis Report", "uri": "ipfs://QmZzz...", "mimeType": "application/pdf", "description": "Final deliverable - 50-page portfolio analysis report" } ``` ### 4. Screenshots/Evidence ```json { "name": "Service Screenshot", "uri": "ipfs://QmAaa...", "mimeType": "image/png", "description": "Screenshot showing successful task completion at 10:45 UTC" } ``` ### Supported File Types * βœ… Documents: PDF, Word, Markdown, Text * βœ… Images: PNG, JPEG, WebP, GIF * βœ… Data: JSON, CSV, XML * βœ… Archives: ZIP (for multiple files) * βœ… Any other format (stored as-is) ## Protocol-Specific Fields ### A2A / OASF Protocol Fields For feedback on **Agent-to-Agent (A2A)** interactions or **OASF** taxonomy: | Field | Type | Example | Description | | --------- | ------ | ----------------------------------- | -------------------------- | | `skill` | string | `"analytical_skills/data_analysis"` | A2A or OASF skill taxonomy | | `domain` | string | `"technology/blockchain"` | OASF domain taxonomy (NEW) | | `context` | string | `"Analyzed blockchain data"` | Task context (A2A) | | `task` | string | `"Generate analytics report"` | Specific task (A2A) | > \[!NOTE] > **v1.1 Change**: The `skill` field now accepts both A2A and OASF skill slugs. The `domain` field was added for OASF domain taxonomy. **Taxonomy References**: * [OASF Skills](https://schema.oasf.outshift.com/0.8.0/skills) * [OASF Domains](https://schema.oasf.outshift.com/0.8.0/domains) ### MCP Protocol Fields For feedback on **Model Context Protocol (MCP)** capabilities: | Field | Type | Values | Description | | ------------ | ------ | ---------------------------------------------- | -------------------------------- | | `capability` | string | `prompts`, `resources`, `tools`, `completions` | MCP capability type | | `name` | string | `"blockchain_analyzer"` | Name of the tool/resource/prompt | ### Custom Extensions The standard supports arbitrary custom fields: ```json { "value": "95", "valueDecimals": 0, // ... standard fields ... // Custom breakdown "rating_breakdown": { "speed": 95, "accuracy": 100, "communication": 90 }, // Custom identifiers "interaction_id": "uuid-v4", "session_id": "session-123", // Custom metadata "service_duration_hours": 2.5, "revisions_requested": 1 } ``` ## Payment Proof Integration ### x402 Protocol Support > \[!NOTE] > **v1.1 Change**: The field name changed from `proof_of_payment` (snake\_case) to `proofOfPayment` (camelCase) in January 2026 for JSON naming consistency. The `proofOfPayment` field integrates with the x402 payment protocol for agents. ```typescript // Official EIP-8004 spec fields interface ProofOfPayment { fromAddress: string; // Payer address (0x...) toAddress: string; // Payee address (0x...) chainId: string; // Chain ID as string (e.g., "1", "84532") txHash: string; // Transaction hash (0x...) // Best practices extensions (this profile) amount?: string; // Payment amount (wei/smallest unit) currency?: string; // Currency symbol (e.g., "ETH", "USDC") protocol?: string; // Payment protocol (e.g., "x402") timestamp?: string; // Payment timestamp (ISO 8601) } ``` ### Example: ETH Payment ```json { "proofOfPayment": { "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "toAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "chainId": "84532", "txHash": "0xabc123..." } } ``` ### Example: ETH Payment with Extensions ```json { "proofOfPayment": { "fromAddress": "0x742d35Cc...", "toAddress": "0x8004...", "chainId": "84532", "txHash": "0xabc123...", "amount": "100000000000000000", "currency": "ETH", "protocol": "x402" } } ``` ### Example: SOL Payment (Solana) ```json { "proofOfPayment": { "fromAddress": "D9bMDMbJungXQrE8n6ZsM3r6ZQLFTzygmsQL7yzGMDHw", "toAddress": "2KmHw8VbShuz9xfj3ecEjBM5nPKR5BcYHRDSFfK1286t", "chainId": "501", "txSignature": "5piJm888s7beTTrB9JuCR5WFvNxXHN78C9ifGEokTucoQy5mb6bKg3e6Fkiv8RznZG2NmzENBWUru5yUGbqMiTMp", "amount": "1000000000", "currency": "SOL", "decimals": 9 } } ``` > Note: Solana uses `txSignature` (base58, 87-88 chars) instead of `txHash`. Amount is in lamports (1 SOL = 10^9 lamports). See [Solana Chain Support Extension](extensions/solana-support.md) for details. ## Authorization (Deprecated in v1.1) > ⚠️ **DEPRECATED**: The `feedbackAuth` field and pre-authorization flow have been **removed in v1.1**. > > In pre-v1 (legacy), feedback required cryptographic authorization from agents. In v1.1, **anyone can submit feedback** directly without pre-approval. Spam/Sybil protection now relies on off-chain filtering and reputation scoring. See [migration guide](implementation/migration-v0-4-to-v1-0.md) if you're upgrading from pre-v1 (legacy). ## Examples ### Example 1: Simple Feedback (5-star rating) ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2026-01-20T12:00:00Z", "value": "5", "valueDecimals": 0, "reasoning": "Great DeFi analytics agent. Quick response time and accurate insights.", "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.example.com/analytics/v1" } ``` ### Example 2: Detailed A2A Feedback with Payment Proof ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 45, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2026-01-20T14:30:00Z", "value": "4.8", "valueDecimals": 1, "reasoning": "Exceptional market analysis service. Provided comprehensive report with actionable insights.", "tag1": "trading", "tag2": "research", "skill": "analytical_skills/market_analysis", "context": "Analyzed crypto market trends for Q1 2026", "task": "Generate comprehensive market analysis report with predictions", "proofOfPayment": { "fromAddress": "eip155:84532:0x742d35Cc...", "toAddress": "eip155:84532:0x8004...", "chainId": 84532, "txHash": "0x789abc...", "amount": "500000000000000000", "currency": "ETH", "protocol": "x402" }, "attachments": [ { "name": "Market Analysis Report", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 2048000, "description": "75-page comprehensive market analysis with charts and predictions", "uploadedAt": "2026-01-20T14:00:00Z" }, { "name": "Raw Data", "uri": "ipfs://QmYyy...", "mimeType": "text/csv", "size": 500000, "description": "Historical price data used for analysis", "uploadedAt": "2026-01-20T14:00:00Z" } ], "rating_breakdown": { "depth": 100, "accuracy": 100, "timeliness": 95, "presentation": 100 }, "interaction_id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### Example 3: MCP Tool Feedback ```json { "agentRegistry": "eip155:11155111:0x8004...", "agentId": 78, "clientAddress": "eip155:11155111:0x123...", "createdAt": "2026-01-20T16:00:00Z", "value": "4", "valueDecimals": 0, "reasoning": "Blockchain analyzer MCP tool worked well. Accurate transaction parsing.", "tag1": "mcp", "tag2": "tools", "capability": "tools", "name": "blockchain_transaction_parser", "rating_breakdown": { "accuracy": 95, "speed": 85, "reliability": 90 } } ``` ### Example 4: Negative Feedback (v2.0 feature) ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 99, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2026-01-20T18:00:00Z", "value": "-2", "valueDecimals": 0, "reasoning": "Service was unresponsive for 48 hours. No deliverables provided despite payment.", "tag1": "unresponsive", "tag2": "dispute", "attachments": [ { "name": "Payment Receipt", "uri": "ipfs://QmZzz...", "mimeType": "application/pdf", "size": 25000, "description": "Proof of payment with no corresponding service" } ] } ``` > **v2.0 Feature**: Negative `value` allows explicit negative feedback. This is useful for dispute resolution and fraud reporting. ## Best Practices ### 1. Always Provide Reasoning **❌ Bad**: ```json { "value": "4", "valueDecimals": 0 } ``` **βœ… Good**: ```json { "value": "4", "valueDecimals": 0, "reasoning": "Good service overall. Response time was a bit slow (2 hours), but final deliverable quality was excellent." } ``` ### 2. Include Evidence for Disputes For high-stakes or high-value interactions, include attachments: ```json { "value": "5", "valueDecimals": 0, "reasoning": "...", "attachments": [ { "name": "Service Receipt", "uri": "ipfs://...", "mimeType": "application/pdf", "description": "Official receipt showing completed deliverables" } ] } ``` ### 3. Use Protocol-Specific Fields If using A2A, OASF, or MCP, include relevant fields for better discoverability: **A2A / OASF Example**: ```json { "value": "4.5", "valueDecimals": 1, "tag1": "defi", "tag2": "analytics", "skill": "analytical_skills/data_analysis/blockchain_analysis", "domain": "technology/blockchain", "context": "Analyzed blockchain transaction patterns for portfolio optimization" } ``` **MCP Example**: ```json { "value": "4", "valueDecimals": 0, "tag1": "mcp", "tag2": "tools", "capability": "tools", "name": "blockchain_analyzer", "context": "Used MCP tools capability for blockchain data analysis" } ``` ### 4. Include Payment Proof for x402 For agents supporting x402 payment protocol: ```json { "value": "5", "valueDecimals": 0, "proofOfPayment": { "txHash": "0x...", "amount": "100000000000000000", "currency": "ETH" } } ``` ### 5. Use CAIP Formats for Addresses **❌ Bad**: ```json { "clientAddress": "0x742d35Cc..." } ``` **βœ… Good**: ```json { "clientAddress": "eip155:84532:0x742d35Cc..." } ``` ### 6. Include Endpoint Information Always include the `endpoint` field to track which service endpoint was used: **❌ Missing context**: ```json { "value": "4.5", "valueDecimals": 1, "tag1": "defi" } ``` **βœ… Good - with endpoint**: ```json { "value": "4.5", "valueDecimals": 1, "tag1": "defi", "endpoint": "https://api.agent.example.com/v1", "reasoning": "Used the v1 API endpoint. Fast response and accurate results." } ``` This helps distinguish feedback for different versions or deployments of the same agent. ### 7. Use String Tags Directly Tags are direct strings (since v1.x), not encoded bytes32: **❌ Old pre-v1 format (deprecated)**: ```json { "tag1": "6465666900000000000000000000000000000000000000000000000000000000", "tag2": "616e616c7974696373000000000000000000000000000000000000000000000000" } ``` **βœ… v1.x/v2.0 format**: ```json { "tag1": "defi", "tag2": "analytics" } ``` ### 8. Timestamp Everything ```json { "createdAt": "2025-12-20T12:00:00Z", "proofOfPayment": { "timestamp": "2025-12-20T11:45:00Z" }, "attachments": [ { "uploadedAt": "2025-12-20T11:50:00Z" } ] } ``` ### 9. Complete v2.0 Best Practice Example Here's a comprehensive example following all v2.0 best practices: ```json { // Core required fields "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2026-01-20T12:00:00Z", // v2.0: value + valueDecimals (replaces score) "value": "4.75", "valueDecimals": 2, // Tags and endpoint "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.agent.example.com/v2", // Human context "reasoning": "Excellent DeFi analytics service. Used the v2 API which provided faster response times. The portfolio optimization recommendations were accurate and well-explained.", // Protocol-specific fields (OASF) "skill": "analytical_skills/data_analysis/blockchain_analysis", "domain": "finance_and_business/finance", "context": "Portfolio optimization for DeFi positions across multiple chains", // Payment proof (x402) "proofOfPayment": { "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "toAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "chainId": "84532", "txHash": "0xabc123...", "amount": "100000000000000000", "currency": "ETH", "timestamp": "2026-01-20T11:45:00Z" }, // Evidence attachments "attachments": [ { "name": "Analysis Report", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 250000, "description": "Full 50-page portfolio analysis with recommendations", "uploadedAt": "2026-01-20T11:50:00Z" }, { "name": "Service Receipt", "uri": "ipfs://QmYyy...", "mimeType": "application/pdf", "size": 50000, "description": "Invoice and proof of deliverables", "uploadedAt": "2026-01-20T11:55:00Z" } ] } ``` **Why this example follows best practices**: * βœ… Uses `value` + `valueDecimals` (v2.0 format) * βœ… Uses CAIP-10 format for addresses * βœ… Includes `endpoint` to track API version used * βœ… Uses direct string tags (not hex-encoded) * βœ… Provides detailed `reasoning` * βœ… Includes protocol-specific fields (`skill`, `domain`) * βœ… Has payment proof with full details * βœ… Includes evidence attachments * βœ… All timestamps in ISO 8601 UTC format ## FAQ ### Q: How do I handle feedback revocation or deletion? **A**: Use the `FeedbackRevoked` event to mark feedback as deleted (immutability-safe approach). **Event structure**: * `FeedbackRevoked(agentId indexed, clientAddress indexed, feedbackIndex indexed)` **Indexer handling**: * Track `FeedbackRevoked` events * Mark feedback as deleted (don't remove it) * Exclude revoked feedback from reputation calculations * Show revocation status in UI ("This feedback was revoked") **Off-chain data**: Archive revoked feedback but don't delete URIs (preserves immutability) *** ### Q: How do I efficiently index and search large feedback volumes? **A**: Leverage the indexed event parameters for optimized queries. **NewFeedback event indexed parameters** (v2.0): * `agentId` (indexed) - Query by agent * `clientAddress` (indexed) - Query by reviewer * `indexedTag1` (indexed) - Filter by tag efficiently (topic hash) **Non-indexed parameters**: * `feedbackIndex` - Sequential ordering * `value`, `valueDecimals` - Feedback rating * `tag1`, `tag2` - Actual tag values * `endpoint`, `feedbackURI`, `feedbackHash` **Optimization strategies**: 1. **Use indexed parameters** for efficient filtering by agent, client, or tag 2. **Aggregate in time windows**: Cache averages per (agentId, tag) per time period 3. **Use feedbackIndex for pagination**: Sequential ordering allows efficient range queries 4. **Separate hot/cold data**: Recent feedback in fast index, historical in archive *** ### Q: What's the relationship between value and valueDecimals? **A**: The actual rating is calculated as `value / 10^valueDecimals`. **Examples**: | value | valueDecimals | Actual Rating | Use Case | | ----- | ------------- | ------------- | ----------------- | | 5 | 0 | 5 | 5-star rating | | 45 | 1 | 4.5 | 4.5 out of 5 | | 475 | 2 | 4.75 | High precision | | -2 | 0 | -2 | Negative feedback | | 100 | 0 | 100 | Percentage (100%) | **Recommended scales**: * **5-star**: `valueDecimals=0`, `value` in range \[-5, 5] * **10-point**: `valueDecimals=0`, `value` in range \[0, 10] * **Percentage**: `valueDecimals=0`, `value` in range \[0, 100] * **Decimal precision**: `valueDecimals=1-2` for 4.5, 4.75 style ratings *** ### Q: What metric types can I use with tag1? **A**: The `tag1` field combined with `value`/`valueDecimals` supports various metric types beyond simple ratings: | tag1 (Metric) | Description | Example value | valueDecimals | Actual Value | | -------------------- | ------------------------- | ------------- | ------------- | ------------------ | | `reachable` | Is endpoint reachable? | 1 | 0 | 1 (binary: 0 or 1) | | `ownerVerified` | Endpoint ownership proof | 1 | 0 | 1 (binary: 0 or 1) | | `starred` | Quality rating | 85 | 0 | 85 (0-100 scale) | | `uptime` | Endpoint uptime % | 9977 | 2 | 99.77% | | `responseTime` | Response time in ms | 560 | 0 | 560 ms | | `successRate` | Request success rate % | 9950 | 2 | 99.50% | | `blocktimeFreshness` | Block delay (# of blocks) | 4 | 0 | 4 blocks | | `correctness` | Response correctness | 1 | 0 | 1 (binary: 0 or 1) | | `revenues` | Cumulative revenues ($) | 1100 | 0 | $1100 | **Key insight**: Since Solidity doesn't support floating-point numbers, `valueDecimals` lets you represent decimals as integers: * `"30"` β†’ `value=30, valueDecimals=0` β†’ Actual: 30 * `"30.73"` β†’ `value=3073, valueDecimals=2` β†’ Actual: 30.73 * `"99.77%"` β†’ `value=9977, valueDecimals=2` β†’ Actual: 99.77 *** ## See Also * [Validation Standard](03-validation-standard.md) - Validation Registry offchain data format * [Agent Metadata Standard](01-agent-metadata-standard.md) - AgentURI metadata format * [Feedback Best Practices](implementation/feedback-best-practices.md) - Detailed implementation guide * [Sources & References](reference/sources.md) - Data sources and methodology **Official EIP-8004 Specification**: --- --- url: /legacy-pre-v1/docs/02-feedback-standard.md description: Recommended offchain data format for ERC-8004 feedback records --- ## Description Recommended offchain data profile for ERC-8004 feedback records This document provides implementation-agnostic guidance for structuring feedback data referenced by the `feedbackUri` field in ERC-8004 Reputation Registry contracts. ## Document Purpose This profile document offers **practical, non-normative recommendations** for feedback data formats used with ERC-8004 Reputation Registries, based on real-world usage patterns and community feedback. ## Relationship to EIP-8004 > **Important**: This is **not** part of the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification. **Official EIP-8004** defines: * Reputation Registry smart contract interface * Onchain fields: `score`, `tag1`, `tag2`, `feedbackUri`, `feedbackHash` * The `feedbackUri` field is OPTIONAL **This profile** suggests: * Offchain JSON structure for feedback data * Protocol-specific field patterns (A2A, MCP) * Evidence attachment guidelines * Payment proof integration (x402) The official EIP makes `feedbackUri` **optional**. When provided, this profile recommends patterns for its content. ## Terminology This document follows conventions defined in [Conventions](00-CONVENTIONS.md), including: * **RFC 2119 keywords**: MUST, SHOULD, MAY * **Field types**: string, number, boolean, object, array * **CAIP formats**: CAIP-2 for blockchain IDs, CAIP-10 for addresses * **Timestamps**: ISO 8601 format in UTC For attachment file patterns, see [Attachment Pattern Guidelines](04-attachment-pattern-standard.md). ## Intended Audience * **Service Clients**: Users giving feedback after agent interactions * **Agent Developers**: Implementing feedback authorization * **Registry Implementers**: Building Reputation Registry contracts and indexers * **Explorer Developers**: Parsing and displaying feedback data ## Table of Contents 1. [Overview](#overview) 2. [Recommended Feedback Profile](#recommended-feedback-profile) 3. [Attachment Pattern](#attachment-pattern) 4. [Protocol-Specific Fields](#protocol-specific-fields) 5. [Payment Proof Integration](#payment-proof-integration) 6. [Feedback Authorization](#feedback-authorization) 7. [Examples](#examples) 8. [Best Practices](#best-practices) ## Overview ### Onchain vs Offchain Data **Onchain** (Reputation Registry contract): * `score` (uint8, 0-100) - REQUIRED * `tag1`, `tag2` (bytes32) - OPTIONAL * `feedbackUri` (string) - OPTIONAL * `feedbackHash` (bytes32) - OPTIONAL * `feedbackIndex` (uint64) - Auto-assigned, **1-indexed** (starts from 1, not 0) **Onchain Events** (for indexers): * `NewFeedback`: `agentId` (indexed), `clientAddress` (indexed), `score`, `tag1` (indexed), `tag2`, `feedbackUri`, `feedbackHash` * `FeedbackRevoked`: `agentId` (indexed), `clientAddress` (indexed), `feedbackIndex` (indexed) * `ResponseAppended`: `agentId` (indexed), `clientAddress` (indexed), `feedbackIndex`, `responder` (indexed), `responseUri`, `responseHash` > **Note for Indexers**: The `indexed` parameters can be efficiently filtered in event queries. Non-indexed parameters require full log scanning. **Offchain** (referenced by `feedbackUri`): * Detailed feedback context and reasoning * Proof of payment (x402 protocol) * Protocol-specific fields (A2A/MCP) * Evidence attachments * Custom extensions > **Non-normative**: The `feedbackUri` field is **optional** per EIP-8004. However, providing rich offchain data improves trust, transparency, and enables better discovery and dispute resolution. ## Recommended Feedback Profile ### Suggested Schema ```json { // ============ REQUIRED FIELDS ============ "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "feedbackAuth": "0x...", "score": 100, // ============ RECOMMENDED FIELDS ============ "reasoning": "Excellent portfolio analysis service. Fast, accurate, and professional communication.", "tag1": "defi", "tag2": "analytics", // ============ PROTOCOL-SPECIFIC FIELDS (OPTIONAL) ============ // A2A Protocol fields "skill": "analytical_skills/data_analysis", "context": "Analyzed blockchain transaction data for portfolio optimization", "task": "Generate daily analytics report with recommendations", // MCP Protocol fields "capability": "tools", "name": "blockchain_analyzer", // ============ PAYMENT PROOF (OPTIONAL) ============ "proof_of_payment": { "fromAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "toAddress": "eip155:84532:0x8004...", "chainId": 84532, "txHash": "0xabc123...", "amount": "100000000000000000", "currency": "ETH", "protocol": "x402" }, // ============ ATTACHMENTS (OPTIONAL) ============ "attachments": [ { "name": "Service Receipt", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 50000, "description": "Detailed service receipt with deliverables", "uploadedAt": "2025-12-20T11:50:00Z" } ], // ============ CUSTOM EXTENSIONS (OPTIONAL) ============ "rating_breakdown": { "speed": 95, "accuracy": 100, "communication": 90, "value": 100 }, "interaction_id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### Recommended Fields | Field | Type | Constraints | Description | | --------------- | ------ | ------------------------------- | ------------------------------------------------- | | `agentRegistry` | string | CAIP-10 format | Agent's identity registry address | | `agentId` | number | uint256, β‰₯ 0 | Agent token ID | | `clientAddress` | string | CAIP-10 format | Client's wallet address | | `createdAt` | string | ISO 8601 UTC | Feedback creation timestamp | | `feedbackAuth` | string | hex (0x...) | Signature from agent authorizing feedback | | `score` | number | 0–100 inclusive (uint8 onchain) | Overall feedback score (must match onchain value) | **CAIP Format References**: * **CAIP-10** (Contract Address): `eip155:84532:0x8004C269...` β†’ [Conventions](00-CONVENTIONS.md#caip-10-for-contract-addresses) * **CAIP-10** (Account ID): `eip155:84532:0x742d35Cc...` β†’ [Conventions](00-CONVENTIONS.md#caip-10-account-address-format) ### Optional Fields | Field | Type | Description | | ----------- | ------ | --------------------------------------------------------------- | | `reasoning` | string | Human-readable explanation of the feedback score | | `tag1` | string | Primary category tag (converted to bytes32 for onchain storage) | | `tag2` | string | Secondary category tag (converted to bytes32 for onchain) | > **Note**: The `tag1` and `tag2` fields are stored as `bytes32` onchain in the ReputationRegistry contract. When providing these fields in the offchain JSON, use human-readable strings. The indexer/frontend is responsible for converting between string and bytes32 formats. ## Attachment Pattern ### Overview The attachment pattern allows clients to provide evidence, receipts, or supporting documents with their feedback. **For complete attachment schema and guidelines**, see [Attachment Pattern Guidelines](04-attachment-pattern-standard.md). ### Quick Reference Attachments use the following structure: ```typescript interface AttachmentFile { name: string; // Display name (required) uri: string; // File location (required) mimeType: string; // MIME type (required) size: number; // File size in bytes (required) description?: string; // Optional context uploadedAt?: string; // Optional timestamp (ISO 8601 UTC) } ``` **Example**: ```json { "attachments": [ { "name": "Service Receipt", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 50000, "description": "Invoice and deliverables", "uploadedAt": "2025-12-20T15:00:00Z" } ] } ``` ### Common Use Cases **1. Service Receipts**: Proof of service completion **2. Communication Logs**: Chat transcripts showing responsiveness **3. Work Product**: Deliverables and analysis reports **4. Screenshots**: Visual evidence of results **Supported File Types**: PDFs, images, videos, JSON, CSV, text files, and more. See [Attachment Pattern Guidelines](04-attachment-pattern-standard.md) for: * Detailed field specifications * Security considerations * Best practices * Implementation requirements ```json { "name": "Analysis Report", "uri": "ipfs://QmZzz...", "mimeType": "application/pdf", "description": "Final deliverable - 50-page portfolio analysis report" } ``` ### 4. Screenshots/Evidence ```json { "name": "Service Screenshot", "uri": "ipfs://QmAaa...", "mimeType": "image/png", "description": "Screenshot showing successful task completion at 10:45 UTC" } ``` ### Supported File Types * βœ… Documents: PDF, Word, Markdown, Text * βœ… Images: PNG, JPEG, WebP, GIF * βœ… Data: JSON, CSV, XML * βœ… Archives: ZIP (for multiple files) * βœ… Any other format (stored as-is) ## Protocol-Specific Fields ### A2A Protocol Fields For feedback on **Agent-to-Agent (A2A)** interactions: | Field | Type | Example | Description | | --------- | ------ | ----------------------------------- | ------------------ | | `skill` | string | `"analytical_skills/data_analysis"` | A2A skill taxonomy | | `context` | string | `"Analyzed blockchain data"` | Task context | | `task` | string | `"Generate analytics report"` | Specific task | **A2A Skill Taxonomy**: See [OASF Taxonomy](https://schema.oasf.outshift.com/0.8.0/skills) ### MCP Protocol Fields For feedback on **Model Context Protocol (MCP)** capabilities: | Field | Type | Values | Description | | ------------ | ------ | ---------------------------------------------- | -------------------------------- | | `capability` | string | `prompts`, `resources`, `tools`, `completions` | MCP capability type | | `name` | string | `"blockchain_analyzer"` | Name of the tool/resource/prompt | ### Custom Extensions The standard supports arbitrary custom fields: ```json { "score": 95, // ... standard fields ... // Custom breakdown "rating_breakdown": { "speed": 95, "accuracy": 100, "communication": 90 }, // Custom identifiers "interaction_id": "uuid-v4", "session_id": "session-123", // Custom metadata "service_duration_hours": 2.5, "revisions_requested": 1 } ``` ## Payment Proof Integration ### x402 Protocol Support The `proof_of_payment` field integrates with the x402 payment protocol for agents. ```typescript interface ProofOfPayment { // Required fromAddress: string; // Payer address (CAIP-10) toAddress: string; // Payee address (CAIP-10) chainId: number; // Chain ID (e.g., 84532 for Base Sepolia) txHash: string; // Transaction hash (0x...) // Recommended amount?: string; // Payment amount (wei/smallest unit) currency?: string; // Currency symbol (e.g., "ETH", "USDC") protocol?: string; // Payment protocol (e.g., "x402") // Optional timestamp?: string; // Payment timestamp (ISO 8601) invoiceId?: string; // Invoice identifier } ``` ### Example: ETH Payment ```json { "proof_of_payment": { "fromAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "toAddress": "eip155:84532:0x8004...", "chainId": 84532, "txHash": "0xabc123...", "amount": "100000000000000000", "currency": "ETH", "protocol": "x402", "timestamp": "2025-12-20T11:45:00Z" } } ``` ### Example: USDC Payment ```json { "proof_of_payment": { "fromAddress": "eip155:84532:0x742d35Cc...", "toAddress": "eip155:84532:0x8004...", "chainId": 84532, "txHash": "0xdef456...", "amount": "100000000", "currency": "USDC", "tokenAddress": "eip155:84532:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "protocol": "x402" } } ``` ## Feedback Authorization ### feedbackAuth Field The `feedbackAuth` field contains a cryptographic signature proving the agent authorized this feedback. **Purpose**: * βœ… Prevents spam feedback * βœ… Proves client actually interacted with agent * βœ… Enables dispute resolution ### Authorization Structure The signature is created by signing the following data: ```solidity struct FeedbackAuth { uint256 agentId; address clientAddress; uint64 indexLimit; // Max feedback index allowed uint256 expiry; // Timestamp when auth expires uint256 chainId; address identityRegistry; address signerAddress; // Agent owner/operator } ``` ### Signature Format ```solidity feedbackAuth = sign(keccak256(abi.encodePacked( agentId, clientAddress, indexLimit, expiry, chainId, identityRegistry, signerAddress ))) ``` **Example**: ```json { "feedbackAuth": "0x1234567890abcdef..." } ``` ## Examples ### Example 1: Simple Feedback ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "feedbackAuth": "0xabc123...", "score": 95, "reasoning": "Great DeFi analytics agent. Quick response time and accurate insights.", "tag1": "defi", "tag2": "analytics" } ``` ### Example 2: Detailed A2A Feedback with Payment Proof ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 45, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T14:30:00Z", "feedbackAuth": "0xdef456...", "score": 100, "reasoning": "Exceptional market analysis service. Provided comprehensive report with actionable insights.", "tag1": "trading", "tag2": "research", "skill": "analytical_skills/market_analysis", "context": "Analyzed crypto market trends for Q4 2025", "task": "Generate comprehensive market analysis report with predictions", "proof_of_payment": { "fromAddress": "eip155:84532:0x742d35Cc...", "toAddress": "eip155:84532:0x8004...", "chainId": 84532, "txHash": "0x789abc...", "amount": "500000000000000000", "currency": "ETH", "protocol": "x402" }, "attachments": [ { "name": "Market Analysis Report", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 2048000, "description": "75-page comprehensive market analysis with charts and predictions", "uploadedAt": "2025-12-20T14:00:00Z" }, { "name": "Raw Data", "uri": "ipfs://QmYyy...", "mimeType": "text/csv", "size": 500000, "description": "Historical price data used for analysis", "uploadedAt": "2025-12-20T14:00:00Z" } ], "rating_breakdown": { "depth": 100, "accuracy": 100, "timeliness": 95, "presentation": 100 }, "interaction_id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### Example 3: MCP Tool Feedback ```json { "agentRegistry": "eip155:11155111:0x8004...", "agentId": 78, "clientAddress": "eip155:11155111:0x123...", "createdAt": "2025-12-20T16:00:00Z", "feedbackAuth": "0xghi789...", "score": 90, "reasoning": "Blockchain analyzer MCP tool worked well. Accurate transaction parsing.", "tag1": "mcp", "tag2": "tools", "capability": "tools", "name": "blockchain_transaction_parser", "rating_breakdown": { "accuracy": 95, "speed": 85, "reliability": 90 } } ``` ## Best Practices ### 1. Always Provide Reasoning **❌ Bad**: ```json { "score": 80 } ``` **βœ… Good**: ```json { "score": 80, "reasoning": "Good service overall. Response time was a bit slow (2 hours), but final deliverable quality was excellent." } ``` ### 2. Include Evidence for Disputes For high-stakes or high-value interactions, include attachments: ```json { "score": 100, "reasoning": "...", "attachments": [ { "name": "Service Receipt", "uri": "ipfs://...", "mimeType": "application/pdf", "description": "Official receipt showing completed deliverables" } ] } ``` ### 3. Use Protocol-Specific Fields If using A2A or MCP, include relevant fields for better discoverability: ```json { "score": 95, "skill": "natural_language_processing/summarization", "capability": "completions" } ``` ### 4. Include Payment Proof for x402 For agents supporting x402 payment protocol: ```json { "score": 100, "proof_of_payment": { "txHash": "0x...", "amount": "100000000000000000", "currency": "ETH" } } ``` ### 5. Use CAIP Formats for Addresses **❌ Bad**: ```json { "clientAddress": "0x742d35Cc..." } ``` **βœ… Good**: ```json { "clientAddress": "eip155:84532:0x742d35Cc..." } ``` ### 6. Timestamp Everything ```json { "createdAt": "2025-12-20T12:00:00Z", "proof_of_payment": { "timestamp": "2025-12-20T11:45:00Z" }, "attachments": [ { "uploadedAt": "2025-12-20T11:50:00Z" } ] } ``` ## See Also * [Validation Standard](03-validation-standard.md) - Validation Registry offchain data format * [Agent Metadata Standard](01-agent-metadata-standard.md) - AgentURI metadata format * [Feedback Best Practices](implementation/feedback-best-practices.md) - Detailed implementation guide * [Sources & References](reference/sources.md) - Data sources and methodology **Official EIP-8004 Specification**: --- --- url: /v1/docs/02-feedback-standard.md description: Recommended offchain data format for ERC-8004 feedback records --- ## Description Recommended offchain data profile for ERC-8004 feedback records This document provides implementation-agnostic guidance for structuring feedback data referenced by the `feedbackURI` field in ERC-8004 Reputation Registry contracts. > **Version Info**: This document describes the **v1.1 specification** (January 2026). For pre-v1 legacy documentation, see [archive copy](/legacy-pre-v1/docs/02-feedback-standard.md). ## Document Purpose This profile document offers **practical, non-normative recommendations** for feedback data formats used with ERC-8004 Reputation Registries, based on real-world usage patterns and community feedback. ## Relationship to EIP-8004 > **Important**: This is **not** part of the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification. **Official EIP-8004** defines: * Reputation Registry smart contract interface * Onchain fields: `score`, `tag1`, `tag2`, `endpoint`, `feedbackURI`, `feedbackHash` * The `feedbackURI` field is OPTIONAL **This profile** suggests: * Offchain JSON structure for feedback data * Protocol-specific field patterns (A2A, MCP) * Evidence attachment guidelines * Payment proof integration (x402) The official EIP makes `feedbackURI` **optional**. When provided, this profile recommends patterns for its content. ### Key Changes in v1.1 (January 2026) | Field | pre-v1 (legacy) | v1.1 | | ----------------- | --------------- | ------------- | | **Tag Types** | `bytes32` | `string` | | **URI Naming** | `feedbackUri` | `feedbackURI` | | **FeedbackAuth** | Required | Removed | | **Endpoint** | β€” | NEW | | **feedbackIndex** | Calculated | From event | See [migration guide](implementation/migration-v0-4-to-v1-0.md) for upgrading from pre-v1 (legacy). ## Terminology This document follows conventions defined in [Conventions](00-CONVENTIONS.md). For attachment file patterns, see [Attachment Pattern Standard](extensions/04-attachment-pattern-standard.md). ## Intended Audience * Service clients giving feedback * Registry implementers building indexers and explorers ## Table of Contents 1. [Overview](#overview) 2. [Recommended Feedback Profile](#recommended-feedback-profile) 3. [Attachment Pattern](#attachment-pattern) 4. [Protocol-Specific Fields](#protocol-specific-fields) 5. [Payment Proof Integration](#payment-proof-integration) 6. [Authorization (Deprecated)](#authorization-deprecated-in-v11) 7. [Examples](#examples) 8. [Best Practices](#best-practices) ## Overview ### Onchain vs Offchain Data **Onchain** (Reputation Registry contract): * `score` (uint8, 0-100) - REQUIRED * `tag1`, `tag2` (string) - OPTIONAL (now direct strings, no encoding) * `endpoint` (string) - OPTIONAL, specifies the service endpoint * `feedbackURI` (string) - OPTIONAL * `feedbackHash` (bytes32) - OPTIONAL * `feedbackIndex` (uint64) - **From event emission** (no longer calculated) **Onchain Events** (for indexers): * `NewFeedback`: `agentId` (indexed), `clientAddress` (indexed), `feedbackIndex`, `score`, `indexedTag1` (indexed), `tag1`, `tag2`, `endpoint`, `feedbackURI`, `feedbackHash` * `FeedbackRevoked`: `agentId` (indexed), `clientAddress` (indexed), `feedbackIndex` (indexed) * `ResponseAppended`: `agentId` (indexed), `clientAddress` (indexed), `feedbackIndex`, `responder` (indexed), `responseURI`, `responseHash` > **Note for Indexers**: The `indexed` parameters can be efficiently filtered in event queries. Non-indexed parameters require full log scanning. > > **Important (v1.1.1 update)**: `tag1` is now emitted **twice** in `NewFeedback`: > > * `indexedTag1` (indexed): Topic-hashed for efficient filtering > * `tag1` (non-indexed): Actual string value for direct access > > This allows both efficient filtering AND direct value retrieval without decoding. **Offchain** (referenced by `feedbackUri`): * Detailed feedback context and reasoning * Proof of payment (x402 protocol) * Protocol-specific fields (A2A/MCP) * Evidence attachments * Custom extensions > **Non-normative**: The `feedbackUri` field is **optional** per EIP-8004. However, providing rich offchain data improves trust, transparency, and enables better discovery and dispute resolution. ## Recommended Feedback Profile ### Suggested Schema ```jsonc { // ============ MUST FIELDS (per official spec) ============ "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "score": 100, // ============ ALL OPTIONAL FIELDS (per official spec) ============ "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.agent.example.com/v1", // A2A / OASF fields "skill": "analytical_skills/data_analysis", // as-defined-by-A2A-or-OASF "domain": "technology/blockchain", // as-defined-by-OASF (NEW in v1.1) "context": "Analyzed blockchain transaction data for portfolio optimization", "task": "Generate daily analytics report with recommendations", // MCP fields "capability": "tools", // prompts, resources, tools, or completions "name": "blockchain_analyzer", // x402 payment proof "proofOfPayment": { "fromAddress": "0x742d35Cc...", "toAddress": "0x8004...", "chainId": "84532", "txHash": "0xabc123..." }, // ============ BEST PRACTICES EXTENSIONS (this profile) ============ "reasoning": "Excellent portfolio analysis service.", "attachments": [ { "name": "Service Receipt", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 50000 } ], // Other custom fields " ... ": { " ... " } } ``` > \[!NOTE] > This schema follows the official EIP-8004 spec structure. Fields marked "MUST" are required by the spec; fields marked "OPTIONAL" are defined by the spec but not required. "Best Practices Extensions" are additional recommendations from this profile. > > The `feedbackAuth` field has been **removed in v1.1**. Feedback no longer requires pre-authorization from agents. See [migration guide](implementation/migration-v0-4-to-v1-0.md) for details. ### Recommended Fields | Field | Type | Constraints | Description | | --------------- | ------ | ------------------------------- | ------------------------------------------------- | | `agentRegistry` | string | CAIP-10 format | Agent's identity registry address | | `agentId` | number | uint256, β‰₯ 0 | Agent token ID | | `clientAddress` | string | CAIP-10 format | Client's wallet address | | `createdAt` | string | ISO 8601 UTC | Feedback creation timestamp | | `score` | number | 0–100 inclusive (uint8 onchain) | Overall feedback score (must match onchain value) | **CAIP Format References**: * **CAIP-10** (Contract Address): `eip155:84532:0x8004C269...` β†’ [Conventions](00-CONVENTIONS.md#caip-10-for-contract-addresses) * **CAIP-10** (Account ID): `eip155:84532:0x742d35Cc...` β†’ [Conventions](00-CONVENTIONS.md#caip-10-account-address-format) ### Recommended Optional Fields | Field | Type | Description | | ----------- | ------ | --------------------------------------------------- | | `reasoning` | string | Human-readable explanation of the feedback score | | `tag1` | string | Primary category tag (direct string, not encoded) | | `tag2` | string | Secondary category tag (direct string) | | `endpoint` | string | Service endpoint used for interaction (NEW in v1.1) | > **Note**: In v1.1, `tag1` and `tag2` are **direct strings** on-chain. No encoding/decoding needed. The `endpoint` field is optional but recommended for tracking which specific service endpoint was used. ## Attachment Pattern ### Overview The attachment pattern allows clients to provide evidence, receipts, or supporting documents with their feedback. **For complete attachment schema and guidelines**, see [Attachment Pattern Guidelines](extensions/04-attachment-pattern-standard.md). ### Quick Reference Attachments use the following structure: ```typescript interface AttachmentFile { name: string; // Display name (required) uri: string; // File location (required) mimeType: string; // MIME type (required) size: number; // File size in bytes (required) description?: string; // Optional context uploadedAt?: string; // Optional timestamp (ISO 8601 UTC) } ``` **Example**: ```json { "attachments": [ { "name": "Service Receipt", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 50000, "description": "Invoice and deliverables", "uploadedAt": "2025-12-20T15:00:00Z" } ] } ``` ### Common Use Cases **1. Service Receipts**: Proof of service completion **2. Communication Logs**: Chat transcripts showing responsiveness **3. Work Product**: Deliverables and analysis reports **4. Screenshots**: Visual evidence of results **Supported File Types**: PDFs, images, videos, JSON, CSV, text files, and more. See [Attachment Pattern Guidelines](extensions/04-attachment-pattern-standard.md) for: * Detailed field specifications * Security considerations * Best practices * Implementation requirements ```json { "name": "Analysis Report", "uri": "ipfs://QmZzz...", "mimeType": "application/pdf", "description": "Final deliverable - 50-page portfolio analysis report" } ``` ### 4. Screenshots/Evidence ```json { "name": "Service Screenshot", "uri": "ipfs://QmAaa...", "mimeType": "image/png", "description": "Screenshot showing successful task completion at 10:45 UTC" } ``` ### Supported File Types * βœ… Documents: PDF, Word, Markdown, Text * βœ… Images: PNG, JPEG, WebP, GIF * βœ… Data: JSON, CSV, XML * βœ… Archives: ZIP (for multiple files) * βœ… Any other format (stored as-is) ## Protocol-Specific Fields ### A2A / OASF Protocol Fields For feedback on **Agent-to-Agent (A2A)** interactions or **OASF** taxonomy: | Field | Type | Example | Description | | --------- | ------ | ----------------------------------- | -------------------------- | | `skill` | string | `"analytical_skills/data_analysis"` | A2A or OASF skill taxonomy | | `domain` | string | `"technology/blockchain"` | OASF domain taxonomy (NEW) | | `context` | string | `"Analyzed blockchain data"` | Task context (A2A) | | `task` | string | `"Generate analytics report"` | Specific task (A2A) | > \[!NOTE] > **v1.1 Change**: The `skill` field now accepts both A2A and OASF skill slugs. The `domain` field was added for OASF domain taxonomy. **Taxonomy References**: * [OASF Skills](https://schema.oasf.outshift.com/0.8.0/skills) * [OASF Domains](https://schema.oasf.outshift.com/0.8.0/domains) ### MCP Protocol Fields For feedback on **Model Context Protocol (MCP)** capabilities: | Field | Type | Values | Description | | ------------ | ------ | ---------------------------------------------- | -------------------------------- | | `capability` | string | `prompts`, `resources`, `tools`, `completions` | MCP capability type | | `name` | string | `"blockchain_analyzer"` | Name of the tool/resource/prompt | ### Custom Extensions The standard supports arbitrary custom fields: ```json { "score": 95, // ... standard fields ... // Custom breakdown "rating_breakdown": { "speed": 95, "accuracy": 100, "communication": 90 }, // Custom identifiers "interaction_id": "uuid-v4", "session_id": "session-123", // Custom metadata "service_duration_hours": 2.5, "revisions_requested": 1 } ``` ## Payment Proof Integration ### x402 Protocol Support > \[!NOTE] > **v1.1 Change**: The field name changed from `proof_of_payment` (snake\_case) to `proofOfPayment` (camelCase) in January 2026 for JSON naming consistency. The `proofOfPayment` field integrates with the x402 payment protocol for agents. ```typescript // Official EIP-8004 spec fields interface ProofOfPayment { fromAddress: string; // Payer address (0x...) toAddress: string; // Payee address (0x...) chainId: string; // Chain ID as string (e.g., "1", "84532") txHash: string; // Transaction hash (0x...) // Best practices extensions (this profile) amount?: string; // Payment amount (wei/smallest unit) currency?: string; // Currency symbol (e.g., "ETH", "USDC") protocol?: string; // Payment protocol (e.g., "x402") timestamp?: string; // Payment timestamp (ISO 8601) } ``` ### Example: ETH Payment ```json { "proofOfPayment": { "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "toAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "chainId": "84532", "txHash": "0xabc123..." } } ``` ### Example: ETH Payment with Extensions ```json { "proofOfPayment": { "fromAddress": "0x742d35Cc...", "toAddress": "0x8004...", "chainId": "84532", "txHash": "0xabc123...", "amount": "100000000000000000", "currency": "ETH", "protocol": "x402" } } ``` ## Authorization (Deprecated in v1.1) > ⚠️ **DEPRECATED**: The `feedbackAuth` field and pre-authorization flow have been **removed in v1.1**. > > In pre-v1 (legacy), feedback required cryptographic authorization from agents. In v1.1, **anyone can submit feedback** directly without pre-approval. Spam/Sybil protection now relies on off-chain filtering and reputation scoring. See [migration guide](implementation/migration-v0-4-to-v1-0.md) if you're upgrading from pre-v1 (legacy). ## Examples ### Example 1: Simple Feedback ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "score": 95, "reasoning": "Great DeFi analytics agent. Quick response time and accurate insights.", "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.example.com/analytics/v1" } ``` ### Example 2: Detailed A2A Feedback with Payment Proof ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 45, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T14:30:00Z", "score": 100, "reasoning": "Exceptional market analysis service. Provided comprehensive report with actionable insights.", "tag1": "trading", "tag2": "research", "skill": "analytical_skills/market_analysis", "context": "Analyzed crypto market trends for Q4 2025", "task": "Generate comprehensive market analysis report with predictions", "proofOfPayment": { "fromAddress": "eip155:84532:0x742d35Cc...", "toAddress": "eip155:84532:0x8004...", "chainId": 84532, "txHash": "0x789abc...", "amount": "500000000000000000", "currency": "ETH", "protocol": "x402" }, "attachments": [ { "name": "Market Analysis Report", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 2048000, "description": "75-page comprehensive market analysis with charts and predictions", "uploadedAt": "2025-12-20T14:00:00Z" }, { "name": "Raw Data", "uri": "ipfs://QmYyy...", "mimeType": "text/csv", "size": 500000, "description": "Historical price data used for analysis", "uploadedAt": "2025-12-20T14:00:00Z" } ], "rating_breakdown": { "depth": 100, "accuracy": 100, "timeliness": 95, "presentation": 100 }, "interaction_id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### Example 3: MCP Tool Feedback ```json { "agentRegistry": "eip155:11155111:0x8004...", "agentId": 78, "clientAddress": "eip155:11155111:0x123...", "createdAt": "2025-12-20T16:00:00Z", "score": 90, "reasoning": "Blockchain analyzer MCP tool worked well. Accurate transaction parsing.", "tag1": "mcp", "tag2": "tools", "capability": "tools", "name": "blockchain_transaction_parser", "rating_breakdown": { "accuracy": 95, "speed": 85, "reliability": 90 } } ``` ## Best Practices ### 1. Always Provide Reasoning **❌ Bad**: ```json { "score": 80 } ``` **βœ… Good**: ```json { "score": 80, "reasoning": "Good service overall. Response time was a bit slow (2 hours), but final deliverable quality was excellent." } ``` ### 2. Include Evidence for Disputes For high-stakes or high-value interactions, include attachments: ```json { "score": 100, "reasoning": "...", "attachments": [ { "name": "Service Receipt", "uri": "ipfs://...", "mimeType": "application/pdf", "description": "Official receipt showing completed deliverables" } ] } ``` ### 3. Use Protocol-Specific Fields If using A2A, OASF, or MCP, include relevant fields for better discoverability: **A2A / OASF Example**: ```json { "score": 95, "tag1": "defi", "tag2": "analytics", "skill": "analytical_skills/data_analysis/blockchain_analysis", "domain": "technology/blockchain", "context": "Analyzed blockchain transaction patterns for portfolio optimization" } ``` **MCP Example**: ```json { "score": 90, "tag1": "mcp", "tag2": "tools", "capability": "tools", "name": "blockchain_analyzer", "context": "Used MCP tools capability for blockchain data analysis" } ``` ### 4. Include Payment Proof for x402 For agents supporting x402 payment protocol: ```json { "score": 100, "proofOfPayment": { "txHash": "0x...", "amount": "100000000000000000", "currency": "ETH" } } ``` ### 5. Use CAIP Formats for Addresses **❌ Bad**: ```json { "clientAddress": "0x742d35Cc..." } ``` **βœ… Good**: ```json { "clientAddress": "eip155:84532:0x742d35Cc..." } ``` ### 6. Include Endpoint Information (v1.1) **NEW in v1.1**: Always include the `endpoint` field to track which service endpoint was used: **❌ Missing context**: ```json { "score": 95, "tag1": "defi" } ``` **βœ… Good - with endpoint**: ```json { "score": 95, "tag1": "defi", "endpoint": "https://api.agent.example.com/v1", "reasoning": "Used the v1 API endpoint. Fast response and accurate results." } ``` This helps distinguish feedback for different versions or deployments of the same agent. ### 7. Use String Tags Directly (v1.1) **NEW in v1.1**: Tags are now direct strings, not encoded bytes32: **❌ Old pre-v1 format (deprecated)**: ```json { "tag1": "6465666900000000000000000000000000000000000000000000000000000000", "tag2": "616e616c7974696373000000000000000000000000000000000000000000000000" } ``` **βœ… v1.1 format**: ```json { "tag1": "defi", "tag2": "analytics" } ``` ### 8. Timestamp Everything ```json { "createdAt": "2025-12-20T12:00:00Z", "proofOfPayment": { "timestamp": "2025-12-20T11:45:00Z" }, "attachments": [ { "uploadedAt": "2025-12-20T11:50:00Z" } ] } ``` ### 9. Complete v1.1 Best Practice Example Here's a comprehensive example following all v1.1 best practices: ```json { // Core required fields "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "score": 95, // v1.1 fields (string tags + endpoint) "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.agent.example.com/v2", // Human context "reasoning": "Excellent DeFi analytics service. Used the v2 API which provided faster response times. The portfolio optimization recommendations were accurate and well-explained.", // Protocol-specific fields (OASF) "skill": "analytical_skills/data_analysis/blockchain_analysis", "domain": "finance_and_business/finance", "context": "Portfolio optimization for DeFi positions across multiple chains", // Payment proof (x402) "proofOfPayment": { "fromAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "toAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "chainId": "84532", "txHash": "0xabc123...", "amount": "100000000000000000", "currency": "ETH", "timestamp": "2025-12-20T11:45:00Z" }, // Evidence attachments "attachments": [ { "name": "Analysis Report", "uri": "ipfs://QmXxx...", "mimeType": "application/pdf", "size": 250000, "description": "Full 50-page portfolio analysis with recommendations", "uploadedAt": "2025-12-20T11:50:00Z" }, { "name": "Service Receipt", "uri": "ipfs://QmYyy...", "mimeType": "application/pdf", "size": 50000, "description": "Invoice and proof of deliverables", "uploadedAt": "2025-12-20T11:55:00Z" } ] } ``` **Why this example follows best practices**: * βœ… Uses CAIP-10 format for addresses * βœ… Includes `endpoint` to track API version used * βœ… Uses direct string tags (not hex-encoded) * βœ… Provides detailed `reasoning` * βœ… Includes protocol-specific fields (`skill`, `domain`) * βœ… Has payment proof with full details * βœ… Includes evidence attachments * βœ… All timestamps in ISO 8601 UTC format * βœ… No `feedbackAuth` field (removed in v1.1) ## FAQ ### Q: How do I handle feedback revocation or deletion? **A**: Use the `FeedbackRevoked` event to mark feedback as deleted (immutability-safe approach): ```solidity // From ReputationRegistry.sol event FeedbackRevoked( uint256 indexed agentId, address indexed clientAddress, uint64 indexed feedbackIndex ); // Client can revoke their own feedback function revokeFeedback(uint256 agentId, uint64 feedbackIndex) external { // Only the client who submitted feedback can revoke it require(msg.sender == feedbackClients[agentId][feedbackIndex], "Only feedback author can revoke"); emit FeedbackRevoked(agentId, msg.sender, feedbackIndex); } ``` **Indexer handling**: * Track `FeedbackRevoked` events * Mark feedback as deleted (don't remove it) * Exclude revoked feedback from reputation calculations * Show revocation status in UI ("This feedback was revoked") **Off-chain data**: Archive revoked feedback but don't delete URIs (preserves immutability) *** ### Q: How do I efficiently index and search large feedback volumes? **A**: Leverage the indexed event parameters for optimized queries: ```solidity event NewFeedback( uint256 indexed agentId, // ← Query by agent address indexed clientAddress, // ← Query by reviewer uint64 feedbackIndex, // ← Sequential ordering uint8 score, string indexed indexedTag1, // ← Filter by tag efficiently (topic hash) string tag1, // ← Actual tag1 value (v1.1.1+) string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash ); ``` **Optimization strategies**: 1. **Use indexed parameters in queries**: ```typescript // Efficient: Uses event indexes const agentFeedback = await contract.queryFilter( contract.filters.NewFeedback(agentId, null, null, null, null) ); // Also efficient: Filter by tag const defiFeedback = await contract.queryFilter( contract.filters.NewFeedback(null, null, null, null, "defi") ); ``` 2. **Aggregate in time windows**: Don't recalculate entire reputation on every query * Cache score averages per (agentId, tag) per time period * Incrementally update on new feedback 3. **Use feedbackIndex for pagination**: ```typescript // Get feedback 100-200 for (agent, client) const feedback = await db.query( "SELECT * FROM feedback WHERE agentId = ? AND feedbackIndex BETWEEN ? AND ?", [agentId, 100, 200] ); ``` 4. **Separate hot/cold data**: * Hot: Recent feedback (last 30 days) β†’ fast index * Cold: Historical feedback β†’ compressed archive *** ## See Also * [Validation Standard](03-validation-standard.md) - Validation Registry offchain data format * [Agent Metadata Standard](01-agent-metadata-standard.md) - AgentURI metadata format * [Feedback Best Practices](implementation/feedback-best-practices.md) - Detailed implementation guide * [Sources & References](reference/sources.md) - Data sources and methodology **Official EIP-8004 Specification**: --- --- url: /docs/GLOSSARY.md description: Quick reference for terms and abbreviations in ERC-8004 standards --- ## Description Quick reference for terms and abbreviations used in ERC-8004 Offchain Standards ## Abbreviations ### A **A2A** - Agent-to-Agent Protocol Communication protocol enabling direct agent-to-agent interactions and collaborations. [Specification](https://a2a.to/) **ATOM** - On-chain trust scoring engine for Solana agents Computes trust metrics (trustTier 0-4, qualityScore 0-10000, confidence, riskScore, diversityRatio) from feedback data. [Source](https://github.com/QuantuLabs/atom-engine) **Arweave (AR)** - Permanent decentralized storage network Uses `ar://` URI scheme ### B **Base58** - Binary-to-text encoding scheme Used by Solana for addresses and transaction signatures. Alphabet excludes `0`, `O`, `I`, `l` to avoid ambiguity. Case-sensitive. ### C **CAIP** - Chain Agnostic Improvement Proposal Standards for blockchain-agnostic identifiers **CAIP-2** - Blockchain ID format (`namespace:reference`) Examples: `eip155:1` (Ethereum Mainnet), `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` (Solana Mainnet), `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` (Solana Devnet) **CAIP-10** - Account address format (`namespace:reference:address`) Examples: `eip155:1:0x742d35...`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:Aqq2ZKnz...` **CID** - Content Identifier Unique hash-based identifier used in IPFS Example: `bafkreiabc...` (CIDv1) ### E **Ed25519** - Edwards-curve Digital Signature Algorithm Signature scheme used by Solana for transaction signing and wallet authentication. Produces 64-byte signatures. **EIP** - Ethereum Improvement Proposal Process for proposing standards to Ethereum ecosystem **ERC** - Ethereum Request for Comments Standards track within EIP process (e.g., ERC-20, ERC-721, ERC-8004) **ERC-8004** - Trustless Agents Standard NFT-based standard for AI agent identity, reputation, and validation ### G **Groth16** - Type of zkSNARK proof system Widely used zero-knowledge proof construction, efficient verification ### I **IANA** - Internet Assigned Numbers Authority Organization that maintains official MIME type registry **IPFS** - InterPlanetary File System Content-addressed, peer-to-peer file system Uses `ipfs://` URI scheme **ISO 8601** - International date and time format standard Example: `2025-12-21T14:30:00Z` ### J **JSON** - JavaScript Object Notation Text-based data format used for all offchain metadata ### K **Keccak-256** - Cryptographic hash function Used for content hashing in Ethereum (produces `bytes32` output) ### L **Lamports** - Smallest unit of SOL (Solana's native token) 1 SOL = 10^9 lamports. Equivalent to "wei" in Ethereum. ### M **MCP** - Model Context Protocol Protocol for AI agents to expose tools, prompts, and resources [Specification](https://modelcontextprotocol.io/) **Metaplex Core** - Solana NFT standard Used for agent identity on Solana (equivalent to ERC-721 on EVM). Assets are identified by base58 public keys. [Documentation](https://developers.metaplex.com/core) **MIME Type** - Multipurpose Internet Mail Extensions Standard for indicating file type (e.g., `application/json`, `image/png`) ### N **NFT** - Non-Fungible Token Unique token standard (ERC-721), used for agent identity in ERC-8004 ### O **OASF** - Open Agent Skills Framework Taxonomy for categorizing agent capabilities and domains. [Specification](https://github.com/agntcy/oasf/) **OASF Domain** - High-level field of operation Categories like `finance_and_business`, `healthcare_and_medicine`, `technology_and_engineering`. See: [OASF Domain Taxonomy](https://github.com/agntcy/oasf/blob/main/categories/domain/README.md) **OASF Skill** - Specific capability an agent possesses Hierarchical paths like `analytical_skills/data_analysis`, `communication_skills/content_creation`. See: [OASF Skills Taxonomy](https://github.com/agntcy/oasf/blob/main/categories/skill/README.md) ### P **PLONK** - Type of zkSNARK proof system More flexible than Groth16, supports universal setup ### R **RFC 2119** - Key words for requirement levels Defines MUST, SHOULD, MAY, etc. for specification documents ### S **SEAL v1** - Solana Event Authenticity Layer Tamper-proof hash chain protocol for Solana feedback events. Uses SHA-256 running digests to ensure event ordering integrity. See: [Solana Chain Support Extension](extensions/solana-support.md) **SemVer** - Semantic Versioning Version numbering scheme (MAJOR.MINOR.PATCH) **Solana** - High-performance blockchain Supports ERC-8004 agents via Metaplex Core NFTs. Uses Ed25519 signatures, base58 addresses, and SHA-256 content hashing. Chain IDs: `501` (Mainnet), `503` (Devnet). See: [Solana Chain Support Extension](extensions/solana-support.md) **Services (Agent Metadata Field)** - Top-level array field in agent metadata (Jan 2026+) The official field name for the array of service endpoints in agent metadata JSON. Replaces legacy `endpoints` field name. Each service object contains `name`, `endpoint`, and optional fields like `version`, `skills`, etc. * **Current**: `"services": [...]` βœ… Recommended (EIP-8004 Jan 2026) * **Legacy**: `"endpoints": [...]` ⚠️ Deprecated but still supported * **Note**: Different from the singular `endpoint` property within each service object, and different from the `endpoint` field in feedback data. See: [Agent Metadata Standard - Field Migration](01-agent-metadata-standard.md#field-name-migration-endpoints-to-services) **STARK** - Scalable Transparent Argument of Knowledge Type of zero-knowledge proof, post-quantum secure ### T **TEE** - Trusted Execution Environment Hardware-based secure computation (e.g., Intel SGX, ARM TrustZone) ### U **URI** - Uniform Resource Identifier Generic identifier for resources (includes URLs) Schemes: `https://`, `ipfs://`, `ar://`, `data:` **URL** - Uniform Resource Locator Subset of URI using `http://` or `https://` schemes **UTC** - Coordinated Universal Time Standard time zone (offset +00:00), required for all timestamps ### X **x402** - Payment protocol for AI agents Protocol for agent payment proofs referenced in feedback records ### Z **zkML** - Zero-Knowledge Machine Learning Techniques for proving ML model execution without revealing model weights **zkSNARK** - Zero-Knowledge Succinct Non-Interactive Argument of Knowledge Cryptographic proof system enabling verification without revealing inputs Types include Groth16, PLONK, STARK, Halo2 ## Key Terms ### AgentURI Offchain metadata URI referenced by ERC-8004 Identity Registry NFTs. Points to JSON containing agent identity, services, and capabilities. See: [Agent Metadata Standard](01-agent-metadata-standard.md) ### Attachment Pattern Standardized schema for including evidence files in feedback and validation records. Defines fields like `name`, `uri`, `mimeType`, `size`. See: [Attachment Pattern Standard](extensions/04-attachment-pattern-standard.md) ### Base Sepolia Ethereum Layer 2 testnet (chainId: 84532). Used extensively in 8004scan production data. ### Compatibility Levels Three-level system for classifying offchain data formats: * **Level 1**: ERC-8004 Standard (recommended) * **Level 2**: Known Custom Formats (recognized) * **Level 3**: Unknown Formats (stored as-is) See: [Validation Standard - Format Compatibility](03-validation-standard.md#format-compatibility-levels) ### Data URI URI scheme for embedding data inline: `data:[mediatype][;base64],` Example: `data:application/json;base64,eyJuYW1lI...` ### Feedback Authorization (Deprecated in v1.1) > ⚠️ **DEPRECATED**: This mechanism was removed in v1.1 (January 2026). \~~Two-step process for creating feedback:~~ 1. \~~Client requests permission via agent endpoint~~ 2. \~~Agent provides signature (`feedbackAuth`) authorizing feedback~~ **v1.1**: Anyone can submit feedback directly without pre-authorization. Spam protection relies on off-chain filtering. See: [Feedback Standard](02-feedback-standard.md) ### Identity Registry ERC-8004 smart contract managing agent NFTs and metadata URIs. Core component for agent registration. ### Normative vs Non-normative **Normative**: Defines requirements (MUST/SHOULD/MAY) **Non-normative**: Provides informative guidance, examples, or rationale Marked with: `> **Non-normative**: ...` ### Offchain Data JSON metadata stored off-blockchain (IPFS, HTTPS) and referenced by URIs in smart contracts. Contrasts with **onchain data**: data stored directly in contract state. ### Parse Status Classification of how well offchain data conforms to standards: * `success` - Perfect compliance * `warning` - Minor issues, still usable * `known_custom` - Recognized custom format * `unknown` - Unrecognized format ### Reputation Registry ERC-8004 smart contract managing feedback records and reputation signals (values) for agents. ### Validation Registry ERC-8004 smart contract managing validation requests and responses (proofs, attestations). ### Validation Type Category of validation method: * `crypto-economic` - Economic incentive based * `tee-attestation` - Hardware-secured proof * `zkml-proof` - Zero-knowledge ML proof See: [Validation Standard](03-validation-standard.md) ## Protocol References ### MCP (Model Context Protocol) **Current Version**: 2025-06-18 **Specification**: Standard for AI agents to expose: * **Tools**: Callable functions * **Prompts**: Pre-defined prompt templates * **Resources**: Data sources and context ### A2A (Agent-to-Agent) **Current Version**: 0.3.0 **Specification**: Protocol for agent discovery, capability negotiation, and communication. ### OASF (Open Agent Skills Framework) **Current Version**: v0.8.0 **Repository**: Hierarchical taxonomy for agent: * **Skills**: What agents can do (e.g., `analytical_skills/data_analysis`) * **Domains**: What fields they operate in (e.g., `finance_and_business`) ### x402 Payment protocol for AI agents. Enables proof of payment in feedback records. **Fields**: * `fromAddress`, `toAddress` (CAIP-10) * `txHash`, `amount`, `currency` * `protocol`: "x402" ## Chain Identifiers Common chain IDs using CAIP-2 format: | Blockchain | CAIP-2 Format | Chain ID | | ---------------- | ----------------------------------------- | -------- | | Ethereum Mainnet | `eip155:1` | 1 | | Sepolia Testnet | `eip155:11155111` | 11155111 | | Base Mainnet | `eip155:8453` | 8453 | | Base Sepolia | `eip155:84532` | 84532 | | Polygon PoS | `eip155:137` | 137 | | Arbitrum One | `eip155:42161` | 42161 | | Optimism | `eip155:10` | 10 | | Solana Mainnet | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | β€” | | Solana Devnet | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | β€” | ## MIME Types Common MIME types used in attachment patterns: | File Type | MIME Type | | ----------- | ------------------ | | JSON | `application/json` | | PDF | `application/pdf` | | PNG | `image/png` | | JPEG | `image/jpeg` | | SVG | `image/svg+xml` | | Plain Text | `text/plain` | | CSV | `text/csv` | | MP4 Video | `video/mp4` | | ZIP Archive | `application/zip` | Custom formats: `application/x-` (e.g., `application/x-groth16-proof`) ## External References * **EIP-8004**: * **RFC 2119**: * **CAIP-2**: * **CAIP-10**: * **ISO 8601**: --- --- url: /legacy-pre-v1/docs/GLOSSARY.md description: Quick reference for terms and abbreviations in ERC-8004 standards --- ## Description Quick reference for terms and abbreviations used in ERC-8004 Offchain Standards ## Abbreviations ### A **A2A** - Agent-to-Agent Protocol Communication protocol enabling direct agent-to-agent interactions and collaborations. [Specification](https://a2a.to/) **Arweave (AR)** - Permanent decentralized storage network Uses `ar://` URI scheme ### C **CAIP** - Chain Agnostic Improvement Proposal Standards for blockchain-agnostic identifiers **CAIP-2** - Blockchain ID format (`namespace:chainId`) Example: `eip155:1` for Ethereum Mainnet **CAIP-10** - Account address format (`namespace:chainId:address`) Example: `eip155:1:0x742d35...` **CID** - Content Identifier Unique hash-based identifier used in IPFS Example: `bafkreiabc...` (CIDv1) ### E **EIP** - Ethereum Improvement Proposal Process for proposing standards to Ethereum ecosystem **ERC** - Ethereum Request for Comments Standards track within EIP process (e.g., ERC-20, ERC-721, ERC-8004) **ERC-8004** - Trustless Agents Standard NFT-based standard for AI agent identity, reputation, and validation ### G **Groth16** - Type of zkSNARK proof system Widely used zero-knowledge proof construction, efficient verification ### I **IANA** - Internet Assigned Numbers Authority Organization that maintains official MIME type registry **IPFS** - InterPlanetary File System Content-addressed, peer-to-peer file system Uses `ipfs://` URI scheme **ISO 8601** - International date and time format standard Example: `2025-12-21T14:30:00Z` ### J **JSON** - JavaScript Object Notation Text-based data format used for all offchain metadata ### K **Keccak-256** - Cryptographic hash function Used for content hashing in Ethereum (produces `bytes32` output) ### M **MCP** - Model Context Protocol Protocol for AI agents to expose tools, prompts, and resources [Specification](https://modelcontextprotocol.io/) **MIME Type** - Multipurpose Internet Mail Extensions Standard for indicating file type (e.g., `application/json`, `image/png`) ### N **NFT** - Non-Fungible Token Unique token standard (ERC-721), used for agent identity in ERC-8004 ### O **OASF** - Open Agent Skills Framework Taxonomy for categorizing agent capabilities and domains. [Specification](https://github.com/agntcy/oasf/) **OASF Domain** - High-level field of operation Categories like `finance_and_business`, `healthcare_and_medicine`, `technology_and_engineering`. See: [OASF Domain Taxonomy](https://github.com/agntcy/oasf/blob/main/categories/domain/README.md) **OASF Skill** - Specific capability an agent possesses Hierarchical paths like `analytical_skills/data_analysis`, `communication_skills/content_creation`. See: [OASF Skills Taxonomy](https://github.com/agntcy/oasf/blob/main/categories/skill/README.md) ### P **PLONK** - Type of zkSNARK proof system More flexible than Groth16, supports universal setup ### R **RFC 2119** - Key words for requirement levels Defines MUST, SHOULD, MAY, etc. for specification documents ### S **SemVer** - Semantic Versioning Version numbering scheme (MAJOR.MINOR.PATCH) **STARK** - Scalable Transparent Argument of Knowledge Type of zero-knowledge proof, post-quantum secure ### T **TEE** - Trusted Execution Environment Hardware-based secure computation (e.g., Intel SGX, ARM TrustZone) ### U **URI** - Uniform Resource Identifier Generic identifier for resources (includes URLs) Schemes: `https://`, `ipfs://`, `ar://`, `data:` **URL** - Uniform Resource Locator Subset of URI using `http://` or `https://` schemes **UTC** - Coordinated Universal Time Standard time zone (offset +00:00), required for all timestamps ### X **x402** - Payment protocol for AI agents Protocol for agent payment proofs referenced in feedback records ### Z **zkML** - Zero-Knowledge Machine Learning Techniques for proving ML model execution without revealing model weights **zkSNARK** - Zero-Knowledge Succinct Non-Interactive Argument of Knowledge Cryptographic proof system enabling verification without revealing inputs Types include Groth16, PLONK, STARK, Halo2 ## Key Terms ### AgentURI Offchain metadata URI referenced by ERC-8004 Identity Registry NFTs. Points to JSON containing agent identity, endpoints, and capabilities. See: [Agent Metadata Standard](01-agent-metadata-standard.md) ### Attachment Pattern Standardized schema for including evidence files in feedback and validation records. Defines fields like `name`, `uri`, `mimeType`, `size`. See: [Attachment Pattern Standard](04-attachment-pattern-standard.md) ### Base Sepolia Ethereum Layer 2 testnet (chainId: 84532). Used extensively in 8004scan production data. ### Compatibility Levels Three-level system for classifying offchain data formats: * **Level 1**: ERC-8004 Standard (recommended) * **Level 2**: Known Custom Formats (recognized) * **Level 3**: Unknown Formats (stored as-is) See: [Validation Standard - Format Compatibility](03-validation-standard.md#format-compatibility-levels) ### Data URI URI scheme for embedding data inline: `data:[mediatype][;base64],` Example: `data:application/json;base64,eyJuYW1lI...` ### Feedback Authorization Two-step process for creating feedback: 1. Client requests permission via agent endpoint 2. Agent provides signature (`feedbackAuth`) authorizing feedback See: [Feedback Standard](02-feedback-standard.md) ### Identity Registry ERC-8004 smart contract managing agent NFTs and metadata URIs. Core component for agent registration. ### Normative vs Non-normative **Normative**: Defines requirements (MUST/SHOULD/MAY) **Non-normative**: Provides informative guidance, examples, or rationale Marked with: `> **Non-normative**: ...` ### Offchain Data JSON metadata stored off-blockchain (IPFS, HTTPS) and referenced by URIs in smart contracts. Contrasts with **onchain data**: data stored directly in contract state. ### Parse Status Classification of how well offchain data conforms to standards: * `success` - Perfect compliance * `warning` - Minor issues, still usable * `known_custom` - Recognized custom format * `unknown` - Unrecognized format ### Reputation Registry ERC-8004 smart contract managing feedback records and reputation scores for agents. ### Validation Registry ERC-8004 smart contract managing validation requests and responses (proofs, attestations). ### Validation Type Category of validation method: * `crypto-economic` - Economic incentive based * `tee-attestation` - Hardware-secured proof * `zkml-proof` - Zero-knowledge ML proof See: [Validation Standard](03-validation-standard.md) ## Protocol References ### MCP (Model Context Protocol) **Current Version**: 2025-06-18 **Specification**: Standard for AI agents to expose: * **Tools**: Callable functions * **Prompts**: Pre-defined prompt templates * **Resources**: Data sources and context ### A2A (Agent-to-Agent) **Current Version**: 0.3.0 **Specification**: Protocol for agent discovery, capability negotiation, and communication. ### OASF (Open Agent Skills Framework) **Current Version**: v0.8.0 **Repository**: Hierarchical taxonomy for agent: * **Skills**: What agents can do (e.g., `analytical_skills/data_analysis`) * **Domains**: What fields they operate in (e.g., `finance_and_business`) ### x402 Payment protocol for AI agents. Enables proof of payment in feedback records. **Fields**: * `fromAddress`, `toAddress` (CAIP-10) * `txHash`, `amount`, `currency` * `protocol`: "x402" ## Chain Identifiers Common chain IDs using CAIP-2 format: | Blockchain | CAIP-2 Format | Chain ID | | ---------------- | ----------------- | -------- | | Ethereum Mainnet | `eip155:1` | 1 | | Sepolia Testnet | `eip155:11155111` | 11155111 | | Base Mainnet | `eip155:8453` | 8453 | | Base Sepolia | `eip155:84532` | 84532 | | Polygon PoS | `eip155:137` | 137 | | Arbitrum One | `eip155:42161` | 42161 | | Optimism | `eip155:10` | 10 | ## MIME Types Common MIME types used in attachment patterns: | File Type | MIME Type | | ----------- | ------------------ | | JSON | `application/json` | | PDF | `application/pdf` | | PNG | `image/png` | | JPEG | `image/jpeg` | | SVG | `image/svg+xml` | | Plain Text | `text/plain` | | CSV | `text/csv` | | MP4 Video | `video/mp4` | | ZIP Archive | `application/zip` | Custom formats: `application/x-` (e.g., `application/x-groth16-proof`) ## External References * **EIP-8004**: * **RFC 2119**: * **CAIP-2**: * **CAIP-10**: * **ISO 8601**: --- --- url: /v1/docs/GLOSSARY.md description: Quick reference for terms and abbreviations in ERC-8004 standards --- ## Description Quick reference for terms and abbreviations used in ERC-8004 Offchain Standards ## Abbreviations ### A **A2A** - Agent-to-Agent Protocol Communication protocol enabling direct agent-to-agent interactions and collaborations. [Specification](https://a2a.to/) **Arweave (AR)** - Permanent decentralized storage network Uses `ar://` URI scheme ### C **CAIP** - Chain Agnostic Improvement Proposal Standards for blockchain-agnostic identifiers **CAIP-2** - Blockchain ID format (`namespace:chainId`) Example: `eip155:1` for Ethereum Mainnet **CAIP-10** - Account address format (`namespace:chainId:address`) Example: `eip155:1:0x742d35...` **CID** - Content Identifier Unique hash-based identifier used in IPFS Example: `bafkreiabc...` (CIDv1) ### E **EIP** - Ethereum Improvement Proposal Process for proposing standards to Ethereum ecosystem **ERC** - Ethereum Request for Comments Standards track within EIP process (e.g., ERC-20, ERC-721, ERC-8004) **ERC-8004** - Trustless Agents Standard NFT-based standard for AI agent identity, reputation, and validation ### G **Groth16** - Type of zkSNARK proof system Widely used zero-knowledge proof construction, efficient verification ### I **IANA** - Internet Assigned Numbers Authority Organization that maintains official MIME type registry **IPFS** - InterPlanetary File System Content-addressed, peer-to-peer file system Uses `ipfs://` URI scheme **ISO 8601** - International date and time format standard Example: `2025-12-21T14:30:00Z` ### J **JSON** - JavaScript Object Notation Text-based data format used for all offchain metadata ### K **Keccak-256** - Cryptographic hash function Used for content hashing in Ethereum (produces `bytes32` output) ### M **MCP** - Model Context Protocol Protocol for AI agents to expose tools, prompts, and resources [Specification](https://modelcontextprotocol.io/) **MIME Type** - Multipurpose Internet Mail Extensions Standard for indicating file type (e.g., `application/json`, `image/png`) ### N **NFT** - Non-Fungible Token Unique token standard (ERC-721), used for agent identity in ERC-8004 ### O **OASF** - Open Agent Skills Framework Taxonomy for categorizing agent capabilities and domains. [Specification](https://github.com/agntcy/oasf/) **OASF Domain** - High-level field of operation Categories like `finance_and_business`, `healthcare_and_medicine`, `technology_and_engineering`. See: [OASF Domain Taxonomy](https://github.com/agntcy/oasf/blob/main/categories/domain/README.md) **OASF Skill** - Specific capability an agent possesses Hierarchical paths like `analytical_skills/data_analysis`, `communication_skills/content_creation`. See: [OASF Skills Taxonomy](https://github.com/agntcy/oasf/blob/main/categories/skill/README.md) ### P **PLONK** - Type of zkSNARK proof system More flexible than Groth16, supports universal setup ### R **RFC 2119** - Key words for requirement levels Defines MUST, SHOULD, MAY, etc. for specification documents ### S **SemVer** - Semantic Versioning Version numbering scheme (MAJOR.MINOR.PATCH) **STARK** - Scalable Transparent Argument of Knowledge Type of zero-knowledge proof, post-quantum secure ### T **TEE** - Trusted Execution Environment Hardware-based secure computation (e.g., Intel SGX, ARM TrustZone) ### U **URI** - Uniform Resource Identifier Generic identifier for resources (includes URLs) Schemes: `https://`, `ipfs://`, `ar://`, `data:` **URL** - Uniform Resource Locator Subset of URI using `http://` or `https://` schemes **UTC** - Coordinated Universal Time Standard time zone (offset +00:00), required for all timestamps ### X **x402** - Payment protocol for AI agents Protocol for agent payment proofs referenced in feedback records ### Z **zkML** - Zero-Knowledge Machine Learning Techniques for proving ML model execution without revealing model weights **zkSNARK** - Zero-Knowledge Succinct Non-Interactive Argument of Knowledge Cryptographic proof system enabling verification without revealing inputs Types include Groth16, PLONK, STARK, Halo2 ## Key Terms ### AgentURI Offchain metadata URI referenced by ERC-8004 Identity Registry NFTs. Points to JSON containing agent identity, endpoints, and capabilities. See: [Agent Metadata Standard](01-agent-metadata-standard.md) ### Attachment Pattern Standardized schema for including evidence files in feedback and validation records. Defines fields like `name`, `uri`, `mimeType`, `size`. See: [Attachment Pattern Standard](extensions/04-attachment-pattern-standard.md) ### Base Sepolia Ethereum Layer 2 testnet (chainId: 84532). Used extensively in 8004scan production data. ### Compatibility Levels Three-level system for classifying offchain data formats: * **Level 1**: ERC-8004 Standard (recommended) * **Level 2**: Known Custom Formats (recognized) * **Level 3**: Unknown Formats (stored as-is) See: [Validation Standard - Format Compatibility](03-validation-standard.md#format-compatibility-levels) ### Data URI URI scheme for embedding data inline: `data:[mediatype][;base64],` Example: `data:application/json;base64,eyJuYW1lI...` ### Feedback Authorization (Deprecated in v1.1) > ⚠️ **DEPRECATED**: This mechanism was removed in v1.1 (January 2026). \~~Two-step process for creating feedback:~~ 1. \~~Client requests permission via agent endpoint~~ 2. \~~Agent provides signature (`feedbackAuth`) authorizing feedback~~ **v1.1**: Anyone can submit feedback directly without pre-authorization. Spam protection relies on off-chain filtering. See: [Feedback Standard](02-feedback-standard.md) ### Identity Registry ERC-8004 smart contract managing agent NFTs and metadata URIs. Core component for agent registration. ### Normative vs Non-normative **Normative**: Defines requirements (MUST/SHOULD/MAY) **Non-normative**: Provides informative guidance, examples, or rationale Marked with: `> **Non-normative**: ...` ### Offchain Data JSON metadata stored off-blockchain (IPFS, HTTPS) and referenced by URIs in smart contracts. Contrasts with **onchain data**: data stored directly in contract state. ### Parse Status Classification of how well offchain data conforms to standards: * `success` - Perfect compliance * `warning` - Minor issues, still usable * `known_custom` - Recognized custom format * `unknown` - Unrecognized format ### Reputation Registry ERC-8004 smart contract managing feedback records and reputation scores for agents. ### Validation Registry ERC-8004 smart contract managing validation requests and responses (proofs, attestations). ### Validation Type Category of validation method: * `crypto-economic` - Economic incentive based * `tee-attestation` - Hardware-secured proof * `zkml-proof` - Zero-knowledge ML proof See: [Validation Standard](03-validation-standard.md) ## Protocol References ### MCP (Model Context Protocol) **Current Version**: 2025-06-18 **Specification**: Standard for AI agents to expose: * **Tools**: Callable functions * **Prompts**: Pre-defined prompt templates * **Resources**: Data sources and context ### A2A (Agent-to-Agent) **Current Version**: 0.3.0 **Specification**: Protocol for agent discovery, capability negotiation, and communication. ### OASF (Open Agent Skills Framework) **Current Version**: v0.8.0 **Repository**: Hierarchical taxonomy for agent: * **Skills**: What agents can do (e.g., `analytical_skills/data_analysis`) * **Domains**: What fields they operate in (e.g., `finance_and_business`) ### x402 Payment protocol for AI agents. Enables proof of payment in feedback records. **Fields**: * `fromAddress`, `toAddress` (CAIP-10) * `txHash`, `amount`, `currency` * `protocol`: "x402" ## Chain Identifiers Common chain IDs using CAIP-2 format: | Blockchain | CAIP-2 Format | Chain ID | | ---------------- | ----------------- | -------- | | Ethereum Mainnet | `eip155:1` | 1 | | Sepolia Testnet | `eip155:11155111` | 11155111 | | Base Mainnet | `eip155:8453` | 8453 | | Base Sepolia | `eip155:84532` | 84532 | | Polygon PoS | `eip155:137` | 137 | | Arbitrum One | `eip155:42161` | 42161 | | Optimism | `eip155:10` | 10 | ## MIME Types Common MIME types used in attachment patterns: | File Type | MIME Type | | ----------- | ------------------ | | JSON | `application/json` | | PDF | `application/pdf` | | PNG | `image/png` | | JPEG | `image/jpeg` | | SVG | `image/svg+xml` | | Plain Text | `text/plain` | | CSV | `text/csv` | | MP4 Video | `video/mp4` | | ZIP Archive | `application/zip` | Custom formats: `application/x-` (e.g., `application/x-groth16-proof`) ## External References * **EIP-8004**: * **RFC 2119**: * **CAIP-2**: * **CAIP-10**: * **ISO 8601**: --- --- url: /docs/implementation/README.md --- # Implementation Guide This section provides practical guidance and best practices for implementing the ERC-8004 standard in your applications. ## Implementation Resources ### Agent Metadata Parsing The [Agent Metadata Parsing](agent-metadata-parsing.md) guide covers: * Parsing agent metadata structures * Handling different metadata formats * Validation during parsing * Error handling strategies ### Onchain Metadata Handling The [Onchain Metadata Handling](onchain-metadata-handling.md) guide provides: * Parsing MetadataSet events and empty value handling * Three-tier metadata precedence (contract state, on-chain, off-chain) * Conflict detection and resolution * Error codes for metadata conflicts (WA080, WA081) ### Feedback Best Practices The [Feedback Best Practices](feedback-best-practices.md) guide provides: * Implementation patterns for feedback collection * Storage and retrieval strategies * Privacy considerations * Integration with existing systems ### Validation Best Practices The [Validation Best Practices](validation-best-practices.md) guide includes: * Implementing validation rules * Performance optimization * Error reporting * Testing validation logic ## Getting Started We recommend following this implementation order: 1. Start with [Agent Metadata Parsing](agent-metadata-parsing.md) to understand data structures 2. Implement [Validation Best Practices](validation-best-practices.md) to ensure data integrity 3. Add [Feedback Best Practices](feedback-best-practices.md) for user interaction Each guide includes code examples and common pitfalls to avoid. --- --- url: /legacy-pre-v1/docs/implementation/README.md --- # Implementation Guide This section provides practical guidance and best practices for implementing the ERC-8004 standard in your applications. ## Implementation Resources ### Agent Metadata Parsing The [Agent Metadata Parsing](agent-metadata-parsing.md) guide covers: * Parsing agent metadata structures * Handling different metadata formats * Validation during parsing * Error handling strategies ### Feedback Best Practices The [Feedback Best Practices](feedback-best-practices.md) guide provides: * Implementation patterns for feedback collection * Storage and retrieval strategies * Privacy considerations * Integration with existing systems ### Validation Best Practices The [Validation Best Practices](validation-best-practices.md) guide includes: * Implementing validation rules * Performance optimization * Error reporting * Testing validation logic ## Getting Started We recommend following this implementation order: 1. Start with [Agent Metadata Parsing](agent-metadata-parsing.md) to understand data structures 2. Implement [Validation Best Practices](validation-best-practices.md) to ensure data integrity 3. Add [Feedback Best Practices](feedback-best-practices.md) for user interaction Each guide includes code examples and common pitfalls to avoid. --- --- url: /v1/docs/implementation/README.md --- # Implementation Guide This section provides practical guidance and best practices for implementing the ERC-8004 standard in your applications. ## Implementation Resources ### Agent Metadata Parsing The [Agent Metadata Parsing](agent-metadata-parsing.md) guide covers: * Parsing agent metadata structures * Handling different metadata formats * Validation during parsing * Error handling strategies ### Feedback Best Practices The [Feedback Best Practices](feedback-best-practices.md) guide provides: * Implementation patterns for feedback collection * Storage and retrieval strategies * Privacy considerations * Integration with existing systems ### Validation Best Practices The [Validation Best Practices](validation-best-practices.md) guide includes: * Implementing validation rules * Performance optimization * Error reporting * Testing validation logic ## Getting Started We recommend following this implementation order: 1. Start with [Agent Metadata Parsing](agent-metadata-parsing.md) to understand data structures 2. Implement [Validation Best Practices](validation-best-practices.md) to ensure data integrity 3. Add [Feedback Best Practices](feedback-best-practices.md) for user interaction Each guide includes code examples and common pitfalls to avoid. --- --- url: /docs/implementation/migration-v1-to-v2.md description: Guide for upgrading from ERC-8004 v1.x to v2.0 feedback specification --- # Migration Guide: v1.x β†’ v2.0 This guide helps implementers upgrade from ERC-8004 v1.x to v2.0 feedback specification. ## Overview of Changes ### Breaking Change: score β†’ value + valueDecimals The primary change in v2.0 is replacing the fixed `score` field with flexible `value` + `valueDecimals` fields. | Aspect | v1.x | v2.0 | | --------------------- | --------------- | ------------------------- | | **Field name** | `score` | `value` + `valueDecimals` | | **Type** | `uint8` (0-100) | `int128` + `uint8` (0-18) | | **Range** | 0-100 only | Unlimited (int128) | | **Negative values** | Not supported | Supported | | **Decimal precision** | Integer only | Up to 18 decimals | ### Why This Change? The v1.x `score` field was limited: * Fixed 0-100 range made many metric types impossible (uptime %, response time, revenues) * No support for negative feedback (disputes, fraud reports) * No decimal precision for granular ratings (99.77% uptime) v2.0 `value` + `valueDecimals` provides: * **Arbitrary metrics**: uptime (%), response time (ms), revenues ($), block freshness, etc. * **Decimal precision**: 99.77% β†’ `value=9977, valueDecimals=2` * **Large values**: 1100ms response time β†’ `value=1100, valueDecimals=0` * **Negative feedback**: Disputes, fraud reports * **Flexible rating scales**: 5-star, 10-point, percentage, custom > **Key insight**: Since Solidity doesn't support floating-point, `valueDecimals` lets you represent decimals as integers: > > * `"30"` β†’ `value=30, valueDecimals=0` > * `"30.73"` β†’ `value=3073, valueDecimals=2` ## Schema Changes ### v1.x Schema (Before) ```json { "agentRegistry": "eip155:84532:0x8004...", "agentId": 22, "clientAddress": "eip155:84532:0x742d...", "createdAt": "2026-01-01T12:00:00Z", "score": 95, "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.example.com/v1" } ``` ### v2.0 Schema (After) ```json { "agentRegistry": "eip155:84532:0x8004...", "agentId": 22, "clientAddress": "eip155:84532:0x742d...", "createdAt": "2026-01-01T12:00:00Z", "value": "4.75", "valueDecimals": 2, "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.example.com/v1" } ``` ## Migration Steps ### Step 1: Update Contract Calls **v1.x contract call:** ```solidity submitFeedback(agentId, score, tag1, tag2, endpoint, feedbackURI, feedbackHash) ``` **v2.0 contract call:** ```solidity submitFeedback(agentId, value, valueDecimals, tag1, tag2, endpoint, feedbackURI, feedbackHash) ``` ### Step 2: Convert Score to Value When migrating existing v1.x feedback data: | v1.x score | v2.0 value | v2.0 valueDecimals | Rating | | ---------- | ---------- | ------------------ | ------- | | 100 | 5 | 0 | 5 stars | | 80 | 4 | 0 | 4 stars | | 60 | 3 | 0 | 3 stars | | 40 | 2 | 0 | 2 stars | | 20 | 1 | 0 | 1 star | | 0 | 0 | 0 | 0 stars | **Conversion formula (0-100 to 5-star):** ```javascript value = score / 20; valueDecimals = 0; ``` **Or keep percentage scale:** ```javascript value = score; valueDecimals = 0; ``` ### Step 3: Update Event Listeners **v1.x event:** ```solidity NewFeedback(agentId, clientAddress, feedbackIndex, score, indexedTag1, tag1, tag2, endpoint, feedbackURI, feedbackHash) ``` **v2.0 event:** ```solidity NewFeedback(agentId, clientAddress, feedbackIndex, value, valueDecimals, indexedTag1, tag1, tag2, endpoint, feedbackURI, feedbackHash) ``` ### Step 4: Update Off-chain Data Update your JSON schema to use `value` and `valueDecimals` instead of `score`: ```json { "value": "4.5", "valueDecimals": 1 // ... other fields unchanged } ``` ## Backward Compatibility ### Reading Historical Data Indexers should support both formats during transition: 1. Check if `value` field exists β†’ Use v2.0 format 2. Check if `score` field exists β†’ Use v1.x format (legacy) 3. Convert v1.x data to v2.0 representation for unified API ### Recommended Normalization For displaying v1.x data in v2.0 format: | v1.x score | Normalized value | valueDecimals | | ---------- | ---------------- | ------------- | | 0-100 | score | 0 | For displaying v2.0 data as percentage (for legacy UIs): | v2.0 value | valueDecimals | Normalized percentage | | ---------- | ------------- | --------------------- | | 5 | 0 | 100% (5-star) | | 4 | 0 | 80% (4-star) | | 4.5 | 1 | 90% (4.5-star) | | -2 | 0 | 0% (negative) | ## Common Rating Scales ### 5-Star Rating ```json { "value": "4", "valueDecimals": 0 } ``` Possible values: -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 ### 10-Point Rating ```json { "value": "8.5", "valueDecimals": 1 } ``` Possible values: 0.0 to 10.0 (or negative for disputes) ### Percentage Rating ```json { "value": "95", "valueDecimals": 0 } ``` Possible values: 0 to 100 (like v1.x, but can now be negative) ### Binary Thumbs Up/Down ```json { "value": "1", "valueDecimals": 0 } ``` Possible values: -1 (thumbs down), 0 (neutral), 1 (thumbs up) ## Common Metric Types (tag1) v2.0 enables many metric types that were impossible with v1.x's 0-100 `score`: | tag1 (Metric) | Description | Example value | valueDecimals | Actual Value | | -------------------- | ------------------------- | ------------- | ------------- | ------------ | | `reachable` | Is endpoint reachable? | 1 | 0 | 1 (binary) | | `ownerVerified` | Endpoint ownership proof | 1 | 0 | 1 (binary) | | `starred` | Quality rating | 85 | 0 | 85 (0-100) | | `uptime` | Endpoint uptime % | 9977 | 2 | 99.77% | | `responseTime` | Response time in ms | 560 | 0 | 560 ms | | `successRate` | Request success rate % | 9950 | 2 | 99.50% | | `blocktimeFreshness` | Block delay (# of blocks) | 4 | 0 | 4 blocks | | `correctness` | Response correctness | 1 | 0 | 1 (binary) | | `revenues` | Cumulative revenues ($) | 1100 | 0 | $1100 | ## Checklist * \[ ] Update contract ABI for v2.0 `submitFeedback` function * \[ ] Update event listeners for v2.0 `NewFeedback` event * \[ ] Update off-chain JSON schema to use `value` + `valueDecimals` * \[ ] Add backward compatibility for reading v1.x data * \[ ] Update UI to handle flexible rating scales * \[ ] Consider supporting negative feedback in UI * \[ ] Update documentation and API references ## See Also * [Feedback Data Profile v2.0](/docs/02-feedback-standard) - Complete v2.0 specification * [v1.x Feedback Standard](/v1/docs/02-feedback-standard) - Previous version reference * [Migration Guide (pre-v1 β†’ v1.x)](/docs/implementation/migration-v0-4-to-v1-0) - Earlier migration guide --- --- url: /docs/implementation/migration-v0-4-to-v1-0.md description: Complete guide for migrating from ERC-8004 pre-v1 (legacy) to v1.1 --- # Migration Guide: ERC-8004 pre-v1 (legacy) β†’ v1.1 **Date**: January 9, 2026 **Impact**: BREAKING CHANGES - Action Required > **Naming note**: The legacy release is referred to here as **pre-v1 (legacy)**. All prior references to "v0.4" map to this pre-v1 legacy release. > > **⚠️ Validation Registry Note**: This migration guide covers **Identity Registry** and **Reputation Registry (Feedback)** changes only. The **Validation Registry** specification is **UNSTABLE** and **PENDING FINALIZATION**. See [Validation Data Profile](../03-validation-standard.md) for the current draft and status tracking. ## Overview ERC-8004 underwent significant updates in January 2026 (Contract PR #11) that simplify the specification and improve usability. ### Quick Summary | Area | pre-v1 (legacy) | v1.1 | Breaking? | Scope | Applies To | | ----------------- | --------------- | ------------- | ----------- | ---------------------------- | --------------------- | | **Tag Types** | `bytes32` | `string` | βœ… YES | OnChain Interface + OffChain | Feedback (Reputation) | | **URI Naming** | `feedbackUri` | `feedbackURI` | βœ… YES | OffChain JSON Only | Feedback (Reputation) | | **FeedbackAuth** | Required | Removed | βœ… YES | OnChain Interface + OffChain | Feedback (Reputation) | | **Endpoint** | β€” | NEW | ⚠️ Addition | OnChain Interface + OffChain | Feedback (Reputation) | | **feedbackIndex** | Calculated | From event | ⚠️ Changed | OnChain Event Only | Feedback (Reputation) | **Scope Legend:** * **OnChain Interface**: Changes to `giveFeedback()` function signature or `NewFeedback` event * **OffChain JSON Only**: Changes only to the off-chain feedback data structure (no contract changes) * **OnChain + OffChain**: Changes affect both the contract interface and off-chain data format **Document Scope:** This guide covers **Feedback (Reputation Registry) changes only**. For Agent (Identity Registry) migration, refer to [Agent Metadata Standard](../01-agent-metadata-standard.md). *** ## Most Important Changes (Read This First) ### 1. FeedbackAuth Removed (CRITICAL) β€” Feedback Registry #### What changed * The old spec required agents to generate `feedbackAuth` signatures pre-authorizing clients to submit feedback. * The new spec removes `feedbackAuth` entirely: * **OnChain**: `giveFeedback()` function no longer includes the `feedbackAuth` parameter * **OffChain**: The feedback JSON no longer includes a `feedbackAuth` field #### Why it matters * This is the biggest trust-model change in v1.1: it removes pre-authorization friction and changes spam resistance approach. * Feedback submission is now direct (any client can call `giveFeedback()` directly). * Spam/Sybil protection is now enforced off-chain through indexing, filtering, and reputation aggregation. #### Concrete interface impact **pre-v1 (legacy)** `giveFeedback()`: ```solidity giveFeedback(uint256 agentId, uint8 score, bytes32 tag1, bytes32 tag2, string feedbackUri, bytes32 feedbackHash, bytes feedbackAuth) ``` **v1.1** `giveFeedback()`: ```solidity giveFeedback(uint256 agentId, uint8 score, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash) ``` *** ### 2. Tag Types Changed: bytes32 β†’ string β€” Feedback Registry #### What changed * **OnChain**: Contract interface now uses `string` for `tag1`, `tag2` (both in function params and event) * **OffChain**: JSON tags change from hex-encoded `bytes32` to plain strings #### Why it matters * Removes encoding/decoding complexity for both onchain and offchain implementations * Makes tags human-readable in events and off-chain data * Simpler for indexers and data consumers *** ### 3. FeedbackIndex Now Emitted in Event β€” Feedback Registry #### What changed * **pre-v1 (legacy)**: `feedbackIndex` was calculated by subgraph (tracking per-client-per-agent count) * **v1.1**: Contract emits `feedbackIndex` directly in the `NewFeedback` event #### Why it matters * Indexers no longer need to maintain and calculate feedback counts * `feedbackIndex` is now a first-class on-chain attribute * Simpler and more reliable feedback ordering per (client, agent) pair *** ## What Changed (Detailed) > **Scope Key:** > > * **\[OnChain]** = Changes to smart contract interface (function signatures, events) > * **\[OffChain]** = Changes to off-chain JSON feedback data structure only > * **\[Both]** = Changes affect both contract and JSON format ### 1. Tag Type Change: bytes32 β†’ string \[Both] β€” Feedback Registry **pre-v1 (legacy)** (hex-encoded tags): **OffChain JSON**: ```json { "tag1": "6465666900000000000000000000000000000000000000000000000000000000", "tag2": "616e616c7974696373000000000000000000000000000000000000000000000000" } ``` **OnChain Contract**: ```solidity // ReputationRegistry.giveFeedback() function giveFeedback(uint256 agentId, uint8 score, bytes32 tag1, bytes32 tag2, ...) ``` *** **v1.1** (plain string tags): **OffChain JSON**: ```json { "tag1": "defi", "tag2": "analytics" } ``` **OnChain Contract**: ```solidity // ReputationRegistry.giveFeedback() function giveFeedback(uint256 agentId, uint8 score, string tag1, string tag2, ...) ``` *** **Impact**: * βœ… **OnChain**: Function signature changes from `bytes32` to `string` parameters * βœ… **OnChain**: `NewFeedback` event now emits `string indexed indexedTag1, string tag1, string tag2` instead of `bytes32` (note: `indexedTag1` is indexed for efficient filtering, `tag1` provides the actual value) * βœ… **OffChain**: JSON tags no longer hex-encoded; use direct strings * βœ… Removes encoding/decoding complexity * βœ… Makes tags human-readable in events and logs *** ### 2. URI Naming: feedbackUri β†’ feedbackURI \[OffChain] β€” Feedback Registry This change affects only the **off-chain JSON data structure**. The onchain contracts already use `feedbackURI`. **pre-v1 (legacy)** OffChain JSON: ```json { "feedbackUri": "ipfs://QmXxx..." } ``` **v1.1** OffChain JSON: ```json { "feedbackURI": "ipfs://QmXxx..." } ``` **Why?** Matches standard camelCase for acronyms (Web3 convention): `feedbackURI` not `feedbackUri` **Impact**: * βœ… **OffChain Only**: JSON field name change in feedback data structure * βœ… Consistency with camelCase acronym conventions * βœ… Aligns with onchain contract naming *** ### 3. FeedbackAuth Removed (CRITICAL) \[Both] β€” Feedback Registry This is the most significant change affecting both the onchain contract interface and off-chain data structure. **pre-v1 (legacy)** - Pre-authorization flow required: **OffChain JSON**: ```json { "feedbackAuth": "0x1234567890abcdef...", "score": 95, "tag1": "defi" } ``` **OnChain Submission Flow**: 1. Client must first request authorization from the agent 2. Agent generates `feedbackAuth` signature (pre-approving this client) 3. Client calls `giveFeedback(..., bytes feedbackAuth)` with the signature 4. Contract validates the signature onchain **v1.1** - Direct submission (no pre-authorization): **OffChain JSON**: ```json { "score": 95, "tag1": "defi" } ``` **OnChain Submission Flow**: 1. Any client can directly call `giveFeedback(agentId, score, tag1, tag2, endpoint, feedbackURI, feedbackHash)` 2. No pre-authorization signature required 3. No `feedbackAuth` parameter in contract function **Impact**: * βœ… **OnChain**: `giveFeedback()` no longer includes `bytes feedbackAuth` parameter * βœ… **OffChain**: Feedback JSON no longer contains `feedbackAuth` field * βœ… Dramatically simplifies feedback submission flow * βœ… Removes agent-initiated authorization step * βœ… Spam/Sybil protection now handled off-chain (filtering, indexing, reputation-based ranking) **Migration**: * ❌ Remove all `feedbackAuth` signature generation code * ❌ Remove feedback authorization endpoints * βœ… Simplify submission to direct posting *** ### 4. New Endpoint Field \[Both] β€” Feedback Registry **pre-v1 (legacy)**: Not available **v1.1** - New optional field in both onchain and offchain: **OffChain JSON**: ```json { "endpoint": "https://agent.example.com", "score": 95, "tag1": "defi" } ``` **OnChain Contract Signature**: ```solidity function giveFeedback(uint256 agentId, uint8 score, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash) ``` **Purpose**: Optional string parameter to record which endpoint-URI was used by the client during the feedback submission process. **Examples**: * `"endpoint": "https://www.example-agent.com"` - Main agent service endpoint * `"endpoint": "https://api.example-agent.com/v2"` - Specific API version * `""` or omitted - No specific endpoint recorded **Impact**: * βœ… **OnChain**: `giveFeedback()` now includes `string endpoint` parameter * βœ… **OffChain**: Optional JSON field for endpoint URI * βœ… Allows tracking which agent endpoint-URI was involved in feedback submission * βœ… Useful for clients to reference which service version they used ### 5. FeedbackIndex Now Emitted in Event \[OnChain] β€” Feedback Registry This change affects only onchain contract behavior. There is no corresponding off-chain data change. **pre-v1 (legacy)** - Index calculated by indexer: * Subgraph maintained a `ClientAgentStats` table to track feedback count per client per agent * `feedbackIndex` was calculated as: incrementing counter for (agentId, clientAddress) pair * Indexers had to maintain this calculation logic **v1.1** - Index emitted directly by contract: **OnChain `NewFeedback` Event**: ```solidity event NewFeedback( uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, // ← Now emitted directly by contract (uint64) uint8 score, string indexed indexedTag1, // ← For efficient filtering (topic hash) string tag1, // ← Actual tag1 value string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash ); ``` **Impact**: * βœ… **OnChain Only**: Contract now emits `uint64 feedbackIndex` in `NewFeedback` event * βœ… No need for indexers to calculate feedback counts * βœ… Simpler indexing logic * βœ… `feedbackIndex` is now a first-class on-chain value * βœ… Guarantees correct sequencing of feedback per (agentId, clientAddress) pair *** ## Migration Checklist ### Phase 1: OffChain Data Format Updates * Update all feedback JSON objects to remove feedbackAuth field * Rename feedbackUri β†’ feedbackURI in all JSON occurrences * Convert tag values (hex-encoded β†’ plain strings) * If tags are hex-encoded bytes32, decode them to strings * Update tag parsing/serialization logic * Add optional endpoint field to feedback JSON where applicable * Update JSON schema validation to reflect v1.1 structure **Example (TypeScript)**: ```typescript // pre-v1 (legacy) Off-Chain Feedback Structure interface FeedbackPreV1 { feedbackAuth: string; // ❌ REMOVE feedbackUri: string; // ❌ RENAME to feedbackURI tag1: string; // Hex-encoded bytes32 tag2: string; // Hex-encoded bytes32 score: number; } // v1.1 Off-Chain Feedback Structure interface FeedbackV10 { feedbackURI: string; // βœ… Renamed endpoint?: string; // βœ… NEW (optional) tag1: string; // βœ… Plain string (no hex) tag2: string; // βœ… Plain string (no hex) score: number; } ``` **Example (Data Migration)**: ```json // pre-v1 (legacy) Feedback JSON { "agentRegistry": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "feedbackAuth": "0xabc123...", "score": 95, "tag1": "6465666900000000000000000000000000000000000000000000000000000000", "tag2": "616e616c7974696373000000000000000000000000000000000000000000000000", "feedbackUri": "ipfs://QmXxx...", "reasoning": "Great service" } // v1.1 Feedback JSON { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "score": 95, "tag1": "defi", "tag2": "analytics", "endpoint": "https://www.example-agent.com", "feedbackURI": "ipfs://QmXxx...", "reasoning": "Great service" } ``` ### Phase 2: Contract Integration Updates * Update contract interaction code to call new giveFeedback() signature * Remove feedbackAuth parameter from calls * Include new string endpoint parameter * Update tag1, tag2 parameter types from bytes32 to string * Update event handler for NewFeedback * Handle new feedbackIndex event parameter * Update tag type handling from bytes32 to string * Add endpoint field handling * Update ABI/interface definitions to reflect v1.1 contract changes **Example (Contract Call - pre-v1 (legacy) to v1.1)**: ```solidity // pre-v1 (legacy) giveFeedback( agentId, score, bytes32("defi"), // bytes32 tag bytes32("analytics"), // bytes32 tag "ipfs://QmXxx...", feedbackHash, feedbackAuthSignature // ❌ REMOVE ); // v1.1 giveFeedback( agentId, score, "defi", // βœ… string tag "analytics", // βœ… string tag "https://www.example-agent.com", // βœ… NEW endpoint "ipfs://QmXxx...", feedbackHash ); ``` ### Phase 3: Testing & Validation * Test giveFeedback() calls without feedbackAuth parameter * Verify tags are handled as strings in contract calls and events * Check feedbackURI field naming consistency * Test endpoint field handling (optional vs. empty string) * Verify feedbackIndex is correctly emitted in events * Test off-chain JSON validation against v1.1 schema * Verify hex-to-string tag decoding for existing pre-v1 (legacy) data * Test with both new v1.1 contract deployments *** ## Data Format Examples ### Off-Chain Feedback Comparison **pre-v1 (legacy)**: ```json { "agentRegistry": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "feedbackAuth": "0xabc123...", "score": 95, "tag1": "6465666900000000000000000000000000000000000000000000000000000000", "tag2": "616e616c7974696373000000000000000000000000000000000000000000000000", "feedbackUri": "ipfs://QmXxx...", "reasoning": "Great service" } ``` **v1.1**: ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "score": 95, "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.example.com/v1", "feedbackURI": "ipfs://QmXxx...", "reasoning": "Great service" } ``` **Changes**: * βœ… Removed `feedbackAuth` field * βœ… Renamed `feedbackUri` β†’ `feedbackURI` * βœ… Converted tags from hex (bytes32) to plain strings * βœ… Added optional `endpoint` field * βœ… Added CAIP format for addresses (best practice) *** ## Implementation Phases ### Phase 1: Assessment & Planning * Read this guide fully * Assess impact on your code (contract interactions, data parsing) * Identify all code paths that handle feedback * Plan data migration if needed * Create v1.1 feature branch ### Phase 2: Implementation * Migrate off-chain JSON data format * Update contract interaction code for new giveFeedback() signature * Update event handlers for NewFeedback event * Update JSON schema validation * Update any data serialization/deserialization code ### Phase 3: Testing & Validation * Unit test contract interactions with new signatures * Integration test feedback submission flow * Validate JSON format against v1.1 schema * Test with v1.1 contract deployment ### Phase 4: Deployment * Deploy updated code * Migrate historical data (if needed) * Monitor feedback submission and events * Update documentation *** ## FAQ ### Q: What's the new `giveFeedback()` function signature? **A**: The v1.1 signature is: ```solidity function giveFeedback( uint256 agentId, uint8 score, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash ) external; ``` Key differences from pre-v1 (legacy): * No `feedbackAuth` parameter * `tag1`, `tag2` are now `string` (not `bytes32`) * New `endpoint` parameter (optional, can be empty string) * `feedbackUri` β†’ `feedbackURI` (in the off-chain data) ### Q: What does the new `feedbackIndex` mean? **A**: `feedbackIndex` is now emitted in the `NewFeedback` event and represents the sequential index of feedback for a specific (agentId, clientAddress) pair. It's auto-incremented by the contract. **v1.1 Event**: ```solidity event NewFeedback( uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, // ← Sequence number per (agent, client) uint8 score, string indexed indexedTag1, // ← For efficient filtering (topic hash) string tag1, // ← Actual tag1 value string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash ); ``` ### Q: Is the `endpoint` field required? **A**: No, it's optional. Use it if you want to track which URI endpoint-source was involved in the feedback submission. Can be an empty string if not needed. ### Q: How do I validate the new off-chain JSON format? **A**: Use this JSON Schema for v1.1 feedback validation: ```json { "type": "object", "required": ["agentRegistry", "agentId", "clientAddress", "createdAt", "score"], "properties": { "agentRegistry": { "type": "string", "description": "CAIP-2 format: eip155:chainId:0x..." }, "agentId": { "type": "integer" }, "clientAddress": { "type": "string", "description": "CAIP-10 format: eip155:chainId:0x..." }, "createdAt": { "type": "string", "format": "date-time", "description": "ISO 8601 UTC timestamp" }, "score": { "type": "integer", "minimum": 0, "maximum": 100, "description": "Feedback score 0–100" }, "tag1": { "type": "string", "description": "First classification tag (indexed on-chain)" }, "tag2": { "type": "string", "description": "Second classification tag" }, "endpoint": { "type": "string", "description": "Optional: agent endpoint URI used during interaction" }, "feedbackURI": { "type": "string", "description": "Off-chain data URI (ipfs://, https://, ar://, data:)" }, "feedbackHash": { "type": "string", "description": "Keccak256 hash of feedback data for integrity (bytes32 hex)" }, "reasoning": { "type": "string", "description": "Human-readable explanation for the feedback" } } } ``` *** ## References * [Feedback Data Profile (v1.1)](../02-feedback-standard.md) * [Official ERC-8004 Spec](https://eips.ethereum.org/EIPS/eip-8004) * [ERC-8004 Jan 2026 Spec Update](../../ref_codes/erc-8004-contracts/SpecsJan26Update.md) * [Contract Repository](https://github.com/erc-8004/erc-8004-contracts) *** **Document Version**: 1.0 **Last Updated**: January 9, 2026 --- --- url: /v1/docs/implementation/migration-v0-4-to-v1-0.md description: Complete guide for migrating from ERC-8004 pre-v1 (legacy) to v1.1 --- # Migration Guide: ERC-8004 pre-v1 (legacy) β†’ v1.1 **Date**: January 9, 2026 **Impact**: BREAKING CHANGES - Action Required > **Naming note**: The legacy release is referred to here as **pre-v1 (legacy)**. All prior references to "v0.4" map to this pre-v1 legacy release. > > **⚠️ Validation Registry Note**: This migration guide covers **Identity Registry** and **Reputation Registry (Feedback)** changes only. The **Validation Registry** specification is **UNSTABLE** and **PENDING FINALIZATION**. See [Validation Data Profile](../03-validation-standard.md) for the current draft and status tracking. ## Overview ERC-8004 underwent significant updates in January 2026 (Contract PR #11) that simplify the specification and improve usability. ### Quick Summary | Area | pre-v1 (legacy) | v1.1 | Breaking? | Scope | Applies To | | ----------------- | --------------- | ------------- | ----------- | ---------------------------- | --------------------- | | **Tag Types** | `bytes32` | `string` | βœ… YES | OnChain Interface + OffChain | Feedback (Reputation) | | **URI Naming** | `feedbackUri` | `feedbackURI` | βœ… YES | OffChain JSON Only | Feedback (Reputation) | | **FeedbackAuth** | Required | Removed | βœ… YES | OnChain Interface + OffChain | Feedback (Reputation) | | **Endpoint** | β€” | NEW | ⚠️ Addition | OnChain Interface + OffChain | Feedback (Reputation) | | **feedbackIndex** | Calculated | From event | ⚠️ Changed | OnChain Event Only | Feedback (Reputation) | **Scope Legend:** * **OnChain Interface**: Changes to `giveFeedback()` function signature or `NewFeedback` event * **OffChain JSON Only**: Changes only to the off-chain feedback data structure (no contract changes) * **OnChain + OffChain**: Changes affect both the contract interface and off-chain data format **Document Scope:** This guide covers **Feedback (Reputation Registry) changes only**. For Agent (Identity Registry) migration, refer to [Agent Metadata Standard](../01-agent-metadata-standard.md). *** ## Most Important Changes (Read This First) ### 1. FeedbackAuth Removed (CRITICAL) β€” Feedback Registry #### What changed * The old spec required agents to generate `feedbackAuth` signatures pre-authorizing clients to submit feedback. * The new spec removes `feedbackAuth` entirely: * **OnChain**: `giveFeedback()` function no longer includes the `feedbackAuth` parameter * **OffChain**: The feedback JSON no longer includes a `feedbackAuth` field #### Why it matters * This is the biggest trust-model change in v1.1: it removes pre-authorization friction and changes spam resistance approach. * Feedback submission is now direct (any client can call `giveFeedback()` directly). * Spam/Sybil protection is now enforced off-chain through indexing, filtering, and reputation aggregation. #### Concrete interface impact **pre-v1 (legacy)** `giveFeedback()`: ```solidity giveFeedback(uint256 agentId, uint8 score, bytes32 tag1, bytes32 tag2, string feedbackUri, bytes32 feedbackHash, bytes feedbackAuth) ``` **v1.1** `giveFeedback()`: ```solidity giveFeedback(uint256 agentId, uint8 score, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash) ``` *** ### 2. Tag Types Changed: bytes32 β†’ string β€” Feedback Registry #### What changed * **OnChain**: Contract interface now uses `string` for `tag1`, `tag2` (both in function params and event) * **OffChain**: JSON tags change from hex-encoded `bytes32` to plain strings #### Why it matters * Removes encoding/decoding complexity for both onchain and offchain implementations * Makes tags human-readable in events and off-chain data * Simpler for indexers and data consumers *** ### 3. FeedbackIndex Now Emitted in Event β€” Feedback Registry #### What changed * **pre-v1 (legacy)**: `feedbackIndex` was calculated by subgraph (tracking per-client-per-agent count) * **v1.1**: Contract emits `feedbackIndex` directly in the `NewFeedback` event #### Why it matters * Indexers no longer need to maintain and calculate feedback counts * `feedbackIndex` is now a first-class on-chain attribute * Simpler and more reliable feedback ordering per (client, agent) pair *** ## What Changed (Detailed) > **Scope Key:** > > * **\[OnChain]** = Changes to smart contract interface (function signatures, events) > * **\[OffChain]** = Changes to off-chain JSON feedback data structure only > * **\[Both]** = Changes affect both contract and JSON format ### 1. Tag Type Change: bytes32 β†’ string \[Both] β€” Feedback Registry **pre-v1 (legacy)** (hex-encoded tags): **OffChain JSON**: ```json { "tag1": "6465666900000000000000000000000000000000000000000000000000000000", "tag2": "616e616c7974696373000000000000000000000000000000000000000000000000" } ``` **OnChain Contract**: ```solidity // ReputationRegistry.giveFeedback() function giveFeedback(uint256 agentId, uint8 score, bytes32 tag1, bytes32 tag2, ...) ``` *** **v1.1** (plain string tags): **OffChain JSON**: ```json { "tag1": "defi", "tag2": "analytics" } ``` **OnChain Contract**: ```solidity // ReputationRegistry.giveFeedback() function giveFeedback(uint256 agentId, uint8 score, string tag1, string tag2, ...) ``` *** **Impact**: * βœ… **OnChain**: Function signature changes from `bytes32` to `string` parameters * βœ… **OnChain**: `NewFeedback` event now emits `string indexed indexedTag1, string tag1, string tag2` instead of `bytes32` (note: `indexedTag1` is indexed for efficient filtering, `tag1` provides the actual value) * βœ… **OffChain**: JSON tags no longer hex-encoded; use direct strings * βœ… Removes encoding/decoding complexity * βœ… Makes tags human-readable in events and logs *** ### 2. URI Naming: feedbackUri β†’ feedbackURI \[OffChain] β€” Feedback Registry This change affects only the **off-chain JSON data structure**. The onchain contracts already use `feedbackURI`. **pre-v1 (legacy)** OffChain JSON: ```json { "feedbackUri": "ipfs://QmXxx..." } ``` **v1.1** OffChain JSON: ```json { "feedbackURI": "ipfs://QmXxx..." } ``` **Why?** Matches standard camelCase for acronyms (Web3 convention): `feedbackURI` not `feedbackUri` **Impact**: * βœ… **OffChain Only**: JSON field name change in feedback data structure * βœ… Consistency with camelCase acronym conventions * βœ… Aligns with onchain contract naming *** ### 3. FeedbackAuth Removed (CRITICAL) \[Both] β€” Feedback Registry This is the most significant change affecting both the onchain contract interface and off-chain data structure. **pre-v1 (legacy)** - Pre-authorization flow required: **OffChain JSON**: ```json { "feedbackAuth": "0x1234567890abcdef...", "score": 95, "tag1": "defi" } ``` **OnChain Submission Flow**: 1. Client must first request authorization from the agent 2. Agent generates `feedbackAuth` signature (pre-approving this client) 3. Client calls `giveFeedback(..., bytes feedbackAuth)` with the signature 4. Contract validates the signature onchain **v1.1** - Direct submission (no pre-authorization): **OffChain JSON**: ```json { "score": 95, "tag1": "defi" } ``` **OnChain Submission Flow**: 1. Any client can directly call `giveFeedback(agentId, score, tag1, tag2, endpoint, feedbackURI, feedbackHash)` 2. No pre-authorization signature required 3. No `feedbackAuth` parameter in contract function **Impact**: * βœ… **OnChain**: `giveFeedback()` no longer includes `bytes feedbackAuth` parameter * βœ… **OffChain**: Feedback JSON no longer contains `feedbackAuth` field * βœ… Dramatically simplifies feedback submission flow * βœ… Removes agent-initiated authorization step * βœ… Spam/Sybil protection now handled off-chain (filtering, indexing, reputation-based ranking) **Migration**: * ❌ Remove all `feedbackAuth` signature generation code * ❌ Remove feedback authorization endpoints * βœ… Simplify submission to direct posting *** ### 4. New Endpoint Field \[Both] β€” Feedback Registry **pre-v1 (legacy)**: Not available **v1.1** - New optional field in both onchain and offchain: **OffChain JSON**: ```json { "endpoint": "https://agent.example.com", "score": 95, "tag1": "defi" } ``` **OnChain Contract Signature**: ```solidity function giveFeedback(uint256 agentId, uint8 score, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash) ``` **Purpose**: Optional string parameter to record which endpoint-URI was used by the client during the feedback submission process. **Examples**: * `"endpoint": "https://www.example-agent.com"` - Main agent service endpoint * `"endpoint": "https://api.example-agent.com/v2"` - Specific API version * `""` or omitted - No specific endpoint recorded **Impact**: * βœ… **OnChain**: `giveFeedback()` now includes `string endpoint` parameter * βœ… **OffChain**: Optional JSON field for endpoint URI * βœ… Allows tracking which agent endpoint-URI was involved in feedback submission * βœ… Useful for clients to reference which service version they used ### 5. FeedbackIndex Now Emitted in Event \[OnChain] β€” Feedback Registry This change affects only onchain contract behavior. There is no corresponding off-chain data change. **pre-v1 (legacy)** - Index calculated by indexer: * Subgraph maintained a `ClientAgentStats` table to track feedback count per client per agent * `feedbackIndex` was calculated as: incrementing counter for (agentId, clientAddress) pair * Indexers had to maintain this calculation logic **v1.1** - Index emitted directly by contract: **OnChain `NewFeedback` Event**: ```solidity event NewFeedback( uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, // ← Now emitted directly by contract (uint64) uint8 score, string indexed indexedTag1, // ← For efficient filtering (topic hash) string tag1, // ← Actual tag1 value string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash ); ``` **Impact**: * βœ… **OnChain Only**: Contract now emits `uint64 feedbackIndex` in `NewFeedback` event * βœ… No need for indexers to calculate feedback counts * βœ… Simpler indexing logic * βœ… `feedbackIndex` is now a first-class on-chain value * βœ… Guarantees correct sequencing of feedback per (agentId, clientAddress) pair *** ## Migration Checklist ### Phase 1: OffChain Data Format Updates * Update all feedback JSON objects to remove feedbackAuth field * Rename feedbackUri β†’ feedbackURI in all JSON occurrences * Convert tag values (hex-encoded β†’ plain strings) * If tags are hex-encoded bytes32, decode them to strings * Update tag parsing/serialization logic * Add optional endpoint field to feedback JSON where applicable * Update JSON schema validation to reflect v1.1 structure **Example (TypeScript)**: ```typescript // pre-v1 (legacy) Off-Chain Feedback Structure interface FeedbackPreV1 { feedbackAuth: string; // ❌ REMOVE feedbackUri: string; // ❌ RENAME to feedbackURI tag1: string; // Hex-encoded bytes32 tag2: string; // Hex-encoded bytes32 score: number; } // v1.1 Off-Chain Feedback Structure interface FeedbackV10 { feedbackURI: string; // βœ… Renamed endpoint?: string; // βœ… NEW (optional) tag1: string; // βœ… Plain string (no hex) tag2: string; // βœ… Plain string (no hex) score: number; } ``` **Example (Data Migration)**: ```json // pre-v1 (legacy) Feedback JSON { "agentRegistry": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "feedbackAuth": "0xabc123...", "score": 95, "tag1": "6465666900000000000000000000000000000000000000000000000000000000", "tag2": "616e616c7974696373000000000000000000000000000000000000000000000000", "feedbackUri": "ipfs://QmXxx...", "reasoning": "Great service" } // v1.1 Feedback JSON { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "score": 95, "tag1": "defi", "tag2": "analytics", "endpoint": "https://www.example-agent.com", "feedbackURI": "ipfs://QmXxx...", "reasoning": "Great service" } ``` ### Phase 2: Contract Integration Updates * Update contract interaction code to call new giveFeedback() signature * Remove feedbackAuth parameter from calls * Include new string endpoint parameter * Update tag1, tag2 parameter types from bytes32 to string * Update event handler for NewFeedback * Handle new feedbackIndex event parameter * Update tag type handling from bytes32 to string * Add endpoint field handling * Update ABI/interface definitions to reflect v1.1 contract changes **Example (Contract Call - pre-v1 (legacy) to v1.1)**: ```solidity // pre-v1 (legacy) giveFeedback( agentId, score, bytes32("defi"), // bytes32 tag bytes32("analytics"), // bytes32 tag "ipfs://QmXxx...", feedbackHash, feedbackAuthSignature // ❌ REMOVE ); // v1.1 giveFeedback( agentId, score, "defi", // βœ… string tag "analytics", // βœ… string tag "https://www.example-agent.com", // βœ… NEW endpoint "ipfs://QmXxx...", feedbackHash ); ``` ### Phase 3: Testing & Validation * Test giveFeedback() calls without feedbackAuth parameter * Verify tags are handled as strings in contract calls and events * Check feedbackURI field naming consistency * Test endpoint field handling (optional vs. empty string) * Verify feedbackIndex is correctly emitted in events * Test off-chain JSON validation against v1.1 schema * Verify hex-to-string tag decoding for existing pre-v1 (legacy) data * Test with both new v1.1 contract deployments *** ## Data Format Examples ### Off-Chain Feedback Comparison **pre-v1 (legacy)**: ```json { "agentRegistry": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "feedbackAuth": "0xabc123...", "score": 95, "tag1": "6465666900000000000000000000000000000000000000000000000000000000", "tag2": "616e616c7974696373000000000000000000000000000000000000000000000000", "feedbackUri": "ipfs://QmXxx...", "reasoning": "Great service" } ``` **v1.1**: ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 22, "clientAddress": "eip155:84532:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", "createdAt": "2025-12-20T12:00:00Z", "score": 95, "tag1": "defi", "tag2": "analytics", "endpoint": "https://api.example.com/v1", "feedbackURI": "ipfs://QmXxx...", "reasoning": "Great service" } ``` **Changes**: * βœ… Removed `feedbackAuth` field * βœ… Renamed `feedbackUri` β†’ `feedbackURI` * βœ… Converted tags from hex (bytes32) to plain strings * βœ… Added optional `endpoint` field * βœ… Added CAIP format for addresses (best practice) *** ## Implementation Phases ### Phase 1: Assessment & Planning * Read this guide fully * Assess impact on your code (contract interactions, data parsing) * Identify all code paths that handle feedback * Plan data migration if needed * Create v1.1 feature branch ### Phase 2: Implementation * Migrate off-chain JSON data format * Update contract interaction code for new giveFeedback() signature * Update event handlers for NewFeedback event * Update JSON schema validation * Update any data serialization/deserialization code ### Phase 3: Testing & Validation * Unit test contract interactions with new signatures * Integration test feedback submission flow * Validate JSON format against v1.1 schema * Test with v1.1 contract deployment ### Phase 4: Deployment * Deploy updated code * Migrate historical data (if needed) * Monitor feedback submission and events * Update documentation *** ## FAQ ### Q: What's the new `giveFeedback()` function signature? **A**: The v1.1 signature is: ```solidity function giveFeedback( uint256 agentId, uint8 score, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash ) external; ``` Key differences from pre-v1 (legacy): * No `feedbackAuth` parameter * `tag1`, `tag2` are now `string` (not `bytes32`) * New `endpoint` parameter (optional, can be empty string) * `feedbackUri` β†’ `feedbackURI` (in the off-chain data) ### Q: What does the new `feedbackIndex` mean? **A**: `feedbackIndex` is now emitted in the `NewFeedback` event and represents the sequential index of feedback for a specific (agentId, clientAddress) pair. It's auto-incremented by the contract. **v1.1 Event**: ```solidity event NewFeedback( uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, // ← Sequence number per (agent, client) uint8 score, string indexed indexedTag1, // ← For efficient filtering (topic hash) string tag1, // ← Actual tag1 value string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash ); ``` ### Q: Is the `endpoint` field required? **A**: No, it's optional. Use it if you want to track which URI endpoint-source was involved in the feedback submission. Can be an empty string if not needed. ### Q: How do I validate the new off-chain JSON format? **A**: Use this JSON Schema for v1.1 feedback validation: ```json { "type": "object", "required": ["agentRegistry", "agentId", "clientAddress", "createdAt", "score"], "properties": { "agentRegistry": { "type": "string", "description": "CAIP-2 format: eip155:chainId:0x..." }, "agentId": { "type": "integer" }, "clientAddress": { "type": "string", "description": "CAIP-10 format: eip155:chainId:0x..." }, "createdAt": { "type": "string", "format": "date-time", "description": "ISO 8601 UTC timestamp" }, "score": { "type": "integer", "minimum": 0, "maximum": 100, "description": "Feedback score 0–100" }, "tag1": { "type": "string", "description": "First classification tag (indexed on-chain)" }, "tag2": { "type": "string", "description": "Second classification tag" }, "endpoint": { "type": "string", "description": "Optional: agent endpoint URI used during interaction" }, "feedbackURI": { "type": "string", "description": "Off-chain data URI (ipfs://, https://, ar://, data:)" }, "feedbackHash": { "type": "string", "description": "Keccak256 hash of feedback data for integrity (bytes32 hex)" }, "reasoning": { "type": "string", "description": "Human-readable explanation for the feedback" } } } ``` *** ## References * [Feedback Data Profile (v1.1)](../02-feedback-standard.md) * [Official ERC-8004 Spec](https://eips.ethereum.org/EIPS/eip-8004) * [ERC-8004 Jan 2026 Spec Update](../../ref_codes/erc-8004-contracts/SpecsJan26Update.md) * [Contract Repository](https://github.com/erc-8004/erc-8004-contracts) *** **Document Version**: 1.0 **Last Updated**: January 9, 2026 --- --- url: /docs/official-specification/README.md --- # Official ERC-8004 Specification This directory contains the **official ERC-8004 normative specification**. ## Documents ### ERC-8004: Trustless Agents Standard **File**: [erc-8004-official.md](erc-8004-official.md) The authoritative Ethereum Improvement Proposal (EIP) for the ERC-8004 standard, defining: * Smart contract interfaces for agent registration, reputation, and validation * Onchain behavior requirements (normative) * Event structures and storage patterns * Upgrade mechanisms ## Relationship to This Project This project provides **community-maintained, non-normative guidance** that builds on the official ERC-8004 specification: | Aspect | Official EIP-8004 | This Project's Profiles | | ------------- | ------------------------------------ | -------------------------------------- | | **Authority** | Ethereum EIP process (normative) | Community guidelines (non-normative) | | **Scope** | Smart contract interfaces | Offchain data formats & best practices | | **Defines** | Onchain behavior (MUST requirements) | Offchain JSON recommendations (SHOULD) | | **Use** | Required for ERC-8004 compliance | Optional for interoperability | ## Key Distinction ### Official Specification (EIP-8004) * Defines smart contract `interface` and `events` * Specifies what MUST be stored onchain * Normative and binding for contract implementations **Example**: "The Reputation Registry MUST emit a `FeedbackSubmitted` event with these parameters..." ### This Project's Data Profiles * Recommends **offchain JSON structures** for metadata URIs * Suggests best practices for parsing and handling data * Non-normative and optional for adoption **Example**: "We recommend this JSON structure for `feedbackURI` content to improve interoperability..." ## Starting Points * **Implementing an ERC-8004 contract?** Read the [official specification](erc-8004-official.md) * **Building an explorer or indexer?** See [Data Profiles](../README.md) * **Publishing agent metadata?** See [Agent Metadata Profile](../01-agent-metadata-standard.md) * **Submitting feedback?** See [Feedback Data Profile](../02-feedback-standard.md) ## External Links * **Official EIP-8004**: [eips.ethereum.org/EIPS/eip-8004](https://eips.ethereum.org/EIPS/eip-8004) * **ERC-8004 Contracts**: [github.com/erc-8004/erc-8004-contracts](https://github.com/erc-8004/erc-8004-contracts) * **EIP Process**: [github.com/ethereum/EIPs](https://github.com/ethereum/EIPs) --- --- url: /v1/docs/official-specification/README.md --- # Official ERC-8004 Specification This directory contains the **official ERC-8004 normative specification**. ## Documents ### ERC-8004: Trustless Agents Standard **File**: [erc-8004-official.md](erc-8004-official.md) The authoritative Ethereum Improvement Proposal (EIP) for the ERC-8004 standard, defining: * Smart contract interfaces for agent registration, reputation, and validation * Onchain behavior requirements (normative) * Event structures and storage patterns * Upgrade mechanisms ## Relationship to This Project This project provides **community-maintained, non-normative guidance** that builds on the official ERC-8004 specification: | Aspect | Official EIP-8004 | This Project's Profiles | | ------------- | ------------------------------------ | -------------------------------------- | | **Authority** | Ethereum EIP process (normative) | Community guidelines (non-normative) | | **Scope** | Smart contract interfaces | Offchain data formats & best practices | | **Defines** | Onchain behavior (MUST requirements) | Offchain JSON recommendations (SHOULD) | | **Use** | Required for ERC-8004 compliance | Optional for interoperability | ## Key Distinction ### Official Specification (EIP-8004) * Defines smart contract `interface` and `events` * Specifies what MUST be stored onchain * Normative and binding for contract implementations **Example**: "The Reputation Registry MUST emit a `FeedbackSubmitted` event with these parameters..." ### This Project's Data Profiles * Recommends **offchain JSON structures** for metadata URIs * Suggests best practices for parsing and handling data * Non-normative and optional for adoption **Example**: "We recommend this JSON structure for `feedbackURI` content to improve interoperability..." ## Starting Points * **Implementing an ERC-8004 contract?** Read the [official specification](erc-8004-official.md) * **Building an explorer or indexer?** See [Data Profiles](../README.md) * **Publishing agent metadata?** See [Agent Metadata Profile](../01-agent-metadata-standard.md) * **Submitting feedback?** See [Feedback Data Profile](../02-feedback-standard.md) ## External Links * **Official EIP-8004**: [eips.ethereum.org/EIPS/eip-8004](https://eips.ethereum.org/EIPS/eip-8004) * **ERC-8004 Contracts**: [github.com/erc-8004/erc-8004-contracts](https://github.com/erc-8004/erc-8004-contracts) * **EIP Process**: [github.com/ethereum/EIPs](https://github.com/ethereum/EIPs) --- --- url: /docs/implementation/onchain-metadata-handling.md description: Best practices for parsing MetadataSet events and handling empty values --- ## Description Best practices for parsing on-chain metadata from `MetadataSet` events and merging with contract state and off-chain metadata. **Audience**: Backend developers, indexer authors, explorer builders ## Overview ERC-8004 supports **on-chain metadata** stored as key-value pairs via the `setMetadata(uint256 agentId, string key, bytes value)` function. This guide covers how to properly parse, decode, and merge this data. ## Empty Value Handling ### Problem When parsing on-chain metadata from `MetadataSet` events, empty hex values (`0x`, `0x0`) are ambiguous: * Are they valid values (empty string)? * Or do they indicate "not set" (absence of data)? ### Solution **Implementations SHOULD treat empty hex values as "not set" rather than valid values.** **Rationale**: Empty hex values indicate the absence of data, not a valid configuration. Treating them as empty strings can cause false conflicts. ### Implementation ```plaintext ALGORITHM: DecodeHexValue(hexValue) INPUT: hexValue - bytes value from MetadataSet event OUTPUT: decoded value or NULL BEGIN // Handle empty values IF hexValue = "0x" OR hexValue = "0x0" THEN RETURN NULL // Treat as "not set" END IF // Decode based on type (address, string, uint256, etc.) // ... type-specific decoding logic ... END ``` **Example** (Python): ```python def decode_hex_value(hex_value: str) -> Any: if not hex_value: return None # Handle empty value - return None to indicate "not set" if hex_value == "0x" or hex_value == "0x0": return None # βœ… Correct # NOT: return "" # ❌ Wrong # ... rest of decoding logic ... ``` ## Metadata Merging ### Three-Tier Precedence Order When multiple sources provide the same field, implementations SHOULD use this priority order: 1. **Contract State** (highest priority) * Direct contract getter functions (e.g., `agentWallet()`) * Authoritative current value set by owner 2. **On-chain Metadata** (medium priority) * `MetadataSet` event key-value pairs * Indexed fields, may be outdated 3. **Off-chain Metadata** (lowest priority) * AgentURI JSON content * Most flexible, least authoritative ### Merging Algorithm ```plaintext ALGORITHM: MergeMetadata(onchain, offchain, hardcoded) INPUT: - onchain: decoded on-chain metadata (from MetadataSet events) - offchain: off-chain metadata (from AgentURI) - hardcoded: contract state (from getters) OUTPUT: merged metadata with conflicts list BEGIN merged ← empty dict conflicts ← empty list // Step 1: Add off-chain data (lowest priority) FOR EACH key, value IN offchain DO IF value is NULL OR value = "" THEN CONTINUE // Skip empty values END IF merged[key] ← value END FOR // Step 2: Override with on-chain data (higher priority) FOR EACH key, value IN onchain DO IF value is NULL OR value = "" THEN CONTINUE // Skip empty values END IF IF key IN merged AND merged[key] β‰  value THEN conflicts.append({ type: "onchain_offchain_conflict", field: key, onchain_value: value, offchain_value: merged[key] }) END IF merged[key] ← value END FOR // Step 3: Override with hardcoded fields (highest priority) FOR EACH key, value IN hardcoded DO IF value is NULL OR value = "" THEN CONTINUE // Skip empty values END IF IF key IN merged AND merged[key] β‰  value THEN conflicts.append({ type: "hardcoded_override", field: key, hardcoded_value: value, overridden_value: merged[key] }) END IF merged[key] ← value END FOR RETURN (merged, conflicts) END ``` ## Conflict Detection ### Valid Conflicts Conflicts SHOULD only be reported when **non-empty values differ**: ```plaintext βœ… Valid Conflict: Contract State: agent_wallet = 0xaaaa (non-empty) Onchain Metadata: agent_wallet = 0xbbbb (non-empty, different) β†’ Report: WA081 "Contract state conflicts with on-chain metadata" βœ… Valid Conflict: Onchain Metadata: agent_wallet = 0xaaaa (non-empty) Offchain Metadata: agent_wallet = 0xbbbb (non-empty, different) β†’ Report: WA080 "Conflict between on-chain and off-chain metadata" ``` ### Not Conflicts Empty values SHOULD NOT trigger conflicts: ```plaintext ❌ Not a Conflict: Contract State: agent_wallet = 0xd5d6... (non-empty) Onchain Metadata: agent_wallet = 0x (empty β†’ NULL) β†’ No conflict (empty value is ignored) ❌ Not a Conflict: Onchain Metadata: agent_wallet = 0xaaaa (non-empty) Offchain Metadata: (field not present) β†’ No conflict (missing field is not a conflict) ``` ## Error Codes ### 8004scan Error Codes > **8004scan-specific**: The following error codes are used by 8004scan's validation system. Other implementations MAY use different codes. **WA080** - Warning * **Message**: "Conflict between on-chain and off-chain metadata" * **Severity**: Warning (parse succeeds) * **Fields**: `onchain_value`, `offchain_value` **WA081** - Warning * **Message**: "Contract state conflicts with on-chain metadata" * **Severity**: Warning (parse succeeds) * **Fields**: `contract_value`, `onchain_metadata_value` **IA050** - Info * **Message**: "Field value from contract state (on-chain metadata empty or not set)" * **Severity**: Info (informational only) * **Fields**: Varies by field (e.g., `agent_wallet`) * **Reason**: On-chain metadata is empty (`0x`) or not set, contract state value used ### Severity Guidelines | Level | Description | Action | | ----------- | ------------------------------------- | -------------- | | **Error** | Critical issues preventing parsing | Parse fails | | **Warning** | Functional issues, data inconsistency | Parse succeeds | | **Info** | Recommendations, best practices | Advisory only | **Rationale**: Metadata conflicts are warnings, not errors. The agent can still be indexed using the higher-priority value. ## Error Reporting ### Clear Source Identification Error messages SHOULD clearly identify which sources conflict: **Good Messages** βœ…: ```plaintext "Contract state conflicts with on-chain metadata: agentWallet" "Conflict between on-chain and off-chain metadata: agentWallet" ``` **Ambiguous Messages** ❌: ```plaintext "Conflict between on-chain and off-chain: agentWallet" // When contract state is involved, this is misleading ``` ### Error Structure ```json { "code": "WA081", "field": "agent_wallet", "message": "Contract state conflicts with on-chain metadata", "contract_value": "0xd5d6d96fa23455ec5e3c00633f85f364d3f5a291", "onchain_metadata_value": "0x1234567890abcdef1234567890abcdef12345678" } ``` ## Real-World Example ### Scenario: Agent with Empty On-chain Metadata ```plaintext Data Sources: Contract State (via getter): agentWallet = 0xd5d6d96fa23455ec5e3c00633f85f364d3f5a291 On-chain Metadata (MetadataSet): agentWallet = 0x (empty) Off-chain Metadata (AgentURI): (no agentWallet field) Processing: 1. decode_hex_value("0x") β†’ NULL (empty value) 2. merge_metadata(): - Step 1: Offchain - no agentWallet field - Step 2: Onchain - agentWallet = NULL, skipped (empty value) - Step 3: Hardcoded - agentWallet = 0xd5d6..., added Final Result: merged.agent_wallet = 0xd5d6d96fa23455ec5e3c00633f85f364d3f5a291 conflicts = [] (no conflicts) parse_status.status = "success" ``` **Before Fix** ❌: ```json { "status": "error", "errors": [ { "type": "metadata_conflict", "field": "agent_wallet", "message": "Conflict between on-chain and off-chain: agent_wallet", "onchain_value": "0xd5d6...", "offchain_value": "" } ] } ``` **After Fix** βœ…: ```json { "status": "success", "errors": [], "warnings": [], "info": [ { "code": "IA050", "field": "agent_wallet", "message": "Field value from contract state (on-chain metadata empty or not set)", "source": "contract_state" } ], "agent_wallet": "0xd5d6d96fa23455ec5e3c00633f85f364d3f5a291" } ``` ## Common Pitfalls ### Pitfall 1: Treating Empty Strings as Valid Values **Problem**: ```python if hex_value == "0x": return "" # ❌ Empty string participates in merging ``` **Solution**: ```python if hex_value == "0x": return None # βœ… NULL is filtered out ``` ### Pitfall 2: Not Filtering Empty Values in Merge **Problem**: ```python for key, value in onchain.items(): if value is None: # ❌ Only filters None continue ``` **Solution**: ```python for key, value in onchain.items(): if value is None or value == "": # βœ… Also filters empty strings continue ``` ### Pitfall 3: Ambiguous Error Messages **Problem**: ```python # When hardcoded value conflicts with on-chain metadata message = "Conflict between on-chain and off-chain" # ❌ Misleading ``` **Solution**: ```python if conflict_type == "hardcoded_override": message = "Contract state conflicts with on-chain metadata" # βœ… Clear else: message = "Conflict between on-chain and off-chain metadata" ``` ## Testing Checklist Implementations SHOULD test these scenarios: * βœ… Empty hex values (`0x`, `0x0`) return NULL * βœ… NULL values are filtered out in merge * βœ… Empty strings are filtered out in merge * βœ… No conflict when on-chain value is empty * βœ… Conflict reported when non-empty values differ * βœ… Contract state has highest priority * βœ… Error codes correctly distinguish conflict types * βœ… Error messages are clear and accurate ## Resources * [Agent Metadata Standard](../01-agent-metadata-standard.md) - Full schema specification * [Agent Metadata Parsing](agent-metadata-parsing.md) - Parser architecture and validation * [Error Codes](error-codes.md) - Complete error code reference (if available) * [EIP-8004 Specification](https://eips.ethereum.org/EIPS/eip-8004) - Official specification --- --- url: /QUICKSTART.md --- # Quick Start Guide This guide is for maintainers with access to the ERC-8004 documentation repository. ## Prerequisites * Node.js (v18 or higher) * npm (v9 or higher) * Git ## Setup 1. **Get repository access** Ask an 8004scan maintainer for access and the repository origin, then clone it: ```bash git clone cd 8004scan-best-practices ``` 2. **Install dependencies** ```bash make install ``` This will install: * VitePress (documentation framework) * npm packages (Prettier, markdownlint) 3. **Configure environment (Optional)** For remote development environments or custom hosts: ```bash # Copy example environment file cp .env.example .env # Edit .env and set your allowed hosts # VITE_ALLOWED_HOSTS=your-host.example.com,another-host.com ``` Default allowed hosts (if `.env` not set): * `localhost` * `.coder.altlayer.network` * `.8004scan.io` ## Development Workflow ### Preview Documentation Locally ```bash make dev # or npm run dev ``` The development server will start at `http://localhost:5173`. Changes will hot-reload automatically. **For remote development**: If you see "host not allowed" errors, set `VITE_ALLOWED_HOSTS` in `.env` with your development host. ### Format Markdown Files ```bash # Auto-format all Markdown files make format # Check formatting without modifying make format-check ``` ### Lint Markdown Files ```bash # Check for linting issues make lint # Auto-fix linting issues make lint-fix ``` ### Build Static Site ```bash make build ``` The built site will be in the `.vitepress/dist/` directory. ### Preview Built Site After building, you can preview the production build: ```bash make preview ``` The preview server will start at `http://localhost:4173`. ## Recommended Workflow Before committing changes: ```bash # 1. Format and lint make format && make lint-fix # 2. Preview changes make dev # 3. Build to ensure no errors make build # 4. Commit changes git add . git commit -m "Your commit message" ``` ## File Structure ```bash . β”œβ”€β”€ .vitepress/ # VitePress configuration β”‚ β”œβ”€β”€ config.mts # Site configuration β”‚ └── theme/ # Custom theme β”œβ”€β”€ docs/ # ERC-8004 standard documentation β”‚ β”œβ”€β”€ 00-CONVENTIONS.md # Naming conventions β”‚ β”œβ”€β”€ 01-*.md # Core standards β”‚ β”œβ”€β”€ extensions/ # Optional extensions β”‚ β”œβ”€β”€ implementation/ # Implementation guides β”‚ └── reference/ # Reference materials β”œβ”€β”€ index.md # Homepage (VitePress) β”œβ”€β”€ README.md # Documentation overview └── package.json # Dependencies and scripts ``` ## Available Commands Run `make help` to see all available commands: ```bash make help ``` ## Getting Help * Read [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines * Check [README.md](README.md) for documentation overview * Open an issue for questions or problems ## Next Steps 1. Explore the [documentation](README.md) 2. Review [contribution guidelines](CONTRIBUTING.md) 3. Start with [Conventions](docs/00-CONVENTIONS.md) Happy documenting! --- --- url: /docs/reference/real-world-examples.md description: Examples of agent metadata formats observed in production deployments --- ## Description This document provides examples of agent metadata formats observed in production deployments during the ERC-8004 legacy testnet phase (pre-v1, October-December 2025). > \[!NOTE] > This is a **non-normative reference document**. These patterns are provided for educational purposes and to help implementers understand real-world variations. For the official schema, see [Agent Metadata Standard](../01-agent-metadata-standard.md). > > \[!IMPORTANT] > **Field Name Update (Jan 2026)**: Examples below have been updated to use `services` instead of `endpoints` per the official EIP-8004 January 2026 update. Historical deployments may still use the legacy `endpoints` field name, which parsers should continue to support for backward compatibility. ## Data Source **Source**: ERC-8004 Legacy Testnet (pre-v1) **Analysis Date**: December 2025 **Sample Size**: 4,725 production agents See [Sources & References](sources.md) for detailed methodology. ## Observed Patterns ### Pattern 1: SDK Standard Format **Prevalence**: High (most compliant agents) **Source**: Official SDK implementations ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent Name", "description": "Description...", "image": "ipfs://CID", "active": true, "services": [ { "name": "A2A", "version": "0.3.0", "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 } ``` **Characteristics**: * Minimal, standards-compliant * SDK-generated * Storage: IPFS or Data URI (base64) *** ### Pattern 2: Extended Metadata Format **Prevalence**: Medium (specific communities) **Source**: Various ecosystem implementations ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent #12345678", "description": "Extended agent with custom attributes", "image": "https://example.com/avatar.jpg", "services": [ { "name": "Custom API", "version": "1.0.0", "endpoint": "https://api.example.com/v1", "description": "Custom API endpoint" }, { "name": "OASF", "version": "0.8", "endpoint": "ipfs://...", "skills": ["analytical_skills/data_analysis/blockchain_analysis"], "domains": ["technology/blockchain"] } ], "attributes": { "custom_field_1": "value1", "custom_field_2": "value2" }, "registrations": [ { "agentId": 123, "agentRegistry": "eip155:84532:0x..." } ], "supportedTrust": ["reputation", "crypto-economic"] } ``` **Characteristics**: * Custom `attributes` object for extended data * Additional trust models possible * Storage: HTTP(S) API endpoint **Parser Considerations**: * Accept `attributes` as custom extension * Unknown fields should be preserved (forward compatibility) *** ### Pattern 3: Non-Standard Data URI **Prevalence**: Low-medium **Source**: Various implementations ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent Name", "description": "Agent description", "image": "https://example.com/avatar.png", "services": [ { "name": "agentWallet", "endpoint": "eip155:11155111:0x..." } ], "registrations": [ { "agentId": 0, "agentRegistry": "eip155:11155111:0x..." } ], "supportedTrust": ["reputation"] } ``` **Peculiarity**: Some agents store this as `data:application/json;base64,{...}` but the payload is NOT base64-encoded (plain JSON). **Parser Strategy**: Detect `{` or `[` at start of "base64" payload, skip base64 decode, parse directly. *** ### Pattern 4: Minimal/Test Agents **Prevalence**: Medium (development/testing) ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Test Agent", "description": "Minimal test agent", "image": "https://example.com/test.png", "services": [], "registrations": [] } ``` **Issues**: * Empty `services` (agent not reachable) * Empty `registrations` (no on-chain link) **Parser Strategy**: Parse successfully, log warnings for missing data. *** ## Common Variations ### Version String Formats | Observed | Valid? | Notes | | -------------- | ------ | -------------------------------------- | | `"0.3.0"` | βœ“ | A2A semver format | | `"0.30"` | βœ“ | A2A semver (though `0.3.0` preferred) | | `"0.8.0"` | βœ“ | OASF without 'v' prefix | | `"v0.8.0"` | βœ“ | OASF with 'v' prefix (both acceptable) | | `"0.8.3"` | βœ“ | OASF latest 0.8.x | | `"2025-06-18"` | βœ“ | MCP date-based versioning | | `"2025-11-25"` | βœ“ | MCP latest spec (as of Nov 2025) | | `"2026-01-29"` | βœ“ | MCP future spec date | ### Image URL Formats | Format | Example | Notes | | -------- | ----------------------------- | ---------------------------- | | HTTPS | `https://example.com/img.png` | Common, mutable | | IPFS | `ipfs://Qm...` | Content-addressed, immutable | | Data URI | `data:image/png;base64,...` | Inline, on-chain | | Relative | `/uploads/avatar.jpg` | Requires base URL resolution | ### Trust Model Values | Value | Prevalence | Description | | ----------------- | ---------- | ------------------------ | | `reputation` | ~80% | On-chain feedback system | | `crypto-economic` | ~50% | Stake-based validation | | `tee-attestation` | ~20% | TEE oracle verification | | `social-graph` | ~5% | Custom (non-standard) | *** ## Migration from Custom Formats If you have existing agent metadata in a custom format, here's how to migrate: ### Field Mapping Example **Custom Format**: ```json { "agent_name": "MyAgent", "agent_description": "Does things", "avatar_url": "https://...", "api_endpoint": "https://..." } ``` **ERC-8004 Format**: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "MyAgent", "description": "Does things", "image": "https://...", "services": [ { "name": "MCP", "endpoint": "https://...", "version": "2025-06-18" } ] } ``` *** ## See Also * [Agent Metadata Standard](../01-agent-metadata-standard.md) - Official schema definition * [Agent Metadata Parsing Guide](../implementation/agent-metadata-parsing.md) - Parser implementation * [Sources & References](sources.md) - Data methodology --- --- url: /v1/docs/reference/real-world-examples.md description: Examples of agent metadata formats observed in production deployments --- ## Description This document provides examples of agent metadata formats observed in production deployments during the ERC-8004 legacy testnet phase (pre-v1, October-December 2025). > \[!NOTE] > This is a **non-normative reference document**. These patterns are provided for educational purposes and to help implementers understand real-world variations. For the official schema, see [Agent Metadata Standard](../01-agent-metadata-standard.md). ## Data Source **Source**: ERC-8004 Legacy Testnet (pre-v1) **Analysis Date**: December 2025 **Sample Size**: 4,725 production agents See [Sources & References](sources.md) for detailed methodology. ## Observed Patterns ### Pattern 1: SDK Standard Format **Prevalence**: High (most compliant agents) **Source**: Official SDK implementations ```json { "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.3.0", "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 } ``` **Characteristics**: * Minimal, standards-compliant * SDK-generated * Storage: IPFS or Data URI (base64) *** ### Pattern 2: Extended Metadata Format **Prevalence**: Medium (specific communities) **Source**: Various ecosystem implementations ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent #12345678", "description": "Extended agent with custom attributes", "image": "https://example.com/avatar.jpg", "endpoints": [ { "name": "Custom API", "version": "1.0.0", "endpoint": "https://api.example.com/v1", "description": "Custom API endpoint" }, { "name": "OASF", "version": "0.8", "endpoint": "ipfs://...", "skills": ["analytical_skills/data_analysis/blockchain_analysis"], "domains": ["technology/blockchain"] } ], "attributes": { "custom_field_1": "value1", "custom_field_2": "value2" }, "registrations": [ { "agentId": 123, "agentRegistry": "eip155:84532:0x..." } ], "supportedTrust": ["reputation", "crypto-economic"] } ``` **Characteristics**: * Custom `attributes` object for extended data * Additional trust models possible * Storage: HTTP(S) API endpoint **Parser Considerations**: * Accept `attributes` as custom extension * Unknown fields should be preserved (forward compatibility) *** ### Pattern 3: Non-Standard Data URI **Prevalence**: Low-medium **Source**: Various implementations ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "Agent Name", "description": "Agent description", "image": "https://example.com/avatar.png", "endpoints": [ { "name": "agentWallet", "endpoint": "eip155:11155111:0x..." } ], "registrations": [ { "agentId": 0, "agentRegistry": "eip155:11155111:0x..." } ], "supportedTrust": ["reputation"] } ``` **Peculiarity**: Some agents store this as `data:application/json;base64,{...}` but the payload is NOT base64-encoded (plain JSON). **Parser Strategy**: Detect `{` or `[` at start of "base64" payload, skip base64 decode, parse directly. *** ### Pattern 4: Minimal/Test Agents **Prevalence**: Medium (development/testing) ```json { "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": [] } ``` **Issues**: * Empty `endpoints` (agent not reachable) * Empty `registrations` (no on-chain link) **Parser Strategy**: Parse successfully, log warnings for missing data. *** ## Common Variations ### Version String Formats | Observed | Valid? | Notes | | -------------- | ------ | -------------------------------------- | | `"0.3.0"` | βœ“ | A2A semver format | | `"0.30"` | βœ“ | A2A semver (though `0.3.0` preferred) | | `"0.8.0"` | βœ“ | OASF without 'v' prefix | | `"v0.8.0"` | βœ“ | OASF with 'v' prefix (both acceptable) | | `"0.8.3"` | βœ“ | OASF latest 0.8.x | | `"2025-06-18"` | βœ“ | MCP date-based versioning | | `"2025-11-25"` | βœ“ | MCP latest spec (as of Nov 2025) | | `"2026-01-29"` | βœ“ | MCP future spec date | ### Image URL Formats | Format | Example | Notes | | -------- | ----------------------------- | ---------------------------- | | HTTPS | `https://example.com/img.png` | Common, mutable | | IPFS | `ipfs://Qm...` | Content-addressed, immutable | | Data URI | `data:image/png;base64,...` | Inline, on-chain | | Relative | `/uploads/avatar.jpg` | Requires base URL resolution | ### Trust Model Values | Value | Prevalence | Description | | ----------------- | ---------- | ------------------------ | | `reputation` | ~80% | On-chain feedback system | | `crypto-economic` | ~50% | Stake-based validation | | `tee-attestation` | ~20% | TEE oracle verification | | `social-graph` | ~5% | Custom (non-standard) | *** ## Migration from Custom Formats If you have existing agent metadata in a custom format, here's how to migrate: ### Field Mapping Example **Custom Format**: ```json { "agent_name": "MyAgent", "agent_description": "Does things", "avatar_url": "https://...", "api_endpoint": "https://..." } ``` **ERC-8004 Format**: ```json { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "MyAgent", "description": "Does things", "image": "https://...", "endpoints": [ { "name": "MCP", "endpoint": "https://...", "version": "2025-06-18" } ] } ``` *** ## See Also * [Agent Metadata Standard](../01-agent-metadata-standard.md) - Official schema definition * [Agent Metadata Parsing Guide](../implementation/agent-metadata-parsing.md) - Parser implementation * [Sources & References](sources.md) - Data methodology --- --- url: /docs/reference/README.md --- # Reference Materials This directory contains reference resources for understanding data sources, methodologies, and real-world examples. ## Documents ### Real-World Examples **File**: [real-world-examples.md](real-world-examples.md) Practical examples from production ERC-8004 deployments showing: * Agent metadata structures used in production * Feedback patterns from real interactions * Validation requests from actual validators * Common use cases and integration patterns **Use this when**: You need to see how the standards are actually used in practice *** ### Sources **File**: [sources.md](sources.md) Documents the data sources, methodologies, and references used throughout this project: * Data collection methodology * Production databases and networks analyzed * References to external standards (RFC, CAIP, ISO, etc.) * Version history and changelog **Use this when**: * You need to verify where specific recommendations come from * You're evaluating the project's evidence basis * You want to understand the data collection methodology *** ## Using These Resources ### For Learning & Understanding 1. Start with [Core Data Profiles](../README.md) 2. See [Real-World Examples](real-world-examples.md) for practical patterns 3. Check [Sources](sources.md) for underlying data and methodology ### For Validation & Verification 1. Check [Sources](sources.md) for data provenance 2. Review the methodology section for reproducibility 3. Visit external standards references for authoritative definitions ### For Contributing When proposing improvements: 1. Reference [Sources](sources.md) for existing data 2. Link to [Real-World Examples](real-world-examples.md) for precedent 3. Cite external standards where applicable *** ## Related Documentation * **Standards & Profiles**: [Data Profiles Overview](../README.md) * **Implementation Guides**: [Implementation Best Practices](../implementation/README.md) * **Official Specification**: [ERC-8004 Official](../official-specification/README.md) * **Conventions**: [Shared Conventions](../00-CONVENTIONS.md) --- --- url: /v1/docs/reference/README.md --- # Reference Materials This directory contains reference resources for understanding data sources, methodologies, and real-world examples. ## Documents ### Real-World Examples **File**: [real-world-examples.md](real-world-examples.md) Practical examples from production ERC-8004 deployments showing: * Agent metadata structures used in production * Feedback patterns from real interactions * Validation requests from actual validators * Common use cases and integration patterns **Use this when**: You need to see how the standards are actually used in practice *** ### Sources **File**: [sources.md](sources.md) Documents the data sources, methodologies, and references used throughout this project: * Data collection methodology * Production databases and networks analyzed * References to external standards (RFC, CAIP, ISO, etc.) * Version history and changelog **Use this when**: * You need to verify where specific recommendations come from * You're evaluating the project's evidence basis * You want to understand the data collection methodology *** ## Using These Resources ### For Learning & Understanding 1. Start with [Core Data Profiles](../README.md) 2. See [Real-World Examples](real-world-examples.md) for practical patterns 3. Check [Sources](sources.md) for underlying data and methodology ### For Validation & Verification 1. Check [Sources](sources.md) for data provenance 2. Review the methodology section for reproducibility 3. Visit external standards references for authoritative definitions ### For Contributing When proposing improvements: 1. Reference [Sources](sources.md) for existing data 2. Link to [Real-World Examples](real-world-examples.md) for precedent 3. Cite external standards where applicable *** ## Related Documentation * **Standards & Profiles**: [Data Profiles Overview](../README.md) * **Implementation Guides**: [Implementation Best Practices](../implementation/README.md) * **Official Specification**: [ERC-8004 Official](../official-specification/README.md) * **Conventions**: [Shared Conventions](../00-CONVENTIONS.md) --- --- url: /docs/extensions/solana-support.md --- # Solana Chain Support > **Extension Type**: Chain Adaptation > **Status**: Draft > **Version**: 0.1.0 > **Authors**: 8004scan Team ## Overview This extension defines how ERC-8004 standards apply to the Solana blockchain. Solana uses different address formats, signature algorithms, and NFT standards compared to EVM chains. This document covers the necessary adaptations for agent registration, feedback submission, and authentication on Solana. ## 1. Chain Identifiers ### CAIP-2: Blockchain ID Solana networks use the `solana` namespace with the first 32 bytes of the genesis block hash (base58-encoded) as the CAIP-2 reference: ```text solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp β†’ Solana Mainnet solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 β†’ Solana Devnet ``` > Note: Solana Testnet is not used in production. ### CAIP-10: Account Address Solana addresses are base58-encoded Ed25519 public keys (32 bytes, 32-44 characters): ```text solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:Aqq2ZKnzXpsR4S18biMnJVEXVecgqU4Szi6rduszF8Sn solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1:2KmHw8VbShuz9xfj3ecEjBM5nPKR5BcYHRDSFfK1286t ``` ### CAIP-10 for Program Addresses Solana programs (equivalent to smart contracts) are referenced by their Program ID: ```text solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:8oo48pya1SZD23ZhzoNMhxR2UGb8BRa41Su4qP9EuaWm ``` ## 2. Agent Identity on Solana ### NFT Standard: Metaplex Core On Solana, ERC-8004 agents are represented as [Metaplex Core](https://developers.metaplex.com/core) assets instead of ERC-721 NFTs. | Concept | EVM (ERC-721) | Solana (Metaplex Core) | | -------------------- | ------------------------- | ----------------------------------------- | | Token standard | ERC-721 | Metaplex Core Asset | | Canonical identifier | `tokenId` (uint256) | `asset` pubkey (base58) | | Numeric identifier | `tokenId` (sequential) | `globalId` (sequential, indexer-assigned) | | Contract/Program | Registry contract address | Program ID | | Owner | `ownerOf(tokenId)` | Asset owner field | | Metadata pointer | `tokenURI(tokenId)` | `agentURI` on-chain field | | Collection | N/A | Metaplex Collection | ### Agent Registry Reference ```text # EVM format eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55 # Solana format solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:8oo48pya1SZD23ZhzoNMhxR2UGb8BRa41Su4qP9EuaWm ``` The agent metadata file (Registration File) follows the same JSON schema as EVM agents. Only the `registrations` array entry differs. ### Solana Agent Identifier Strategy Solana agents have two identifiers that serve different purposes: | Identifier | Type | Source | Purpose | | ------------------------- | ---------------------- | ---------------------------- | ------------------------------------- | | **Asset pubkey** (base58) | `string` (32-44 chars) | On-chain Metaplex Core asset | Canonical, immutable, globally unique | | **Global ID** (numeric) | `bigint` (sequential) | Indexer DB sequence trigger | Display-compatible, EVM-compatible | **Key points**: 1. **Asset pubkey** is the canonical Solana agent identifier β€” it is the on-chain NFT address and is immutable once created. 2. **Global ID** (`globalId` / `agentid` in the indexer GraphQL) is a sequential auto-increment number assigned by the indexer's PostgreSQL trigger on agent creation. It provides EVM-compatible numeric addressing (e.g., `#001`, `#042`) for display and URL compatibility. 3. Global ID is **stable once assigned** (no shifting when new agents register), but **not guaranteed consistent across independent indexer instances** β€” re-indexing from scratch may re-assign numbers. 4. API endpoints and URLs SHOULD accept both formats and auto-detect: * Numeric string β†’ lookup by `globalId` / `token_id` * Non-numeric string β†’ lookup by asset pubkey / `agent_id` 5. Frontend URLs and display SHOULD prefer the base58 asset pubkey for Solana agents, truncating to 7-8 characters when space is limited (e.g., `84bgovN...`). **GraphQL field mapping** (indexer β†’ backend): | Indexer GraphQL | Backend DB | Description | | -------------------- | ---------- | --------------------------------------- | | `agentid` | `token_id` | Sequential global ID (bigint) | | `agentidFormatted` | β€” | Display format: `#001`, `#042` | | `solana.assetPubkey` | `agent_id` | Base58 asset pubkey (canonical) | | `agentId` | β€” | Legacy hash-derived uint64 (deprecated) | > **Note**: The indexer also exposes `agentId` (camelCase), a hash-derived uint64 from the first 8 bytes of the asset pubkey. This field is **deprecated** β€” use `agentid` (lowercase) for numeric identifiers. ## 3. Address and Transaction Formats ### Comparison Table | Property | EVM | Solana | | ---------------- | ------------------------------------------- | ------------------------------ | | Address encoding | Hex with `0x` prefix | Base58 (no prefix) | | Address length | 42 chars (`0x` + 40 hex) | 32-44 chars (base58) | | Raw address size | 20 bytes | 32 bytes | | Case sensitivity | Case-insensitive (EIP-55 checksum optional) | **Case-sensitive** | | Transaction hash | 66 chars (`0x` + 64 hex) | 87-88 chars (base58 signature) | | Block identifier | Block number (uint64) | Slot number (uint64) | ### Validation Rules **Solana Address**: * Base58-encoded string (alphabet: `123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz`) * Decodes to exactly 32 bytes * Case-sensitive β€” do NOT apply `.toLowerCase()` or `.toUpperCase()` **Solana Transaction Signature**: * Base58-encoded Ed25519 signature * 87-88 characters * Decodes to 64 bytes ## 4. Content Hashing ### Hash Algorithm Differences | Property | EVM (ERC-8004 v1) | Solana (SEAL v1) | | ------------- | ------------------- | ------------------------ | | Algorithm | Keccak-256 | SHA-256 | | Output format | `0x` + 64 hex chars | 64 hex chars (no prefix) | | Output length | 66 chars | 64 chars | | Hash chain | Simple content hash | Running digest chain | ### SEAL v1 (Solana Event Authenticity Layer) Solana feedback uses SEAL v1 for tamper-proof hash chains: ```text feedback_hash = SHA-256(feedback_content) running_digest = SHA-256(previous_digest + feedback_hash) ``` This creates an append-only, verifiable chain of feedback events per agent+client pair. ## 5. Authentication ### Signature Algorithm | Property | EVM | Solana | | ---------------- | ----------------------- | ------------------------- | | Algorithm | ECDSA (secp256k1) | Ed25519 | | Signature format | `0x` + hex (130 chars) | Base58 (~88 chars) | | Message signing | EIP-191 `personal_sign` | `signMessage` (raw bytes) | | Smart wallet | ERC-1271 / ERC-6492 | N/A (no smart wallets) | ### Sign-In with Solana (SIWS) Message format for wallet authentication: ```text 8004scan wants you to sign in with your Solana account: Aqq2ZKnzXpsR4S18biMnJVEXVecgqU4Szi6rduszF8Sn Sign this message to authenticate with 8004scan. Nonce: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4 ``` Verification uses Ed25519 `VerifyKey` from the wallet's public key. ## 6. Feedback on Solana ### SEAL v1 Fields Solana feedback includes additional fields from the SEAL v1 protocol: | Field | Type | Description | | --------------- | ------------- | ------------------------------------ | | `value` | int64 | Raw metric value | | `valueDecimals` | uint8 (0-6) | Decimal places for value | | `score` | uint8 (0-100) | ATOM trust-weighted score (optional) | | `feedbackHash` | hex string | SHA-256 hash (64 chars, no `0x`) | | `runningDigest` | bytes | Hash chain digest | | `isRevoked` | boolean | Revocation status | ### ATOM Trust Metrics The [ATOM engine](https://github.com/QuantuLabs/atom-engine) computes on-chain trust scores for agents: | Metric | Range | Description | | ---------------- | ------- | -------------------------- | | `trustTier` | 0-4 | Overall trust level | | `qualityScore` | 0-10000 | Feedback quality aggregate | | `confidence` | 0-10000 | Statistical confidence | | `riskScore` | 0-100 | Sybil/manipulation risk | | `diversityRatio` | 0-255 | Unique reviewer diversity | These metrics are computed on-chain and available through the Solana indexer's GraphQL API as the `solana` extension on Agent and Feedback types. ## 7. Payment Proof Format ### SOL Payment ```json { "proofOfPayment": { "fromAddress": "D9bMDMbJungXQrE8n6ZsM3r6ZQLFTzygmsQL7yzGMDHw", "toAddress": "2KmHw8VbShuz9xfj3ecEjBM5nPKR5BcYHRDSFfK1286t", "chainId": "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", "txSignature": "5piJm888s7beTTrB9JuCR5WFvNxXHN78C9ifGEokTucoQy5mb6bKg3e6Fkiv8RznZG2NmzENBWUru5yUGbqMiTMp", "amount": "1000000000", "currency": "SOL", "decimals": 9 } } ``` > Note: Solana uses `txSignature` (base58, 87-88 chars) instead of `txHash` (hex, 66 chars). The `amount` is in lamports (1 SOL = 10^9 lamports). ### SPL Token Payment ```json { "proofOfPayment": { "fromAddress": "D9bMDMbJungXQrE8n6ZsM3r6ZQLFTzygmsQL7yzGMDHw", "toAddress": "2KmHw8VbShuz9xfj3ecEjBM5nPKR5BcYHRDSFfK1286t", "chainId": "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", "txSignature": "53i5Ymuosn6RduaxLw8Bx1P8XMrnzBRj7EJKdmNLnMtmN9WL45gjzq3jRQupTfhBP7MEghM9TUkhTq3zWz8gkB74", "amount": "1000000", "currency": "USDC", "tokenMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "decimals": 6 } } ``` ## 8. Cross-Chain Agent Registration Agents can be registered on both EVM and Solana chains simultaneously. The registration file's `registrations` array includes entries for each chain: ```json { "name": "My Cross-Chain Agent", "registrations": [ { "agentId": 42, "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55" }, { "agentId": 7, "agentRegistry": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:8oo48pya1SZD23ZhzoNMhxR2UGb8BRa41Su4qP9EuaWm" } ] } ``` The `registrations` array uses a uniform schema across all chains: `agentId` + `agentRegistry` (CAIP-10 string). On EVM, `agentId` is a sequential uint256 token ID. On Solana, the `agentId` in the registration file SHOULD be the numeric `globalId` (sequential auto-increment from the indexer) for cross-chain consistency. Implementations MUST also support resolving agents by base58 asset pubkey for native Solana addressing. ## 9. Implementation Notes ### Address Normalization ```python # EVM: case-insensitive, normalize to lowercase address = evm_address.lower() # Solana: case-sensitive, DO NOT normalize address = solana_address # Keep as-is ``` ### Storage Considerations | Field | EVM Sizing | Solana Sizing | Recommended | | ---------------- | ---------- | -------------------- | ---------------------- | | Address | 42 chars | 44 chars | String(50) | | Transaction hash | 66 chars | 88 chars | String(100) | | Content hash | 66 chars | 64 chars | String(66) β€” fits both | | Feedback ID | ~40 chars | 91 chars (composite) | String(150) | ### Validation Helper ```python import base58 def is_valid_solana_address(address: str) -> bool: """Validate Solana address: base58-encoded, decodes to 32 bytes.""" try: decoded = base58.b58decode(address) return len(decoded) == 32 except Exception: return False ``` ## 10. References * [CAIP-2 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) * [CAIP-10 Specification](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md) * [Metaplex Core Documentation](https://developers.metaplex.com/core) * [ATOM Engine](https://github.com/QuantuLabs/atom-engine) β€” On-chain trust scoring * [SEAL v1](https://github.com/QuantuLabs/8004-solana) β€” Solana Event Authenticity Layer * [Solana Genesis Hash (CAIP-2)](https://namespaces.chainagnostic.org/solana/caip2) β€” CAIP-2 namespace definition for Solana * [Sign-In with Solana](https://github.com/nichelikealope/siws) β€” Authentication standard --- --- url: /docs/reference/sources.md description: Source tracking and references for ERC-8004 documentation --- ## Description Source tracking for ERC-8004 standards documentation > **Data Source Notice**: Statistical data in this documentation is derived from the **ERC-8004 Legacy Testnet (pre-v1)**, collected during December 2025. This data reflects testnet behavior and may differ from mainnet patterns once ERC-8004 v1.1 contracts are widely deployed. ## Document Structure This directory contains three comprehensive standards documents based on the official EIP-8004 specification and real-world production data: 1. **[Agent Metadata Standard](../01-agent-metadata-standard.md)** - AgentURI offchain data format 2. **[Feedback Standard](../02-feedback-standard.md)** - Reputation Registry offchain data format 3. **[Validation Standard](../03-validation-standard.md)** - Validation Registry offchain data format All documents positioned as **"8004scan's official supplementary recommended standards for ERC-8004"**. ## Primary Sources ### 1. Official ERC-8004 Specification **Organization**: Ethereum Foundation **Document**: EIP-8004: Trustless Agents **URL**: https://eips.ethereum.org/EIPS/eip-8004 **Status**: Peer Review (as of 2025-12-20) **Reference Repository**: * **Repo**: https://github.com/erc-8004/erc-8004-contracts * **Key Files**: * `ERC8004SPEC.md` - Complete technical specification * `contracts/` - Reference implementation contracts * `README.md` - Overview and deployment info **What We Used**: * AgentURI metadata schema (required/recommended/optional fields) * Reputation Registry feedback structure * Validation Registry request/response structure * Onchain metadata key-value specification * Trust model definitions (reputation, crypto-economic, tee-attestation) * Contract interface specifications ### 2. Agent0 SDK Documentation **Organization**: Agent0 Project (ERC-8004 reference implementation) **Repository**: https://github.com/agent0/agent0 (assumed - verify actual URL) **Documentation Site**: https://docs.agent0.xyz/ (assumed - verify actual URL) **Key Documents**: * `1-welcome-1-4-erc-8004.md` - ERC-8004 overview and integration * `2-usage-2-2-configure-agents.md` - Agent configuration guide * `2-usage-2-3-registration-ipfs.md` - IPFS registration workflow * `5-reference-5-2-agent.md` - Agent API reference **What We Used**: * Standard agent metadata format (type, endpoints, registrations) * MCP and A2A endpoint specifications * IPFS storage patterns * Timestamp field usage (`createdAt`, `updatedAt`) * Feedback submission patterns * Validation request/response patterns ### 3. ERC-8004 Best Practices Guide **Organization**: ERC-8004 Community **Repository**: https://github.com/erc-8004/best-practices (assumed - verify) **Document**: `README.md` - "4 Golden Rules for Agent Registration" **What We Used**: * Rule 1: Name, Image, Description importance * Rule 2: Endpoint types and formats (MCP, A2A, OASF, ENS, DID, agentWallet) * Rule 3: OASF skills and domains taxonomy usage * Rule 4: Registrations array bidirectional verification * x402 support flag * Active status flag ### 4. OASF (Open Agentic Schema Framework) **Organization**: agntcy (now Linux Foundation) **Repository**: https://github.com/agntcy/oasf **Version**: v0.8.0 **Schema Browser**: https://schema.oasf.outshift.com/0.8.0 **What We Used**: * Skills taxonomy structure (categories/subcategories) * Domains taxonomy structure * OASF endpoint format and version specification * Recommended skills for blockchain agents * Recommended domains for financial/technical agents **Resources**: * [All Skills](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * [All Domains](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 5. CAIP Standards **Organization**: Chain Agnostic Improvement Proposals (ChainAgnostic) **Repository**: https://github.com/ChainAgnostic/CAIPs **CAIP-2: Blockchain ID Specification**: * **URL**: https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md * **Status**: Final (August 2021) * **What We Used**: * `namespace:chainId:reference` format for chain IDs * `eip155` namespace for EVM chains * Usage in `agentRegistry`, `validatorAddress` fields **CAIP-10: Account ID Specification**: * **URL**: https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md * **Status**: Final * **What We Used**: * `namespace:chainId:address` format for account IDs * Usage in `agentWallet` endpoint, `clientAddress` field * Character set restrictions ### 6. Protocol Documentation **MCP (Model Context Protocol)**: * **URL**: https://modelcontextprotocol.io/ * **Standard Version**: 2025-06-18 * **What We Used**: MCP endpoint structure, tools, prompts, resources **A2A (Agent-to-Agent Protocol)**: * **URL**: https://a2a.to/ * **Standard Version**: v0.3.0 * **What We Used**: A2A endpoint structure, agent card format, skills taxonomy ### 7. Community Resources **Awesome ERC-8004**: * **Repository**: https://github.com/sudeepb02/awesome-erc8004 * **What We Used**: Community project patterns, real-world implementation examples **Trustless Agents Reference Implementation**: * **Repository**: https://github.com/ChaosChain/trustless-agents-erc-ri * **Organization**: Ch40s Chain / ChaosChain * **What We Used**: Contract deployment patterns, spec compliance checklist ## Real-World Data Sources ### 8. Production Agent Metadata **Organization**: 8004scan Project **Data Collection Date**: 2025-12-19 **Sample Size**: 400 agents (8.5% of 4,725 total with metadata) **Collection Method**: ```sql SELECT chain_id, agent_id, metadata_uri, metadata_json, metadata_parse_status, metadata_parse_warnings FROM agents WHERE metadata_json IS NOT NULL ORDER BY created_at DESC LIMIT 400; ``` **Key Statistics** (Legacy Testnet pre-v1, December 2025): * URI types: IPFS 51%, HTTP 22%, Data URI 18% * Endpoint adoption: A2A 85%, MCP 75%, OASF 60% * Parse success: 69.9% (including warnings), 58.1% perfect * Common issues: ~15% empty endpoints, ~30% null agentId **OASF Taxonomy Usage** (Top 5 by adoption): Skills: 1. `natural_language_processing/natural_language_generation/summarization` (40%) 2. `tool_interaction/api_schema_understanding` (35%) 3. `multi_modal/image_processing/text_to_image` (30%) 4. `natural_language_processing/information_retrieval_synthesis/search` (28%) 5. `tool_interaction/workflow_automation` (25%) Domains: 1. `technology/blockchain` (45%) 2. `finance_and_business/finance` (35%) 3. `technology/software_engineering/apis_integration` (30%) 4. `technology/blockchain/cryptocurrency` (28%) 5. `media_and_entertainment/content_creation` (25%) **Trust Model Adoption**: * `reputation`: 80% of agents * `crypto-economic`: 50% of agents * `tee-attestation`: 20% of agents **Documented Patterns**: 1. Agent0 SDK Standard Format 2. Alias AI Star Card Format 3. ChaosChain Studio Format 4. Minimal/Test Agents ### 9. Production Validation Data **Organization**: 8004scan Project **Data Collection Date**: 2025-12-20 **Sample Size**: 8,219 validation records (Base Sepolia) **Key Findings**: * **100% Groth16 zkSNARK proofs** (8,219 records) * No ERC-8004 standard format validations (yet) * Circuit: `zyfi-rebalancing-validation` (ZyFi protocol) * All contain: `proof.pi_a/pi_b/pi_c`, `publicSignals`, `verifierAddress` **Implications**: * Led to design of three-level format compatibility system * Groth16 recognized as Level 2 (Known Custom Format) * Migration guides created for Groth16 β†’ ERC-8004 standard ### 10. v1 Frontend Implementation **Organization**: 8004scan v1 Project **Data**: v1 frontend code and patterns **Key Discoveries**: * **Attachment Pattern**: Flexible evidence system supporting any file type * Upload methods: File upload, JSON paste, manual URI * Metadata structure: `name`, `uri`, `mimeType`, `size`, `description`, `uploadedAt` * Use cases: Security audits (PDF), test results (JSON/CSV), screenshots, videos **Impact**: * Integrated attachment pattern into Feedback and Validation standards * Documented best practices for evidence collection * Created migration examples ## Synthesis Methodology ### Step 1: Official Spec Analysis 1. Read EIP-8004 specification in full 2. Extract schema definitions (required/recommended/optional) 3. Document contract interfaces 4. Note trust model specifications ### Step 2: Reference Implementation Review 1. Study Agent0 SDK documentation 2. Identify standard patterns and conventions 3. Extract endpoint format specifications 4. Document IPFS storage patterns ### Step 3: Community Best Practices Integration 1. Review "4 Golden Rules" from best practices guide 2. Integrate OASF taxonomy usage 3. Document x402 and active flags 4. Cross-reference with CAIP standards ### Step 4: Real-World Data Analysis **Agent Metadata (4,725 agents)**: 1. Collect 400 production samples 2. Categorize by pattern (4 major patterns) 3. Calculate adoption statistics 4. Identify common issues and edge cases 5. Document non-standard but common fields **Validation Data (8,219 validations)**: 1. Analyze all validation records on Base Sepolia 2. Identify dominant format (100% Groth16) 3. Document custom proof structures 4. Design three-level compatibility system 5. Create migration guides **v1 Frontend Analysis**: 1. Review v1 attachment implementation 2. Extract reusable patterns 3. Document best practices 4. Integrate into new standards ### Step 5: Validation Rule Derivation **Agent Metadata**: * **Level 1 (Required)**: From EIP-8004 spec + ERC-721 compatibility * **Level 2 (Endpoints)**: From best practices + real-world usage * **Level 3 (Registrations)**: From EIP-8004 + CAIP standards * **Level 4 (Trust Models)**: From EIP-8004 + community extensions * **Level 5 (Status Fields)**: From best practices + real-world usage **Validation Format**: * **Level 1 (ERC-8004 Standard)**: From official spec + suggested improvements * **Level 2 (Known Custom)**: From production data analysis (Groth16) * **Level 3 (Unknown)**: Fallback for unrecognized formats ### Step 6: Documentation Structure Design 1. Separate feedback and validation standards 2. Create professional developer-facing documents 3. Position as "supplementary recommended standards" 4. Add implementation guides and references 5. Include migration guides for existing formats ## Update Process When updating these documents in the future: ### 1. Check Official Sources * \[ ] Review EIP-8004 specification for changes * \[ ] Check agent0 SDK documentation updates * \[ ] Verify OASF taxonomy version (currently v0.8.0) * \[ ] Review CAIP standards for updates * \[ ] Check MCP/A2A protocol versions ### 2. Collect Fresh Data * \[ ] Export latest agent samples from database * \[ ] Export latest validation samples * \[ ] Export latest feedback samples (when available) * \[ ] Run statistical analysis on full datasets * \[ ] Identify new patterns or changes in adoption ### 3. Identify Changes * \[ ] Compare new data with previous baseline * \[ ] Document any schema drift * \[ ] Note new common fields or patterns * \[ ] Identify deprecated patterns * \[ ] Check for new trust models or endpoint types ### 4. Update Documentation * \[ ] Revise standard documents for spec changes * \[ ] Update statistics and examples * \[ ] Add new patterns to implementation guides * \[ ] Update parser validation rules if needed * \[ ] Revise migration guides ### 5. Version Control * \[ ] Update "Last Updated" date in all documents * \[ ] Note version changes in this sources.md * \[ ] Git commit with clear message describing changes * \[ ] Tag release if major update (e.g., v3.0) ## Documentation Coverage | Standard | Status | Data Sources | Real-World Samples | | ------------------ | ----------- | ------------------------------- | ------------------ | | **Agent Metadata** | βœ… Complete | EIP-8004 + Agent0 + OASF + CAIP | 400 agents | | **Feedback** | βœ… Complete | EIP-8004 + v1 frontend | v1 patterns | | **Validation** | βœ… Complete | EIP-8004 + production data | 8,219 validations | **Implementation Guides**: * βœ… Agent Metadata Parsing * βœ… Feedback Best Practices * βœ… Validation Best Practices **Reference Materials**: * βœ… Sources & References (this document) ## Known Format Variants ### Agent Metadata * **Standard**: Agent0 SDK format (most common) * **Custom**: Alias AI Star Card, ChaosChain Studio * **Edge Cases**: Empty endpoints, null agentId, version typos ### Validation * **Standard**: ERC-8004 format (0% adoption currently) * **Custom Level 2**: Groth16 zkSNARK (100% of production data) * **Future**: PLONK, STARK (designed but not yet seen) ### Feedback * **Standard**: ERC-8004 format * **Extension**: v1 attachment pattern * **Protocol Fields**: A2A, MCP, x402 specific fields ## Contact and Maintenance **Primary Maintainer**: 8004scan Development Team **Documentation Owner**: Backend Team **Review Frequency**: Monthly **Next Scheduled Review**: 2026-01-20 **For Updates**: 1. Check official sources listed above 2. Collect fresh production data 3. Follow update process in this document 4. Update version and date in all documents **For Questions**: * **Specification interpretation** β†’ Refer to EIP-8004 official spec * **Implementation patterns** β†’ Refer to Agent0 SDK docs * **Real-world usage** β†’ Refer to production data analysis * **CAIP formats** β†’ Refer to ChainAgnostic CAIPs repo * **OASF taxonomy** β†’ Refer to OASF v0.8.0 schema browser ## References Summary | Source | Organization | Type | URL | | --------------------------- | ----------------------- | --------------- | ----------------------------------------------------------------- | | **EIP-8004** | Ethereum Foundation | Official Spec | https://eips.ethereum.org/EIPS/eip-8004 | | **erc-8004-contracts** | ERC-8004 Project | Reference Impl | https://github.com/erc-8004/erc-8004-contracts | | **agent0 docs** | Agent0 Project | SDK Docs | https://docs.agent0.xyz/ | | **best-practices** | ERC-8004 Community | Guide | https://github.com/erc-8004/best-practices | | **OASF v0.8.0** | agntcy/Linux Foundation | Taxonomy | https://github.com/agntcy/oasf | | **CAIP-2** | ChainAgnostic | Standard | https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md | | **CAIP-10** | ChainAgnostic | Standard | https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md | | **MCP Protocol** | Model Context Protocol | Protocol Docs | https://modelcontextprotocol.io/ | | **A2A Protocol** | Agent-to-Agent | Protocol Docs | https://a2a.to/ | | **awesome-erc8004** | Community | Resource List | https://github.com/sudeepb02/awesome-erc8004 | | **trustless-agents-erc-ri** | ChaosChain | Reference Impl | https://github.com/ChaosChain/trustless-agents-erc-ri | | **8004scan Production DB** | This Project | Real-world Data | 4,725 agents, 8,219 validations | | **8004scan v1 Frontend** | This Project | Implementation | Attachment pattern | --- --- url: /legacy-pre-v1/docs/reference/sources.md description: Source tracking and references for ERC-8004 documentation --- ## Description Source tracking for ERC-8004 standards documentation ## Document Structure This directory contains three comprehensive standards documents based on the official EIP-8004 specification and real-world production data: 1. **[Agent Metadata Standard](../01-agent-metadata-standard.md)** - AgentURI offchain data format 2. **[Feedback Standard](../02-feedback-standard.md)** - Reputation Registry offchain data format 3. **[Validation Standard](../03-validation-standard.md)** - Validation Registry offchain data format All documents positioned as **"8004scan's official supplementary recommended standards for ERC-8004"**. ## Primary Sources ### 1. Official ERC-8004 Specification **Organization**: Ethereum Foundation **Document**: EIP-8004: Trustless Agents **URL**: https://eips.ethereum.org/EIPS/eip-8004 **Status**: Peer Review (as of 2025-12-20) **Reference Repository**: * **Repo**: https://github.com/erc-8004/erc-8004-contracts * **Key Files**: * `ERC8004SPEC.md` - Complete technical specification * `contracts/` - Reference implementation contracts * `README.md` - Overview and deployment info **What We Used**: * AgentURI metadata schema (required/recommended/optional fields) * Reputation Registry feedback structure * Validation Registry request/response structure * Onchain metadata key-value specification * Trust model definitions (reputation, crypto-economic, tee-attestation) * Contract interface specifications ### 2. Agent0 SDK Documentation **Organization**: Agent0 Project (ERC-8004 reference implementation) **Repository**: https://github.com/agent0/agent0 (assumed - verify actual URL) **Documentation Site**: https://docs.agent0.xyz/ (assumed - verify actual URL) **Key Documents**: * `1-welcome-1-4-erc-8004.md` - ERC-8004 overview and integration * `2-usage-2-2-configure-agents.md` - Agent configuration guide * `2-usage-2-3-registration-ipfs.md` - IPFS registration workflow * `5-reference-5-2-agent.md` - Agent API reference **What We Used**: * Standard agent metadata format (type, endpoints, registrations) * MCP and A2A endpoint specifications * IPFS storage patterns * Timestamp field usage (`createdAt`, `updatedAt`) * Feedback submission patterns * Validation request/response patterns ### 3. ERC-8004 Best Practices Guide **Organization**: ERC-8004 Community **Repository**: https://github.com/erc-8004/best-practices (assumed - verify) **Document**: `README.md` - "4 Golden Rules for Agent Registration" **What We Used**: * Rule 1: Name, Image, Description importance * Rule 2: Endpoint types and formats (MCP, A2A, OASF, ENS, DID, agentWallet) * Rule 3: OASF skills and domains taxonomy usage * Rule 4: Registrations array bidirectional verification * x402 support flag * Active status flag ### 4. OASF (Open Agentic Schema Framework) **Organization**: agntcy (now Linux Foundation) **Repository**: https://github.com/agntcy/oasf **Version**: v0.8.0 **Schema Browser**: https://schema.oasf.outshift.com/0.8.0 **What We Used**: * Skills taxonomy structure (categories/subcategories) * Domains taxonomy structure * OASF endpoint format and version specification * Recommended skills for blockchain agents * Recommended domains for financial/technical agents **Resources**: * [All Skills](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * [All Domains](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 5. CAIP Standards **Organization**: Chain Agnostic Improvement Proposals (ChainAgnostic) **Repository**: https://github.com/ChainAgnostic/CAIPs **CAIP-2: Blockchain ID Specification**: * **URL**: https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md * **Status**: Final (August 2021) * **What We Used**: * `namespace:chainId:reference` format for chain IDs * `eip155` namespace for EVM chains * Usage in `agentRegistry`, `validatorAddress` fields **CAIP-10: Account ID Specification**: * **URL**: https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md * **Status**: Final * **What We Used**: * `namespace:chainId:address` format for account IDs * Usage in `agentWallet` endpoint, `clientAddress` field * Character set restrictions ### 6. Protocol Documentation **MCP (Model Context Protocol)**: * **URL**: https://modelcontextprotocol.io/ * **Standard Version**: 2025-06-18 * **What We Used**: MCP endpoint structure, tools, prompts, resources **A2A (Agent-to-Agent Protocol)**: * **URL**: https://a2a.to/ * **Standard Version**: v0.3.0 * **What We Used**: A2A endpoint structure, agent card format, skills taxonomy ### 7. Community Resources **Awesome ERC-8004**: * **Repository**: https://github.com/sudeepb02/awesome-erc8004 * **What We Used**: Community project patterns, real-world implementation examples **Trustless Agents Reference Implementation**: * **Repository**: https://github.com/ChaosChain/trustless-agents-erc-ri * **Organization**: Ch40s Chain / ChaosChain * **What We Used**: Contract deployment patterns, spec compliance checklist ## Real-World Data Sources ### 8. Production Agent Metadata **Organization**: 8004scan Project **Data Collection Date**: 2025-12-19 **Sample Size**: 400 agents (8.5% of 4,725 total with metadata) **Collection Method**: ```sql SELECT chain_id, agent_id, metadata_uri, metadata_json, metadata_parse_status, metadata_parse_warnings FROM agents WHERE metadata_json IS NOT NULL ORDER BY created_at DESC LIMIT 400; ``` **Key Statistics**: * URI types: IPFS 51%, HTTP 22%, Data URI 18% * Endpoint adoption: A2A 85%, MCP 75%, OASF 60% * Parse success: 69.9% (including warnings), 58.1% perfect * Common issues: ~15% empty endpoints, ~30% null agentId **Documented Patterns**: 1. Agent0 SDK Standard Format 2. Alias AI Star Card Format 3. ChaosChain Studio Format 4. Minimal/Test Agents ### 9. Production Validation Data **Organization**: 8004scan Project **Data Collection Date**: 2025-12-20 **Sample Size**: 8,219 validation records (Base Sepolia) **Key Findings**: * **100% Groth16 zkSNARK proofs** (8,219 records) * No ERC-8004 standard format validations (yet) * Circuit: `zyfi-rebalancing-validation` (ZyFi protocol) * All contain: `proof.pi_a/pi_b/pi_c`, `publicSignals`, `verifierAddress` **Implications**: * Led to design of three-level format compatibility system * Groth16 recognized as Level 2 (Known Custom Format) * Migration guides created for Groth16 β†’ ERC-8004 standard ### 10. v1 Frontend Implementation **Organization**: 8004scan v1 Project **Data**: v1 frontend code and patterns **Key Discoveries**: * **Attachment Pattern**: Flexible evidence system supporting any file type * Upload methods: File upload, JSON paste, manual URI * Metadata structure: `name`, `uri`, `mimeType`, `size`, `description`, `uploadedAt` * Use cases: Security audits (PDF), test results (JSON/CSV), screenshots, videos **Impact**: * Integrated attachment pattern into Feedback and Validation standards * Documented best practices for evidence collection * Created migration examples ## Synthesis Methodology ### Step 1: Official Spec Analysis 1. Read EIP-8004 specification in full 2. Extract schema definitions (required/recommended/optional) 3. Document contract interfaces 4. Note trust model specifications ### Step 2: Reference Implementation Review 1. Study Agent0 SDK documentation 2. Identify standard patterns and conventions 3. Extract endpoint format specifications 4. Document IPFS storage patterns ### Step 3: Community Best Practices Integration 1. Review "4 Golden Rules" from best practices guide 2. Integrate OASF taxonomy usage 3. Document x402 and active flags 4. Cross-reference with CAIP standards ### Step 4: Real-World Data Analysis **Agent Metadata (4,725 agents)**: 1. Collect 400 production samples 2. Categorize by pattern (4 major patterns) 3. Calculate adoption statistics 4. Identify common issues and edge cases 5. Document non-standard but common fields **Validation Data (8,219 validations)**: 1. Analyze all validation records on Base Sepolia 2. Identify dominant format (100% Groth16) 3. Document custom proof structures 4. Design three-level compatibility system 5. Create migration guides **v1 Frontend Analysis**: 1. Review v1 attachment implementation 2. Extract reusable patterns 3. Document best practices 4. Integrate into new standards ### Step 5: Validation Rule Derivation **Agent Metadata**: * **Level 1 (Required)**: From EIP-8004 spec + ERC-721 compatibility * **Level 2 (Endpoints)**: From best practices + real-world usage * **Level 3 (Registrations)**: From EIP-8004 + CAIP standards * **Level 4 (Trust Models)**: From EIP-8004 + community extensions * **Level 5 (Status Fields)**: From best practices + real-world usage **Validation Format**: * **Level 1 (ERC-8004 Standard)**: From official spec + suggested improvements * **Level 2 (Known Custom)**: From production data analysis (Groth16) * **Level 3 (Unknown)**: Fallback for unrecognized formats ### Step 6: Documentation Structure Design 1. Separate feedback and validation standards 2. Create professional developer-facing documents 3. Position as "supplementary recommended standards" 4. Add implementation guides and references 5. Include migration guides for existing formats ## Update Process When updating these documents in the future: ### 1. Check Official Sources * \[ ] Review EIP-8004 specification for changes * \[ ] Check agent0 SDK documentation updates * \[ ] Verify OASF taxonomy version (currently v0.8.0) * \[ ] Review CAIP standards for updates * \[ ] Check MCP/A2A protocol versions ### 2. Collect Fresh Data * \[ ] Export latest agent samples from database * \[ ] Export latest validation samples * \[ ] Export latest feedback samples (when available) * \[ ] Run statistical analysis on full datasets * \[ ] Identify new patterns or changes in adoption ### 3. Identify Changes * \[ ] Compare new data with previous baseline * \[ ] Document any schema drift * \[ ] Note new common fields or patterns * \[ ] Identify deprecated patterns * \[ ] Check for new trust models or endpoint types ### 4. Update Documentation * \[ ] Revise standard documents for spec changes * \[ ] Update statistics and examples * \[ ] Add new patterns to implementation guides * \[ ] Update parser validation rules if needed * \[ ] Revise migration guides ### 5. Version Control * \[ ] Update "Last Updated" date in all documents * \[ ] Note version changes in this sources.md * \[ ] Git commit with clear message describing changes * \[ ] Tag release if major update (e.g., v3.0) ## Documentation Coverage | Standard | Status | Data Sources | Real-World Samples | | ------------------ | ----------- | ------------------------------- | ------------------ | | **Agent Metadata** | βœ… Complete | EIP-8004 + Agent0 + OASF + CAIP | 400 agents | | **Feedback** | βœ… Complete | EIP-8004 + v1 frontend | v1 patterns | | **Validation** | βœ… Complete | EIP-8004 + production data | 8,219 validations | **Implementation Guides**: * βœ… Agent Metadata Parsing * βœ… Feedback Best Practices * βœ… Validation Best Practices **Reference Materials**: * βœ… Sources & References (this document) ## Known Format Variants ### Agent Metadata * **Standard**: Agent0 SDK format (most common) * **Custom**: Alias AI Star Card, ChaosChain Studio * **Edge Cases**: Empty endpoints, null agentId, version typos ### Validation * **Standard**: ERC-8004 format (0% adoption currently) * **Custom Level 2**: Groth16 zkSNARK (100% of production data) * **Future**: PLONK, STARK (designed but not yet seen) ### Feedback * **Standard**: ERC-8004 format * **Extension**: v1 attachment pattern * **Protocol Fields**: A2A, MCP, x402 specific fields ## Contact and Maintenance **Primary Maintainer**: 8004scan Development Team **Documentation Owner**: Backend Team **Review Frequency**: Monthly **Next Scheduled Review**: 2026-01-20 **For Updates**: 1. Check official sources listed above 2. Collect fresh production data 3. Follow update process in this document 4. Update version and date in all documents **For Questions**: * **Specification interpretation** β†’ Refer to EIP-8004 official spec * **Implementation patterns** β†’ Refer to Agent0 SDK docs * **Real-world usage** β†’ Refer to production data analysis * **CAIP formats** β†’ Refer to ChainAgnostic CAIPs repo * **OASF taxonomy** β†’ Refer to OASF v0.8.0 schema browser ## References Summary | Source | Organization | Type | URL | | --------------------------- | ----------------------- | --------------- | ----------------------------------------------------------------- | | **EIP-8004** | Ethereum Foundation | Official Spec | https://eips.ethereum.org/EIPS/eip-8004 | | **erc-8004-contracts** | ERC-8004 Project | Reference Impl | https://github.com/erc-8004/erc-8004-contracts | | **agent0 docs** | Agent0 Project | SDK Docs | https://docs.agent0.xyz/ | | **best-practices** | ERC-8004 Community | Guide | https://github.com/erc-8004/best-practices | | **OASF v0.8.0** | agntcy/Linux Foundation | Taxonomy | https://github.com/agntcy/oasf | | **CAIP-2** | ChainAgnostic | Standard | https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md | | **CAIP-10** | ChainAgnostic | Standard | https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md | | **MCP Protocol** | Model Context Protocol | Protocol Docs | https://modelcontextprotocol.io/ | | **A2A Protocol** | Agent-to-Agent | Protocol Docs | https://a2a.to/ | | **awesome-erc8004** | Community | Resource List | https://github.com/sudeepb02/awesome-erc8004 | | **trustless-agents-erc-ri** | ChaosChain | Reference Impl | https://github.com/ChaosChain/trustless-agents-erc-ri | | **8004scan Production DB** | This Project | Real-world Data | 4,725 agents, 8,219 validations | | **8004scan v1 Frontend** | This Project | Implementation | Attachment pattern | --- --- url: /v1/docs/reference/sources.md description: Source tracking and references for ERC-8004 documentation --- ## Description Source tracking for ERC-8004 standards documentation > **Data Source Notice**: Statistical data in this documentation is derived from the **ERC-8004 Legacy Testnet (pre-v1)**, collected during December 2025. This data reflects testnet behavior and may differ from mainnet patterns once ERC-8004 v1.1 contracts are widely deployed. ## Document Structure This directory contains three comprehensive standards documents based on the official EIP-8004 specification and real-world production data: 1. **[Agent Metadata Standard](../01-agent-metadata-standard.md)** - AgentURI offchain data format 2. **[Feedback Standard](../02-feedback-standard.md)** - Reputation Registry offchain data format 3. **[Validation Standard](../03-validation-standard.md)** - Validation Registry offchain data format All documents positioned as **"8004scan's official supplementary recommended standards for ERC-8004"**. ## Primary Sources ### 1. Official ERC-8004 Specification **Organization**: Ethereum Foundation **Document**: EIP-8004: Trustless Agents **URL**: https://eips.ethereum.org/EIPS/eip-8004 **Status**: Peer Review (as of 2025-12-20) **Reference Repository**: * **Repo**: https://github.com/erc-8004/erc-8004-contracts * **Key Files**: * `ERC8004SPEC.md` - Complete technical specification * `contracts/` - Reference implementation contracts * `README.md` - Overview and deployment info **What We Used**: * AgentURI metadata schema (required/recommended/optional fields) * Reputation Registry feedback structure * Validation Registry request/response structure * Onchain metadata key-value specification * Trust model definitions (reputation, crypto-economic, tee-attestation) * Contract interface specifications ### 2. Agent0 SDK Documentation **Organization**: Agent0 Project (ERC-8004 reference implementation) **Repository**: https://github.com/agent0/agent0 (assumed - verify actual URL) **Documentation Site**: https://docs.agent0.xyz/ (assumed - verify actual URL) **Key Documents**: * `1-welcome-1-4-erc-8004.md` - ERC-8004 overview and integration * `2-usage-2-2-configure-agents.md` - Agent configuration guide * `2-usage-2-3-registration-ipfs.md` - IPFS registration workflow * `5-reference-5-2-agent.md` - Agent API reference **What We Used**: * Standard agent metadata format (type, endpoints, registrations) * MCP and A2A endpoint specifications * IPFS storage patterns * Timestamp field usage (`createdAt`, `updatedAt`) * Feedback submission patterns * Validation request/response patterns ### 3. ERC-8004 Best Practices Guide **Organization**: ERC-8004 Community **Repository**: https://github.com/erc-8004/best-practices (assumed - verify) **Document**: `README.md` - "4 Golden Rules for Agent Registration" **What We Used**: * Rule 1: Name, Image, Description importance * Rule 2: Endpoint types and formats (MCP, A2A, OASF, ENS, DID, agentWallet) * Rule 3: OASF skills and domains taxonomy usage * Rule 4: Registrations array bidirectional verification * x402 support flag * Active status flag ### 4. OASF (Open Agentic Schema Framework) **Organization**: agntcy (now Linux Foundation) **Repository**: https://github.com/agntcy/oasf **Version**: v0.8.0 **Schema Browser**: https://schema.oasf.outshift.com/0.8.0 **What We Used**: * Skills taxonomy structure (categories/subcategories) * Domains taxonomy structure * OASF endpoint format and version specification * Recommended skills for blockchain agents * Recommended domains for financial/technical agents **Resources**: * [All Skills](https://github.com/agntcy/oasf/blob/v0.8.0/all_skills.json) * [All Domains](https://github.com/agntcy/oasf/blob/v0.8.0/all_domains.json) ### 5. CAIP Standards **Organization**: Chain Agnostic Improvement Proposals (ChainAgnostic) **Repository**: https://github.com/ChainAgnostic/CAIPs **CAIP-2: Blockchain ID Specification**: * **URL**: https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md * **Status**: Final (August 2021) * **What We Used**: * `namespace:chainId:reference` format for chain IDs * `eip155` namespace for EVM chains * Usage in `agentRegistry`, `validatorAddress` fields **CAIP-10: Account ID Specification**: * **URL**: https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md * **Status**: Final * **What We Used**: * `namespace:chainId:address` format for account IDs * Usage in `agentWallet` endpoint, `clientAddress` field * Character set restrictions ### 6. Protocol Documentation **MCP (Model Context Protocol)**: * **URL**: https://modelcontextprotocol.io/ * **Standard Version**: 2025-06-18 * **What We Used**: MCP endpoint structure, tools, prompts, resources **A2A (Agent-to-Agent Protocol)**: * **URL**: https://a2a.to/ * **Standard Version**: v0.3.0 * **What We Used**: A2A endpoint structure, agent card format, skills taxonomy ### 7. Community Resources **Awesome ERC-8004**: * **Repository**: https://github.com/sudeepb02/awesome-erc8004 * **What We Used**: Community project patterns, real-world implementation examples **Trustless Agents Reference Implementation**: * **Repository**: https://github.com/ChaosChain/trustless-agents-erc-ri * **Organization**: Ch40s Chain / ChaosChain * **What We Used**: Contract deployment patterns, spec compliance checklist ## Real-World Data Sources ### 8. Production Agent Metadata **Organization**: 8004scan Project **Data Collection Date**: 2025-12-19 **Sample Size**: 400 agents (8.5% of 4,725 total with metadata) **Collection Method**: ```sql SELECT chain_id, agent_id, metadata_uri, metadata_json, metadata_parse_status, metadata_parse_warnings FROM agents WHERE metadata_json IS NOT NULL ORDER BY created_at DESC LIMIT 400; ``` **Key Statistics** (Legacy Testnet pre-v1, December 2025): * URI types: IPFS 51%, HTTP 22%, Data URI 18% * Endpoint adoption: A2A 85%, MCP 75%, OASF 60% * Parse success: 69.9% (including warnings), 58.1% perfect * Common issues: ~15% empty endpoints, ~30% null agentId **OASF Taxonomy Usage** (Top 5 by adoption): Skills: 1. `natural_language_processing/natural_language_generation/summarization` (40%) 2. `tool_interaction/api_schema_understanding` (35%) 3. `multi_modal/image_processing/text_to_image` (30%) 4. `natural_language_processing/information_retrieval_synthesis/search` (28%) 5. `tool_interaction/workflow_automation` (25%) Domains: 1. `technology/blockchain` (45%) 2. `finance_and_business/finance` (35%) 3. `technology/software_engineering/apis_integration` (30%) 4. `technology/blockchain/cryptocurrency` (28%) 5. `media_and_entertainment/content_creation` (25%) **Trust Model Adoption**: * `reputation`: 80% of agents * `crypto-economic`: 50% of agents * `tee-attestation`: 20% of agents **Documented Patterns**: 1. Agent0 SDK Standard Format 2. Alias AI Star Card Format 3. ChaosChain Studio Format 4. Minimal/Test Agents ### 9. Production Validation Data **Organization**: 8004scan Project **Data Collection Date**: 2025-12-20 **Sample Size**: 8,219 validation records (Base Sepolia) **Key Findings**: * **100% Groth16 zkSNARK proofs** (8,219 records) * No ERC-8004 standard format validations (yet) * Circuit: `zyfi-rebalancing-validation` (ZyFi protocol) * All contain: `proof.pi_a/pi_b/pi_c`, `publicSignals`, `verifierAddress` **Implications**: * Led to design of three-level format compatibility system * Groth16 recognized as Level 2 (Known Custom Format) * Migration guides created for Groth16 β†’ ERC-8004 standard ### 10. v1 Frontend Implementation **Organization**: 8004scan v1 Project **Data**: v1 frontend code and patterns **Key Discoveries**: * **Attachment Pattern**: Flexible evidence system supporting any file type * Upload methods: File upload, JSON paste, manual URI * Metadata structure: `name`, `uri`, `mimeType`, `size`, `description`, `uploadedAt` * Use cases: Security audits (PDF), test results (JSON/CSV), screenshots, videos **Impact**: * Integrated attachment pattern into Feedback and Validation standards * Documented best practices for evidence collection * Created migration examples ## Synthesis Methodology ### Step 1: Official Spec Analysis 1. Read EIP-8004 specification in full 2. Extract schema definitions (required/recommended/optional) 3. Document contract interfaces 4. Note trust model specifications ### Step 2: Reference Implementation Review 1. Study Agent0 SDK documentation 2. Identify standard patterns and conventions 3. Extract endpoint format specifications 4. Document IPFS storage patterns ### Step 3: Community Best Practices Integration 1. Review "4 Golden Rules" from best practices guide 2. Integrate OASF taxonomy usage 3. Document x402 and active flags 4. Cross-reference with CAIP standards ### Step 4: Real-World Data Analysis **Agent Metadata (4,725 agents)**: 1. Collect 400 production samples 2. Categorize by pattern (4 major patterns) 3. Calculate adoption statistics 4. Identify common issues and edge cases 5. Document non-standard but common fields **Validation Data (8,219 validations)**: 1. Analyze all validation records on Base Sepolia 2. Identify dominant format (100% Groth16) 3. Document custom proof structures 4. Design three-level compatibility system 5. Create migration guides **v1 Frontend Analysis**: 1. Review v1 attachment implementation 2. Extract reusable patterns 3. Document best practices 4. Integrate into new standards ### Step 5: Validation Rule Derivation **Agent Metadata**: * **Level 1 (Required)**: From EIP-8004 spec + ERC-721 compatibility * **Level 2 (Endpoints)**: From best practices + real-world usage * **Level 3 (Registrations)**: From EIP-8004 + CAIP standards * **Level 4 (Trust Models)**: From EIP-8004 + community extensions * **Level 5 (Status Fields)**: From best practices + real-world usage **Validation Format**: * **Level 1 (ERC-8004 Standard)**: From official spec + suggested improvements * **Level 2 (Known Custom)**: From production data analysis (Groth16) * **Level 3 (Unknown)**: Fallback for unrecognized formats ### Step 6: Documentation Structure Design 1. Separate feedback and validation standards 2. Create professional developer-facing documents 3. Position as "supplementary recommended standards" 4. Add implementation guides and references 5. Include migration guides for existing formats ## Update Process When updating these documents in the future: ### 1. Check Official Sources * \[ ] Review EIP-8004 specification for changes * \[ ] Check agent0 SDK documentation updates * \[ ] Verify OASF taxonomy version (currently v0.8.0) * \[ ] Review CAIP standards for updates * \[ ] Check MCP/A2A protocol versions ### 2. Collect Fresh Data * \[ ] Export latest agent samples from database * \[ ] Export latest validation samples * \[ ] Export latest feedback samples (when available) * \[ ] Run statistical analysis on full datasets * \[ ] Identify new patterns or changes in adoption ### 3. Identify Changes * \[ ] Compare new data with previous baseline * \[ ] Document any schema drift * \[ ] Note new common fields or patterns * \[ ] Identify deprecated patterns * \[ ] Check for new trust models or endpoint types ### 4. Update Documentation * \[ ] Revise standard documents for spec changes * \[ ] Update statistics and examples * \[ ] Add new patterns to implementation guides * \[ ] Update parser validation rules if needed * \[ ] Revise migration guides ### 5. Version Control * \[ ] Update "Last Updated" date in all documents * \[ ] Note version changes in this sources.md * \[ ] Git commit with clear message describing changes * \[ ] Tag release if major update (e.g., v3.0) ## Documentation Coverage | Standard | Status | Data Sources | Real-World Samples | | ------------------ | ----------- | ------------------------------- | ------------------ | | **Agent Metadata** | βœ… Complete | EIP-8004 + Agent0 + OASF + CAIP | 400 agents | | **Feedback** | βœ… Complete | EIP-8004 + v1 frontend | v1 patterns | | **Validation** | βœ… Complete | EIP-8004 + production data | 8,219 validations | **Implementation Guides**: * βœ… Agent Metadata Parsing * βœ… Feedback Best Practices * βœ… Validation Best Practices **Reference Materials**: * βœ… Sources & References (this document) ## Known Format Variants ### Agent Metadata * **Standard**: Agent0 SDK format (most common) * **Custom**: Alias AI Star Card, ChaosChain Studio * **Edge Cases**: Empty endpoints, null agentId, version typos ### Validation * **Standard**: ERC-8004 format (0% adoption currently) * **Custom Level 2**: Groth16 zkSNARK (100% of production data) * **Future**: PLONK, STARK (designed but not yet seen) ### Feedback * **Standard**: ERC-8004 format * **Extension**: v1 attachment pattern * **Protocol Fields**: A2A, MCP, x402 specific fields ## Contact and Maintenance **Primary Maintainer**: 8004scan Development Team **Documentation Owner**: Backend Team **Review Frequency**: Monthly **Next Scheduled Review**: 2026-01-20 **For Updates**: 1. Check official sources listed above 2. Collect fresh production data 3. Follow update process in this document 4. Update version and date in all documents **For Questions**: * **Specification interpretation** β†’ Refer to EIP-8004 official spec * **Implementation patterns** β†’ Refer to Agent0 SDK docs * **Real-world usage** β†’ Refer to production data analysis * **CAIP formats** β†’ Refer to ChainAgnostic CAIPs repo * **OASF taxonomy** β†’ Refer to OASF v0.8.0 schema browser ## References Summary | Source | Organization | Type | URL | | --------------------------- | ----------------------- | --------------- | ----------------------------------------------------------------- | | **EIP-8004** | Ethereum Foundation | Official Spec | https://eips.ethereum.org/EIPS/eip-8004 | | **erc-8004-contracts** | ERC-8004 Project | Reference Impl | https://github.com/erc-8004/erc-8004-contracts | | **agent0 docs** | Agent0 Project | SDK Docs | https://docs.agent0.xyz/ | | **best-practices** | ERC-8004 Community | Guide | https://github.com/erc-8004/best-practices | | **OASF v0.8.0** | agntcy/Linux Foundation | Taxonomy | https://github.com/agntcy/oasf | | **CAIP-2** | ChainAgnostic | Standard | https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md | | **CAIP-10** | ChainAgnostic | Standard | https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md | | **MCP Protocol** | Model Context Protocol | Protocol Docs | https://modelcontextprotocol.io/ | | **A2A Protocol** | Agent-to-Agent | Protocol Docs | https://a2a.to/ | | **awesome-erc8004** | Community | Resource List | https://github.com/sudeepb02/awesome-erc8004 | | **trustless-agents-erc-ri** | ChaosChain | Reference Impl | https://github.com/ChaosChain/trustless-agents-erc-ri | | **8004scan Production DB** | This Project | Real-world Data | 4,725 agents, 8,219 validations | | **8004scan v1 Frontend** | This Project | Implementation | Attachment pattern | --- --- url: /docs/official-specification/erc-8004-official.md description: Discover agents and establish trust through reputation and validation --- ## Abstract This protocol proposes to use blockchains to **discover, choose, and interact with agents across organizational boundaries** without pre-existing trust, thus **enabling open-ended agent economies**. Trust models are pluggable and tiered, with security proportional to value at risk, from low-stake tasks like ordering pizza to high-stake tasks like medical diagnosis. Developers can choose from different trust models: reputation systems using client feedback, validation via stake-secured re-execution, zkML proofs, or TEE oracles. ## Motivation MCP allows servers to list and offer their capabilities (prompts, resources, tools, and completions), while A2A handles agent authentication, skills advertisement via AgentCards, direct messaging, and complete task-lifecycle orchestration. However, these agent communication protocols don't inherently cover agent discovery and trust. To foster an open, cross-organizational agent economy, we need mechanisms for discovering and trusting agents in untrusted settings. This ERC addresses this need through three lightweight registries, which can be deployed on any L2 or on Mainnet as per-chain singletons: **Identity Registry** - A minimal on-chain handle based on [ERC-721](https://eips.ethereum.org/EIPS/eip-721) with URIStorage extension that resolves to an agent's registration file, providing every agent with a portable, censorship-resistant identifier. **Reputation Registry** - A standard interface for posting and fetching feedback signals. Scoring and aggregation occur both on-chain (for composability) and off-chain (for sophisticated algorithms), enabling an ecosystem of specialized services for agent scoring, auditor networks, and insurance pools. **Validation Registry** - Generic hooks for requesting and recording independent validators checks (e.g. stakers re-running the job, zkML verifiers, TEE oracles, trusted judges). Payments are orthogonal to this protocol and not covered here. However, examples are provided showing how **x402 payments** can enrich feedback signals. ## Specification The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174). ### Identity Registry The Identity Registry uses ERC-721 with the URIStorage extension for agent registration, making **all agents immediately browsable and transferable with NFTs-compliant apps**. Each agent is uniquely identified globally by: * *agentRegistry*: A colon-separated string `{namespace}:{chainId}:{identityRegistry}` (e.g., `eip155:1:0x742...`) where: * *namespace*: The chain family identifier (`eip155` for EVM chains) * *chainId*: The blockchain network identifier * *identityRegistry*: The address where the ERC-721 registry contract is deployed * *agentId*: The ERC-721 tokenId assigned incrementally by the registry Throughout this document, *tokenId* in ERC-721 is referred to as *agentId* and *tokenURI* in ERC-721 is referred to as *agentURI*. The owner of the ERC-721 token is the owner of the agent and can transfer ownership or delegate management (e.g., updating the registration file) to operators, as supported by `ERC721URIStorage`. #### Agent URI and Agent Registration File The *agentURI* MUST resolve to the agent registration file. It MAY use any URI scheme such as `ipfs://` (e.g., `ipfs://cid`) or `https://` (e.g., `https://domain.com/agent3.json`). When the registration uri changes, it can be updated with *setAgentURI()*. The registration file MUST have the following structure: ```jsonc { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "myAgentName", "description": "A natural language description of the Agent, which MAY include what it does, how it works, pricing, and interaction methods", "image": "https://example.com/agentimage.png", "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", // https://github.com/agntcy/oasf/tree/v0.8.0 "skills": [], // OPTIONAL "domains": [] // OPTIONAL }, { "name": "ENS", "endpoint": "vitalik.eth", "version": "v1" }, { "name": "DID", "endpoint": "did:method:foobar", "version": "v1" }, { "name": "email", "endpoint": "mail@myagent.com" } ], "x402Support": false, "active": true, "registrations": [ { "agentId": 22, "agentRegistry": "{namespace}:{chainId}:{identityRegistry}" // e.g. eip155:1:0x742... } ], "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"] } ``` The *type*, *name*, *description*, and *image* fields at the top SHOULD ensure compatibility with ERC-721 apps. The number and type of *services* are fully customizable, allowing developers to add as many as they wish. The *version* field in services is a SHOULD, not a MUST. Agents MAY advertise their services, which point to an A2A agent card, an MCP endpoint, an ENS agent name, DIDs, or the agent's wallets on any chain (even chains where the agent is not registered). #### Endpoint Domain Verification (Optional) Since services can point to domains not controlled by the agent owner, an agent MAY optionally prove control of an HTTPS service domain by publishing `https://{service-domain}/.well-known/agent-registration.json` containing at least a `registrations` list (or the full agent registration file). Verifiers MAY treat the service domain as verified if the file is reachable over HTTPS and includes a `registrations` entry whose `agentRegistry` and `agentId` match the on-chain agent; if the service domain is the same domain that serves the agent's primary registration file referenced by `agentURI`, this additional check is not needed because domain control is already demonstrated there. Agents SHOULD have at least one registration (multiple are possible), and all fields in the registration are mandatory. The *supportedTrust* field is OPTIONAL. If absent or empty, this ERC is used only for discovery, not for trust. #### Onchain metadata The registry extends ERC-721 by adding *getMetadata(uint256 agentId, string metadataKey)* and *setMetadata(uint256 agentId, string metadataKey, string metadataValue)* functions for optional extra on-chain agent metadata. When metadata is set, the following event is emitted: ```solidity event MetadataSet(uint256 indexed agentId, string indexed indexedMetadataKey, string metadataKey, bytes metadataValue) ``` The key `agentWallet` is reserved and cannot be set via *setMetadata()* or during *register()*. It represents the address where the agent receives payments and is initially set to the owner's address. To change it, the agent owner must prove control of the new wallet by providing a valid [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signature for EOAs or [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) for smart contract walletsβ€”by calling: ```solidity function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes calldata signature) external ``` When the agent is transferred, `agentWallet` is automatically reset to the zero address and must be re-verified by the new owner. #### Registration New agents can be minted by calling one of these functions: ```solidity struct MetadataEntry { string metadataKey; bytes metadataValue; } function register(string agentURI, MetadataEntry[] calldata metadata) external returns (uint256 agentId) function register(string agentURI) external returns (uint256 agentId) // agentURI is added later with setAgentURI() function register() external returns (uint256 agentId) ``` This emits one Transfer event, one MetadataSet event for each metadata entry, if any, and ```solidity event Registered(uint256 indexed agentId, string agentURI, address indexed owner) ``` #### Update agentURI The agentURI can be updated by calling the following function, which emits a URIUpdated event: ```solidity function setAgentURI(uint256 agentId, string calldata newURI) external event URIUpdated(uint256 indexed agentId, string newURI, address indexed updatedBy) ``` If the owner wants to store the entire registration file on-chain, the *agentURI* SHOULD use a base64-encoded data URI rather than a serialized JSON string: ```text data:application/json;base64,eyJ0eXBlIjoi... ``` ### Reputation Registry When the Reputation Registry is deployed, the identityRegistry address is set via `initialize(address identityRegistry_)` and publicly visible by calling: ```solidity function getIdentityRegistry() external view returns (address identityRegistry) ``` The feedback given by a `clientAddress` to an agent consists of a signed fixed-point value (`int128`) and its `valueDecimals` (`uint8`, 0-18), plus optional `tag1` and `tag2` (left to developers' discretion to provide maximum on-chain composability and filtering), an endpoint URI, a file URI pointing to an off-chain JSON containing additional information, and its KECCAK-256 file hash to guarantee integrity. We suggest using IPFS or equivalent services to make feedback easily indexed by subgraphs or similar technologies. For IPFS URIs, the hash is not required. All fields except `value` and `valueDecimals` are OPTIONAL, so the off-chain file is not required and can be omitted. #### Giving Feedback New feedback can be added by any `clientAddress` calling: ```solidity function giveFeedback(uint256 agentId, int128 value, uint8 valueDecimals, string calldata tag1, string calldata tag2, string calldata endpoint, string calldata feedbackURI, bytes32 feedbackHash) external ``` The `agentId` must be a validly registered agent. The `valueDecimals` MUST be between 0 and 18. The feedback submitter MUST NOT be the agent owner or an approved operator for `agentId`. `tag1`, `tag2`, `endpoint`, `feedbackURI`, and `feedbackHash` are OPTIONAL. Where provided, `feedbackHash` is the KECCAK-256 hash (`keccak256`) of the content referenced by `feedbackURI`, enabling verifiable integrity for non-content-addressed URIs. For IPFS (or other content-addressed URIs), `feedbackHash` is OPTIONAL and can be omitted (e.g., set to `bytes32(0)`). If the procedure succeeds, an event is emitted: ```solidity event NewFeedback(uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, int128 value, uint8 valueDecimals, string indexed indexedTag1, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash) ``` The feedback fields `value`, `valueDecimals`, `tag1`, `tag2`, and `isRevoked` are stored in the contract storage along with the `feedbackIndex` (a 1-indexed counter of feedback submissions that `clientAddress` has given to `agentId`). The fields `endpoint`, `feedbackURI`, and `feedbackHash` are emitted but are not stored. This exposes reputation signals to any smart contract, enabling on-chain composability. When the feedback is given by an agent (i.e., the client is an agent), the agent SHOULD use the address set in the on-chain optional `agentWallet` metadata as the `clientAddress`, to facilitate reputation aggregation. #### Examples of value / valueDecimals | tag1 | What it measures | Example | value | valueDecimals | | :----------------- | :---------------------------------------- | :------------ | :---- | :------------ | | human | value | valueDecimals | | | | starred | Quality rating (0-100) | 87/100 | 87 | 0 | | reachable | Endpoint reachable (binary) | true | 1 | 0 | | ownerVerified | Endpoint owned by agent owner (binary) | true | 1 | 0 | | uptime | Endpoint uptime (%) | 99.77% | 9977 | 2 | | successRate | Endpoint success rate (%) | 89% | 89 | 0 | | responseTime | Response time (ms) | 560ms | 560 | 0 | | blocktimeFreshness | Avg block delay (blocks) | 4 blocks | 4 | 0 | | revenues | Cumulative revenues (e.g., USD) | $560 | 560 | 0 | | tradingYield | ( `tag2` = day, week, month, year ) Yield | -3,2% | -32 | 1 | #### Revoking Feedback *clientAddress* can revoke feedback by calling: ```solidity function revokeFeedback(uint256 agentId, uint64 feedbackIndex) external ``` This emits: ```solidity event FeedbackRevoked(uint256 indexed agentId, address indexed clientAddress, uint64 indexed feedbackIndex) ``` #### Appending Responses Anyone (e.g., the *agentId* showing a refund, any off-chain data intelligence aggregator tagging feedback as spam) can call: ```solidity function appendResponse(uint256 agentId, address clientAddress, uint64 feedbackIndex, string calldata responseURI, bytes32 responseHash) external ``` Where *responseHash* is the KECCAK-256 file hash of the *responseURI* file content to guarantee integrity. This field is not required for IPFS URIs. This emits: ```solidity event ResponseAppended(uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, address indexed responder, string responseURI) ``` #### Read Functions ```solidity function getSummary(uint256 agentId, address[] calldata clientAddresses, string tag1, string tag2) external view returns (uint64 count, int128 averageValue, uint8 valueDecimals) // agentId is the only mandatory parameter; others are optional filters. // Without filtering by clientAddresses, results are subject to Sybil/spam attacks. See Security Considerations for details function readFeedback(uint256 agentId, address clientAddress, uint64 feedbackIndex) external view returns (int128 value, uint8 valueDecimals, string tag1, string tag2, bool isRevoked) function readAllFeedback(uint256 agentId, address[] calldata clientAddresses, string tag1, string tag2, bool includeRevoked) external view returns (address[] memory clientAddresses, uint64[] memory feedbackIndexes, int128[] memory values, uint8[] memory valueDecimals, string[] memory tag1s, string[] memory tag2s, bool[] memory revokedStatuses) // agentId is the only mandatory parameter; others are optional filters. Revoked feedback are omitted by default. function getResponseCount(uint256 agentId, address clientAddress, uint64 feedbackIndex, address[] responders) external view returns (uint64) // agentId is the only mandatory parameter; others are optional filters. function getClients(uint256 agentId) external view returns (address[] memory) function getLastIndex(uint256 agentId, address clientAddress) external view returns (uint64) ``` We expect reputation systems around reviewers/clientAddresses to emerge. **While simple filtering by reviewer (useful to mitigate spam) and by tag are enabled on-chain, more complex reputation aggregation will happen off-chain**. #### Off-Chain Feedback File Structure The OPTIONAL file at the URI could look like: ```jsonc { // MUST FIELDS "agentRegistry": "eip155:1:{identityRegistry}", "agentId": 22, "clientAddress": "eip155:1:{clientAddress}", "createdAt": "2025-09-23T12:00:00Z", "value": 100, "valueDecimals": 0, // ALL OPTIONAL FIELDS "tag1": "foo", "tag2": "bar", "endpoint": "https://.../", "skill": "as-defined-by-A2A-or-OASF", "domain": "as-defined-by-OASF", "context": "as-defined-by-A2A", "task": "as-defined-by-A2A", "capability": "tools", // As per MCP: "prompts", "resources", "tools" or "completions" "name": "foo", // As per MCP: the name of the prompt, resource or tool "proofOfPayment": { "fromAddress": "0x00...", "toAddress": "0x00...", "chainId": "1", "txHash": "0x00..." }, // this can be used for x402 proof of payment // Other fields " ... ": { " ... " } // MAY } ``` ### Validation Registry **This registry enables agents to request verification of their work and allows validator smart contracts to provide responses that can be tracked on-chain**. Validator smart contracts could use, for example, stake-secured inference re-execution, zkML verifiers or TEE oracles to validate or reject requests. When the Validation Registry is deployed, the *identityRegistry* address is passed to the constructor and is visible by calling getIdentityRegistry(), as described above. #### Validation Request Agents request validation by calling: ```solidity function validationRequest(address validatorAddress, uint256 agentId, string requestURI, bytes32 requestHash) external ``` This function MUST be called by the owner or operator of *agentId*. The *requestURI* points to off-chain data containing all information needed for the validator to validate, including inputs and outputs needed for the verification. The *requestHash* is a commitment to this data (`keccak256` of the request payload) and identifies the request. All other fields are mandatory. A ValidationRequest event is emitted: ```solidity event ValidationRequest(address indexed validatorAddress, uint256 indexed agentId, string requestURI, bytes32 indexed requestHash) ``` #### Validation Response Validators respond by calling: ```solidity function validationResponse(bytes32 requestHash, uint8 response, string responseURI, bytes32 responseHash, string tag) external ``` Only *requestHash* and *response* are mandatory; *responseURI*, *responseHash* and *tag* are optional. This function MUST be called by the *validatorAddress* specified in the original request. The *response* is a value between 0 and 100, which can be used as binary (0 for failed, 100 for passed) or with intermediate values for validations with a spectrum of outcomes. The optional *responseURI* points to off-chain evidence or audit of the validation, *responseHash* is its commitment (in case the resource is not on IPFS), while *tag* allows for custom categorization or additional data. validationResponse() can be called multiple times for the same *requestHash*, enabling use cases like progressive validation states (e.g., β€œsoft finality” and β€œhard finality” using *tag*) or updates to validation status. Upon successful execution, a *ValidationResponse* event is emitted with all function parameters: ```solidity event ValidationResponse(address indexed validatorAddress, uint256 indexed agentId, bytes32 indexed requestHash, uint8 response, string responseURI, bytes32 responseHash, string tag) ``` The contract stores *requestHash*, *validatorAddress*, *agentId*, *response*, *lastUpdate*, and *tag* for on-chain querying and composability. #### Read Functions ```solidity function getValidationStatus(bytes32 requestHash) external view returns (address validatorAddress, uint256 agentId, uint8 response, string tag, uint256 lastUpdate) //Returns aggregated validation statistics for an agent. agentId is the only mandatory parameter; validatorAddresses and tag are optional filters function getSummary(uint256 agentId, address[] calldata validatorAddresses, string tag) external view returns (uint64 count, uint8 averageResponse) function getAgentValidations(uint256 agentId) external view returns (bytes32[] memory requestHashes) function getValidatorRequests(address validatorAddress) external view returns (bytes32[] memory requestHashes) ``` Incentives and slashing related to validation are managed by the specific validation protocol and are outside the scope of this registry. ## Rationale * **Agent communication protocols**: MCP and A2A are popular, and other protocols could emerge. For this reason, this protocol links from the blockchain to a flexible registration file including a list where endpoints can be added at will, combining AI primitives (MCP, A2A) and Web3 primitives such as wallet addresses, DIDs, and ENS names. * **Feedback**: The protocol combines the leverage of nomenclature already established by A2A (such as tasks and skills) and MCP (such as tools and prompts) with complete flexibility in the feedback signal structure. * **Gas Sponsorship**: Since clients don't need to be registered anymore, any application can implement frictionless feedback leveraging [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702). * **Indexing**: Since feedback data is saved on-chain and we suggest using IPFS for full data, it's easy to leverage subgraphs to create indexers and improve UX. * **Deployment**: We expect the registries to be deployed with singletons per chain. Note that an agent registered and receiving feedback on chain A can still operate and transact on other chains. Agents can also be registered on multiple chains if desired. ## Test Cases This protocol enables: * Crawling all agents starting from a logically centralized endpoint and discover agent information (name, image, services), capabilities, communication endpoints (MCP, A2A, others), ENS names, wallet addresses and which trust models they support (reputation, validation, TEE attestation) * Building agent explorers and marketplaces using any ERC-721 compatible application to browse, transfer, and manage agents * Building reputation systems with on-chain aggregation (average scores for smart contract composability) or sophisticated off-chain analysis. All reputation signals are public good. * Discovering which agents support stake-secured or zkML validation and how to request it through a standardized interface ## Security Considerations * Sybil attacks are possible, inflating the reputation of fake agents. The protocol's contribution is to make signals public and use the same schema. We expect many players to build reputation systems, for example, trusting or giving reputation to reviewers (and therefore filtering by reviewer, as the protocol already enables). * On-chain pointers and hashes cannot be deleted, ensuring audit trail integrity * Validator incentives and slashing are managed by specific validation protocols * While this ERC cryptographically ensures the registration file corresponds to the on-chain agent, it cannot cryptographically guarantee that advertised capabilities are functional and non-malicious. The three trust models (reputation, validation, and TEE attestation) are designed to support this verification need ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md). --- --- url: /legacy-pre-v1/docs/official-specification/erc-8004-official.md description: Discover agents and establish trust through reputation and validation --- ## Abstract This protocol proposes to use blockchains to **discover, choose, and interact with agents across organizational boundaries** without pre-existing trust, thus **enabling open-ended agent economies**. Trust models are pluggable and tiered, with security proportional to value at risk, from low-stake tasks like ordering pizza to high-stake tasks like medical diagnosis. Developers can choose from three trust models: reputation systems using client feedback, validation via stake-secured re-execution, zkML proofs, or TEE oracles. ## Motivation MCP allows servers to list and offer their capabilities (prompts, resources, tools, and completions), while A2A handles agent authentication, skills advertisement via AgentCards, direct messaging, and complete task-lifecycle orchestration. However, these agent communication protocols don't inherently cover agent discovery and trust. To foster an open, cross-organizational agent economy, we need mechanisms for discovering and trusting agents in untrusted settings. This ERC addresses this need through three lightweight registries, which can be deployed on any L2 or on Mainnet as per-chain singletons: **Identity Registry** - A minimal on-chain handle based on [ERC-721](https://eips.ethereum.org/EIPS/eip-721) with URIStorage extension that resolves to an agent's registration file, providing every agent with a portable, censorship-resistant identifier. **Reputation Registry** - A standard interface for posting and fetching feedback signals. Scoring and aggregation occur both on-chain (for composability) and off-chain (for sophisticated algorithms), enabling an ecosystem of specialized services for agent scoring, auditor networks, and insurance pools. **Validation Registry** - Generic hooks for requesting and recording independent validators checks (e.g. stakers re-running the job, zkML verifiers, TEE oracles, trusted judges). Payments are orthogonal to this protocol and not covered here. However, examples are provided showing how **x402 payment proofs** can enrich feedback signals. ## Specification The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174). ### Identity Registry The Identity Registry uses ERC-721 with the URIStorage extension for agent registration, making **all agents immediately browsable and transferable with NFTs-compliant apps**. Each agent is uniquely identified globally by: * *namespace:* `eip155` for EVM chains * *chainId*: The blockchain network identifier * *identityRegistry*: The address where the ERC-721 registry contract is deployed * *agentId*: The ERC-721 tokenId assigned incrementally by the registry Throughout this document, *tokenId* in ERC-721 is referred to as *agentId*. The owner of the ERC-721 token is the owner of the agent and can transfer ownership or delegate management (e.g., updating the registration file) to operators, as supported by `ERC721URIStorage`. #### Token URI and Agent Registration File The *tokenURI* MUST resolve to the agent registration file. It MAY use any URI scheme such as `ipfs://` (e.g., `ipfs://cid`) or `https://` (e.g., `https://domain.com/agent3.json`). When the registration data changes, it can be updated with *\_setTokenURI()* as per `ERC721URIStorage`. The registration file MUST have the following structure: ```jsonc { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "myAgentName", "description": "A natural language description of the Agent, which MAY include what it does, how it works, pricing, and interaction methods", "image": "https://example.com/agentimage.png", "endpoints": [ { "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.7" // https://github.com/agntcy/oasf/tree/v0.7.0 }, { "name": "ENS", "endpoint": "vitalik.eth", "version": "v1" }, { "name": "DID", "endpoint": "did:method:foobar", "version": "v1" }, { "name": "agentWallet", "endpoint": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7" } ], "registrations": [ { "agentId": 22, "agentRegistry": "eip155:1:{identityRegistry}" } ], "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"] } ``` The *type*, *name*, *description*, and *image* fields at the top SHOULD ensure compatibility with ERC-721 apps. The number and type of *endpoints* are fully customizable, allowing developers to add as many as they wish. The *version* field in endpoints is a SHOULD, not a MUST. Agents MAY advertise their endpoints, which point to an A2A agent card, an MCP endpoint, an ENS agent name, DIDs, or the agent's wallets on any chain (even chains where the agent is not registered). Agents SHOULD have at least one registration (multiple are possible), and all fields in the registration are mandatory. The *supportedTrust* field is OPTIONAL. If absent or empty, this ERC is used only for discovery, not for trust. #### Onchain metadata The registry extends ERC-721 by adding *getMetadata(uint256 agentId, string key)* and *setMetadata(uint256 agentId, string key, bytes value)* functions for optional extra on-chain agent metadata. Examples of keys are β€œagentWallet” or β€œagentName”. When metadata is set, the following event is emitted: ```javascript event MetadataSet(uint256 indexed agentId, string indexed indexedKey, string key, bytes value) ``` #### Registration New agents can be minted by calling one of these functions: ```javascript struct MetadataEntry { string key; bytes value; } function register(string tokenURI, MetadataEntry[] calldata metadata) returns (uint256 agentId) function register(string tokenURI) returns (uint256 agentId) // tokenURI is added later with _setTokenURI() function register() returns (uint256 agentId) ``` This emits one Transfer event, one MetadataSet event for each metadata entry, if any, and ```javascript event Registered(uint256 indexed agentId, string tokenURI, address indexed owner) ``` ### Reputation Registry When the Reputation Registry is deployed, the *identityRegistry* address is passed to the constructor and publicly visible by calling: ```javascript function getIdentityRegistry() external view returns (address identityRegistry) ``` **As an agent accepts a task, it's expected to sign a *feedbackAuth* to authorize the *clientAddress* (human or agent) to give feedback**. The feedback consists of a *score* (0-100), *tag1* and *tag2* (left to developers' discretion to provide maximum on-chain composability and filtering), a file uri pointing to an off-chain JSON containing additional information, and its KECCAK-256 file hash to guarantee integrity. We suggest using IPFS or equivalent services to make feedback easily indexed by subgraphs or similar technologies. For IPFS uris, the hash is not required. All fields except the *score* are OPTIONAL, so the off-chain file is not required and can be omitted. #### Giving Feedback New feedback can be added by any *clientAddress* calling: ```javascript function giveFeedback(uint256 agentId, uint8 score, bytes32 tag1, bytes32 tag2, string calldata fileuri, bytes32 calldata filehash, bytes memory feedbackAuth) external ``` The *agentId* must be a validly registered agent. The *score* MUST be between 0 and 100. *tag1*, *tag2*, and *uri* are OPTIONAL. *feedbackAuth* is a tuple with the structure (*agentId*, *clientAddress*, *indexLimit*, *expiry*, *chainId*, *identityRegistry*, *signerAddress*) signed using [EIP-191](https://eips.ethereum.org/EIPS/eip-191) or [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) (if *clientAddress* is a smart contract). The *signerAddress* field identifies the agent owner or operator who signed. Verification succeeds only if: *agentId*, *clientAddress*, *chainId* and *identityRegistry* are correct, blocktime < *expiry* and *indexLimit* is greater than the last index of feedback received by that client for that *agentId*. While in most cases *indexLimit* is simply lastIndex + 1, it can be much higher. This allows *agentId* to pre-authorize multiple feedback submissions, useful for agent watch tower use cases. If the procedure succeeds, an event is emitted: ```javascript event NewFeedback(uint256 indexed agentId, address indexed clientAddress, uint8 score, bytes32 indexed tag1, bytes32 tag2, string fileuri, bytes32 filehash) ``` The feedback fields, except *fileuri* and *filehash*, are stored in the contract storage along with the feedbackIndex (the number of feedback submissions that *clientAddress* has given to *agentId*). This exposes reputation signals to any smart contract, enabling on-chain composability. When the feedback is given by an agent (i.e., the client is an agent), the agent SHOULD use the address set in the on-chain optional walletAddress metadata as the clientAddress, to facilitate reputation aggregation. #### Revoking Feedback *clientAddress* can revoke feedback by calling: ```javascript function revokeFeedback(uint256 agentId, uint64 feedbackIndex) external ``` This emits: ```javascript event FeedbackRevoked(uint256 indexed agentId, address indexed clientAddress, uint64 indexed feedbackIndex) ``` Appending Responses Anyone (e.g., the *agentId* showing a refund, any off-chain data intelligence aggregator tagging feedback as spam) can call: ```javascript function appendResponse(uint256 agentId, address clientAddress, uint64 feedbackIndex, string calldata responseUri, bytes32 calldata responseHash) external ``` Where *responseHash* is the KECCAK-256 file hash of the *responseUri* file content to guarantee integrity. This field is OPTIONAL for IPFS URIs. This emits: ```javascript event ResponseAppended(uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, address indexed responder, string responseUri) ``` #### Read Functions ```javascript function getSummary(uint256 agentId, address[] calldata clientAddresses, bytes32 tag1, bytes32 tag2) external view returns (uint64 count, uint8 averageScore) //agentId is the only mandatory parameter; others are optional filters. //Without filtering by clientAddresses, results are subject to Sybil/spam attacks. See Security Considerations for details function readFeedback(uint256 agentId, address clientAddress, uint64 index) external view returns (uint8 score, bytes32 tag1, bytes32 tag2, bool isRevoked) function readAllFeedback(uint256 agentId, address[] calldata clientAddresses, bytes32 tag1, bytes32 tag2, bool includeRevoked) external view returns (address[] memory clientAddresses, uint8[] memory scores, bytes32[] memory tag1s, bytes32[] memory tag2s, bool[] memory revokedStatuses) //agentId is the only mandatory parameter; others are optional filters. Revoked feedback are omitted. function getResponseCount(uint256 agentId, address clientAddress, uint64 feedbackIndex, address[] responders) external view returns (uint64) //agentId is the only mandatory parameter; others are optional filters. function getClients(uint256 agentId) external view returns (address[] memory) function getLastIndex(uint256 agentId, address clientAddress) external view returns (uint64) ``` We expect reputation systems around reviewers/clientAddresses to emerge. **While simple filtering by reviewer (useful to mitigate spam) and by tag are enabled on-chain, more complex reputation aggregation will happen off-chain**. #### Off-Chain Feedback File Structure The OPTIONAL file at the URI could look like: ```jsonc { //MUST FIELDS "agentRegistry": "eip155:1:{identityRegistry}", "agentId": 22, "clientAddress": "eip155:1:{clientAddress}", "createdAt": "2025-09-23T12:00:00Z", "feedbackAuth": "...", "score": 100, //MAY FIELDS "tag1": "foo", "tag2": "bar", "skill": "as-defined-by-A2A", "context": "as-defined-by-A2A", "task": "as-defined-by-A2A", "capability": "tools", // As per MCP: "prompts", "resources", "tools" or "completions" "name": "Put the name of the MCP tool you liked!", // As per MCP: the name of the prompt, resource or tool "proof_of_payment": { "fromAddress": "0x00...", "toAddress": "0x00...", "chainId": "1", "txHash": "0x00..." }, // this can be used for x402 proof of payment // Other fields " ... ": { " ... " } // MAY } ``` ### Validation Registry **This registry enables agents to request verification of their work and allows validator smart contracts to provide responses that can be tracked on-chain**. Validator smart contracts could use, for example, stake-secured inference re-execution, zkML verifiers or TEE oracles to validate or reject requests. When the Validation Registry is deployed, the *identityRegistry* address is passed to the constructor and is visible by calling getIdentityRegistry(), as described above. #### Validation Request Agents request validation by calling: ```javascript function validationRequest(address validatorAddress, uint256 agentId, string requestUri, bytes32 requestHash) external ``` This function MUST be called by the owner or operator of *agentId*. The *requestUri* points to off-chain data containing all information needed for the validator to validate, including inputs and outputs needed for the verification. The *requestHash* is a commitment to this data, which is OPTIONAL if *requestUri* is a content addressable storage uri (e.g. IPFS). All other fields are mandatory. A ValidationRequest event is emitted: ```javascript event ValidationRequest(address indexed validatorAddress, uint256 indexed agentId, string requestUri, bytes32 indexed requestHash) ``` #### Validation Response Validators respond by calling: ```javascript function validationResponse(bytes32 requestHash, uint8 response, string responseUri, bytes32 responseHash, bytes32 tag) external ``` Only *requestHash* and *response* are mandatory; *responseUri*, *responseHash* and *tag* are optional. This function MUST be called by the *validatorAddress* specified in the original request. The *response* is a value between 0 and 100, which can be used as binary (0 for failed, 100 for passed) or with intermediate values for validations with a spectrum of outcomes. The optional *responseUri* points to off-chain evidence or audit of the validation, *responseHash* is its commitment (in case the resource is not on IPFS), while *tag* allows for custom categorization or additional data. validationResponse() can be called multiple times for the same *requestHash*, enabling use cases like progressive validation states (e.g., β€œsoft finality” and β€œhard finality” using *tag*) or updates to validation status. Upon successful execution, a *ValidationResponse* event is emitted with all function parameters: ```javascript event ValidationResponse(address indexed validatorAddress, uint256 indexed agentId, bytes32 indexed requestHash, uint8 response, string responseUri, bytes32 tag) ``` The contract stores *requestHash*, *validatorAddress*, *agentId*, *response*, *lastUpdate*, and *tag* in its memory for on-chain querying and composability. #### Read Functions ```javascript function getValidationStatus(bytes32 requestHash) external view returns (address validatorAddress, uint256 agentId, uint8 response, bytes32 tag, uint256 lastUpdate) function getSummary(uint256 agentId, address[] calldata validatorAddresses, bytes32 tag) external view returns (uint64 count, uint8 avgResponse) //Returns aggregated validation statistics for an agent. agentId is the only mandatory parameter; validatorAddresses and tag are optional filters function getAgentValidations(uint256 agentId) external view returns (bytes32[] memory requestHashes) function getValidatorRequests(address validatorAddress) external view returns (bytes32[] memory requestHashes) ``` Incentives and slashing related to validation are managed by the specific validation protocol and are outside the scope of this registry. ## Rationale * **Agent communication protocols**: MCP and A2A are popular, and other protocols could emerge. For this reason, this protocol links from the blockchain to a flexible registration file including a list where endpoints can be added at will, combining AI primitives (MCP, A2A) and Web3 primitives such as wallet addresses, DIDs, and ENS names. * **Feedback**: The protocol combines the leverage of nomenclature already established by A2A (such as tasks and skills) and MCP (such as tools and prompts) with complete flexibility in the feedback signal structure. * **Gas Sponsorship**: Since clients don't need to be registered anymore, any application can implement frictionless feedback leveraging [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702). * **Indexing**: Since feedback data is saved on-chain and we suggest using IPFS for full data, it's easy to leverage subgraphs to create indexers and improve UX. * **Deployment**: We expect the registries to be deployed with singletons per chain. Note that an agent registered and receiving feedback on chain A can still operate and transact on other chains. Agents can also be registered on multiple chains if desired. ## Test Cases This protocol enables: * Crawling all agents starting from a logically centralized endpoint and discover agent information (name, image, services), capabilities, communication endpoints (MCP, A2A, others), ENS names, wallet addresses and which trust models they support (reputation, validation, TEE attestation) * Building agent explorers and marketplaces using any ERC-721 compatible application to browse, transfer, and manage agents * Building reputation systems with on-chain aggregation (average scores for smart contract composability) or sophisticated off-chain analysis. All reputation signals are public good. * Discovering which agents support stake-secured or zkML validation and how to request it through a standardized interface ## Security Considerations * Pre-authorization for feedback only partially mitigates spam, as Sybil attacks are still possible, inflating the reputation of fake agents. The protocol's contribution is to make signals public and use the same schema. We expect many players to build reputation systems, for example, trusting or giving reputation to reviewers (and therefore filtering by reviewer, as the protocol already enables). * On-chain pointers and hashes cannot be deleted, ensuring audit trail integrity * Validator incentives and slashing are managed by specific validation protocols * While this ERC cryptographically ensures the registration file corresponds to the on-chain agent, it cannot cryptographically guarantee that advertised capabilities are functional and non-malicious. The three trust models (reputation, validation, and TEE attestation) are designed to support this verification need ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). --- --- url: /v1/docs/official-specification/erc-8004-official.md description: Discover agents and establish trust through reputation and validation --- ## Abstract This protocol proposes to use blockchains to **discover, choose, and interact with agents across organizational boundaries** without pre-existing trust, thus **enabling open-ended agent economies**. Trust models are pluggable and tiered, with security proportional to value at risk, from low-stake tasks like ordering pizza to high-stake tasks like medical diagnosis. Developers can choose from different trust models: reputation systems using client feedback, validation via stake-secured re-execution, zkML proofs, or TEE oracles. ## Motivation MCP allows servers to list and offer their capabilities (prompts, resources, tools, and completions), while A2A handles agent authentication, skills advertisement via AgentCards, direct messaging, and complete task-lifecycle orchestration. However, these agent communication protocols don't inherently cover agent discovery and trust. To foster an open, cross-organizational agent economy, we need mechanisms for discovering and trusting agents in untrusted settings. This ERC addresses this need through three lightweight registries, which can be deployed on any L2 or on Mainnet as per-chain singletons: **Identity Registry** - A minimal on-chain handle based on [ERC-721](https://eips.ethereum.org/EIPS/eip-721) with URIStorage extension that resolves to an agent's registration file, providing every agent with a portable, censorship-resistant identifier. **Reputation Registry** - A standard interface for posting and fetching feedback signals. Scoring and aggregation occur both on-chain (for composability) and off-chain (for sophisticated algorithms), enabling an ecosystem of specialized services for agent scoring, auditor networks, and insurance pools. **Validation Registry** - Generic hooks for requesting and recording independent validators checks (e.g. stakers re-running the job, zkML verifiers, TEE oracles, trusted judges). Payments are orthogonal to this protocol and not covered here. However, examples are provided showing how **x402 payments** can enrich feedback signals. ## Specification The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174). ### Identity Registry The Identity Registry uses ERC-721 with the URIStorage extension for agent registration, making **all agents immediately browsable and transferable with NFTs-compliant apps**. Each agent is uniquely identified globally by: * *agentRegistry*: A colon-separated string `{namespace}:{chainId}:{identityRegistry}` (e.g., `eip155:1:0x742...`) where: * *namespace*: The chain family identifier (`eip155` for EVM chains) * *chainId*: The blockchain network identifier * *identityRegistry*: The address where the ERC-721 registry contract is deployed * *agentId*: The ERC-721 tokenId assigned incrementally by the registry Throughout this document, *tokenId* in ERC-721 is referred to as *agentId* and *tokenURI* in ERC-721 is referred to as *agentURI*. The owner of the ERC-721 token is the owner of the agent and can transfer ownership or delegate management (e.g., updating the registration file) to operators, as supported by `ERC721URIStorage`. #### Agent URI and Agent Registration File The *agentURI* MUST resolve to the agent registration file. It MAY use any URI scheme such as `ipfs://` (e.g., `ipfs://cid`) or `https://` (e.g., `https://domain.com/agent3.json`). When the registration uri changes, it can be updated with *setAgentURI()*. The registration file MUST have the following structure: ```jsonc { "type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1", "name": "myAgentName", "description": "A natural language description of the Agent, which MAY include what it does, how it works, pricing, and interaction methods", "image": "https://example.com/agentimage.png", "endpoints": [ { "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", // https://github.com/agntcy/oasf/tree/v0.8.0 "skills": [], // OPTIONAL "domains": [] // OPTIONAL }, { "name": "ENS", "endpoint": "vitalik.eth", "version": "v1" }, { "name": "DID", "endpoint": "did:method:foobar", "version": "v1" }, { "name": "email", "endpoint": "mail@myagent.com" } ], "x402Support": false, "active": true, "registrations": [ { "agentId": 22, "agentRegistry": "{namespace}:{chainId}:{identityRegistry}" // e.g. eip155:1:0x742... } ], "supportedTrust": ["reputation", "crypto-economic", "tee-attestation"] } ``` The *type*, *name*, *description*, and *image* fields at the top SHOULD ensure compatibility with ERC-721 apps. The number and type of *endpoints* are fully customizable, allowing developers to add as many as they wish. The *version* field in endpoints is a SHOULD, not a MUST. Agents MAY advertise their endpoints, which point to an A2A agent card, an MCP endpoint, an ENS agent name, DIDs, or the agent's wallets on any chain (even chains where the agent is not registered). #### Endpoint Domain Verification (Optional) Since endpoints can point to domains not controlled by the agent owner, an agent MAY optionally prove control of an HTTPS endpoint-domain by publishing `https://{endpoint-domain}/.well-known/agent-registration.json` containing at least a `registrations` list (or the full agent registration file). Verifiers MAY treat the endpoint-domain as verified if the file is reachable over HTTPS and includes a `registrations` entry whose `agentRegistry` and `agentId` match the on-chain agent; if the endpoint-domain is the same domain that serves the agent’s primary registration file referenced by `agentURI`, this additional check is not needed because domain control is already demonstrated there. Agents SHOULD have at least one registration (multiple are possible), and all fields in the registration are mandatory. The *supportedTrust* field is OPTIONAL. If absent or empty, this ERC is used only for discovery, not for trust. #### Onchain metadata The registry extends ERC-721 by adding *getMetadata(uint256 agentId, string metadataKey)* and *setMetadata(uint256 agentId, string metadataKey, string metadataValue)* functions for optional extra on-chain agent metadata. When metadata is set, the following event is emitted: ```solidity event MetadataSet(uint256 indexed agentId, string indexed indexedMetadataKey, string metadataKey, bytes metadataValue) ``` The key `agentWallet` is reserved and cannot be set via *setMetadata()* or during *register()*. It represents the address where the agent receives payments and is initially set to the owner's address. To change it, the agent owner must prove control of the new wallet by providing a valid [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signature for EOAs or [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) for smart contract walletsβ€”by calling: ```solidity function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes calldata signature) external ``` When the agent is transferred, `agentWallet` is automatically reset to the zero address and must be re-verified by the new owner. #### Registration New agents can be minted by calling one of these functions: ```solidity struct MetadataEntry { string metadataKey; bytes metadataValue; } function register(string agentURI, MetadataEntry[] calldata metadata) external returns (uint256 agentId) function register(string agentURI) external returns (uint256 agentId) // agentURI is added later with setAgentURI() function register() external returns (uint256 agentId) ``` This emits one Transfer event, one MetadataSet event for each metadata entry, if any, and ```solidity event Registered(uint256 indexed agentId, string agentURI, address indexed owner) ``` #### Update agentURI The agentURI can be updated by calling the following function, which emits a URIUpdated event: ```solidity function setAgentURI(uint256 agentId, string calldata newURI) external event URIUpdated(uint256 indexed agentId, string newURI, address indexed updatedBy) ``` If the owner wants to store the entire registration file on-chain, the *agentURI* SHOULD use a base64-encoded data URI rather than a serialized JSON string: ```text data:application/json;base64,eyJ0eXBlIjoi... ``` ### Reputation Registry When the Reputation Registry is deployed, the *identityRegistry* address is passed to the constructor and publicly visible by calling: ```solidity function getIdentityRegistry() external view returns (address identityRegistry) ``` The feedback given by a *clientAddress* to an agent consists of a *score* (0-100), *tag1* and *tag2* (left to developers' discretion to provide maximum on-chain composability and filtering), a *endpoint* uri, a file uri pointing to an off-chain JSON containing additional information, and its KECCAK-256 file hash to guarantee integrity. We suggest using IPFS or equivalent services to make feedback easily indexed by subgraphs or similar technologies. For IPFS uris, the hash is not required. All fields except the *score* are OPTIONAL, so the off-chain file is not required and can be omitted. #### Giving Feedback New feedback can be added by any *clientAddress* calling: ```solidity function giveFeedback(uint256 agentId, uint8 score, string tag1, string tag2, string endpoint, string calldata feedbackURI, bytes32 feedbackHash) external ``` The *agentId* must be a validly registered agent. The *score* MUST be between 0 and 100. *tag1*, *tag2*, *endpoint*, *feedbackURI*, and *feedbackHash* are OPTIONAL. If the procedure succeeds, an event is emitted: ```solidity event NewFeedback(uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, uint8 score, string indexed indexedTag1, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash) ``` The feedback fields, except *feedbackURI* and *feedbackHash*, are stored in the contract storage along with the feedbackIndex (the number of feedback submissions that *clientAddress* has given to *agentId*). This exposes reputation signals to any smart contract, enabling on-chain composability. When the feedback is given by an agent (i.e., the client is an agent), the agent SHOULD use the address set in the on-chain optional walletAddress metadata as the clientAddress, to facilitate reputation aggregation. #### Revoking Feedback *clientAddress* can revoke feedback by calling: ```solidity function revokeFeedback(uint256 agentId, uint64 feedbackIndex) external ``` This emits: ```solidity event FeedbackRevoked(uint256 indexed agentId, address indexed clientAddress, uint64 indexed feedbackIndex) ``` #### Appending Responses Anyone (e.g., the *agentId* showing a refund, any off-chain data intelligence aggregator tagging feedback as spam) can call: ```solidity function appendResponse(uint256 agentId, address clientAddress, uint64 feedbackIndex, string calldata responseURI, bytes32 responseHash) external ``` Where *responseHash* is the KECCAK-256 file hash of the *responseURI* file content to guarantee integrity. This field is not required for IPFS URIs. This emits: ```solidity event ResponseAppended(uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, address indexed responder, string responseURI) ``` #### Read Functions ```solidity function getSummary(uint256 agentId, address[] calldata clientAddresses, string tag1, string tag2) external view returns (uint64 count, uint8 averageScore) // agentId is the only mandatory parameter; others are optional filters. // Without filtering by clientAddresses, results are subject to Sybil/spam attacks. See Security Considerations for details function readFeedback(uint256 agentId, address clientAddress, uint64 feedbackIndex) external view returns (uint8 score, string tag1, string tag2, bool isRevoked) function readAllFeedback(uint256 agentId, address[] calldata clientAddresses, string tag1, string tag2, bool includeRevoked) external view returns (address[] memory clientAddresses, uint64[] memory feedbackIndexes, uint8[] memory scores, string[] memory tag1s, string[] memory tag2s, bool[] memory revokedStatuses) // agentId is the only mandatory parameter; others are optional filters. Revoked feedback are omitted by default. function getResponseCount(uint256 agentId, address clientAddress, uint64 feedbackIndex, address[] responders) external view returns (uint64) // agentId is the only mandatory parameter; others are optional filters. function getClients(uint256 agentId) external view returns (address[] memory) function getLastIndex(uint256 agentId, address clientAddress) external view returns (uint64) ``` We expect reputation systems around reviewers/clientAddresses to emerge. **While simple filtering by reviewer (useful to mitigate spam) and by tag are enabled on-chain, more complex reputation aggregation will happen off-chain**. #### Off-Chain Feedback File Structure The OPTIONAL file at the URI could look like: ```jsonc { // MUST FIELDS "agentRegistry": "eip155:1:{identityRegistry}", "agentId": 22, "clientAddress": "eip155:1:{clientAddress}", "createdAt": "2025-09-23T12:00:00Z", "score": 100, // ALL OPTIONAL FIELDS "tag1": "foo", "tag2": "bar", "endpoint": "https://.../", "skill": "as-defined-by-A2A-or-OASF", "domain": "as-defined-by-OASF", "context": "as-defined-by-A2A", "task": "as-defined-by-A2A", "capability": "tools", // As per MCP: "prompts", "resources", "tools" or "completions" "name": "foo", // As per MCP: the name of the prompt, resource or tool "proofOfPayment": { "fromAddress": "0x00...", "toAddress": "0x00...", "chainId": "1", "txHash": "0x00..." }, // this can be used for x402 proof of payment // Other fields " ... ": { " ... " } // MAY } ``` ### Validation Registry **This registry enables agents to request verification of their work and allows validator smart contracts to provide responses that can be tracked on-chain**. Validator smart contracts could use, for example, stake-secured inference re-execution, zkML verifiers or TEE oracles to validate or reject requests. When the Validation Registry is deployed, the *identityRegistry* address is passed to the constructor and is visible by calling getIdentityRegistry(), as described above. #### Validation Request Agents request validation by calling: ```solidity function validationRequest(address validatorAddress, uint256 agentId, string requestURI, bytes32 requestHash) external ``` This function MUST be called by the owner or operator of *agentId*. The *requestURI* points to off-chain data containing all information needed for the validator to validate, including inputs and outputs needed for the verification. The *requestHash* is a commitment to this data (`keccak256` of the request payload) and identifies the request. All other fields are mandatory. A ValidationRequest event is emitted: ```solidity event ValidationRequest(address indexed validatorAddress, uint256 indexed agentId, string requestURI, bytes32 indexed requestHash) ``` #### Validation Response Validators respond by calling: ```solidity function validationResponse(bytes32 requestHash, uint8 response, string responseURI, bytes32 responseHash, string tag) external ``` Only *requestHash* and *response* are mandatory; *responseURI*, *responseHash* and *tag* are optional. This function MUST be called by the *validatorAddress* specified in the original request. The *response* is a value between 0 and 100, which can be used as binary (0 for failed, 100 for passed) or with intermediate values for validations with a spectrum of outcomes. The optional *responseURI* points to off-chain evidence or audit of the validation, *responseHash* is its commitment (in case the resource is not on IPFS), while *tag* allows for custom categorization or additional data. validationResponse() can be called multiple times for the same *requestHash*, enabling use cases like progressive validation states (e.g., β€œsoft finality” and β€œhard finality” using *tag*) or updates to validation status. Upon successful execution, a *ValidationResponse* event is emitted with all function parameters: ```solidity event ValidationResponse(address indexed validatorAddress, uint256 indexed agentId, bytes32 indexed requestHash, uint8 response, string responseURI, bytes32 responseHash, string tag) ``` The contract stores *requestHash*, *validatorAddress*, *agentId*, *response*, *lastUpdate*, and *tag* for on-chain querying and composability. #### Read Functions ```solidity function getValidationStatus(bytes32 requestHash) external view returns (address validatorAddress, uint256 agentId, uint8 response, string tag, uint256 lastUpdate) //Returns aggregated validation statistics for an agent. agentId is the only mandatory parameter; validatorAddresses and tag are optional filters function getSummary(uint256 agentId, address[] calldata validatorAddresses, string tag) external view returns (uint64 count, uint8 averageResponse) function getAgentValidations(uint256 agentId) external view returns (bytes32[] memory requestHashes) function getValidatorRequests(address validatorAddress) external view returns (bytes32[] memory requestHashes) ``` Incentives and slashing related to validation are managed by the specific validation protocol and are outside the scope of this registry. ## Rationale * **Agent communication protocols**: MCP and A2A are popular, and other protocols could emerge. For this reason, this protocol links from the blockchain to a flexible registration file including a list where endpoints can be added at will, combining AI primitives (MCP, A2A) and Web3 primitives such as wallet addresses, DIDs, and ENS names. * **Feedback**: The protocol combines the leverage of nomenclature already established by A2A (such as tasks and skills) and MCP (such as tools and prompts) with complete flexibility in the feedback signal structure. * **Gas Sponsorship**: Since clients don't need to be registered anymore, any application can implement frictionless feedback leveraging [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702). * **Indexing**: Since feedback data is saved on-chain and we suggest using IPFS for full data, it's easy to leverage subgraphs to create indexers and improve UX. * **Deployment**: We expect the registries to be deployed with singletons per chain. Note that an agent registered and receiving feedback on chain A can still operate and transact on other chains. Agents can also be registered on multiple chains if desired. ## Test Cases This protocol enables: * Crawling all agents starting from a logically centralized endpoint and discover agent information (name, image, services), capabilities, communication endpoints (MCP, A2A, others), ENS names, wallet addresses and which trust models they support (reputation, validation, TEE attestation) * Building agent explorers and marketplaces using any ERC-721 compatible application to browse, transfer, and manage agents * Building reputation systems with on-chain aggregation (average scores for smart contract composability) or sophisticated off-chain analysis. All reputation signals are public good. * Discovering which agents support stake-secured or zkML validation and how to request it through a standardized interface ## Security Considerations * Sybil attacks are possible, inflating the reputation of fake agents. The protocol's contribution is to make signals public and use the same schema. We expect many players to build reputation systems, for example, trusting or giving reputation to reviewers (and therefore filtering by reviewer, as the protocol already enables). * On-chain pointers and hashes cannot be deleted, ensuring audit trail integrity * Validator incentives and slashing are managed by specific validation protocols * While this ERC cryptographically ensures the registration file corresponds to the on-chain agent, it cannot cryptographically guarantee that advertised capabilities are functional and non-malicious. The three trust models (reputation, validation, and TEE attestation) are designed to support this verification need ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md). --- --- url: /v1.md --- --- --- url: /legacy-pre-v1/docs/implementation/validation-best-practices.md description: Practical guide for validators responding to validation requests --- ## Description Practical guide for validators responding to validation requests **Audience**: Validators, auditors, testing services ## Overview This guide provides best practices for validators responding to ERC-8004 validation requests, ensuring high-quality validation responses that build trust in the ecosystem. **What You'll Learn**: * βœ… Structure validation responses effectively * βœ… Choose appropriate validation types * βœ… Provide comprehensive evidence * βœ… Use zkSNARK proofs (Groth16, PLONK, STARK) * βœ… Leverage attachment pattern for complex evidence * βœ… Migrate from custom formats to ERC-8004 standard ## Validation Response Principles ### 1. Be Thorough and Evidence-Based **Every validation MUST include**: * Clear result (approved/rejected/conditional) * Detailed reasoning * Supporting evidence * Reproducible test methodology ❌ **Bad**: ```json { "result": "approved" } ``` βœ… **Good**: ```json { "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "security-audit", "result": "approved", "reasoning": "Agent passed security audit with 0 critical findings. Tested 15 attack vectors including reentrancy, integer overflow, and access control. All tests passed.", "attachments": [ { "name": "Security Audit Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "description": "Comprehensive security audit using Slither v0.9.6 + manual review" } ] } ``` ### 2. Match Validation Type to Request Ensure your response addresses the specific validation type requested: | Validation Type | What to Validate | Evidence to Provide | | ------------------ | ------------------------------- | --------------------------------------- | | `security-audit` | Code security, vulnerabilities | Audit report, test results | | `performance-test` | Speed, scalability, uptime | Benchmark data, load test results | | `accuracy-test` | Output correctness, reliability | Test cases, comparison data | | `zkml-proof` | Zero-knowledge ML verification | zkSNARK proof, public signals | | `tee-attestation` | Trusted execution environment | Attestation certificate, enclave report | | `crypto-economic` | Economic stake verification | Stake proof, slashing conditions | ### 3. Use Structured Result Values **Standard Results**: * `approved` - Agent meets validation criteria * `rejected` - Agent fails validation criteria * `conditional` - Agent meets criteria with conditions/warnings **With Confidence Scores**: ```json { "result": "approved", "confidence": 0.95, "reasoning": "95% confidence based on 1000 test cases. 5% margin due to limited edge case coverage." } ``` ## Validation Type Guides ### Security Audit **Checklist**: * \[ ] Smart contract vulnerabilities (if applicable) * \[ ] API endpoint security * \[ ] Access control validation * \[ ] Data privacy compliance * \[ ] Common attack vectors tested **Response Example**: ```json { "validationType": "security-audit", "result": "approved", "reasoning": "Comprehensive security audit completed. Scanned 5 smart contracts and 12 API endpoints. 0 critical findings, 2 low-severity recommendations provided.", "attachments": [ { "name": "Slither Automated Scan", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Automated scan results using Slither v0.9.6. 47 detectors run, 0 critical issues found." }, { "name": "Manual Review Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "description": "Manual code review by certified auditor. Focused on business logic and edge cases. 2 recommendations for optimization." }, { "name": "Penetration Test Results", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "description": "Tested 15 attack vectors including reentrancy, access control bypass, SQL injection. All tests passed." } ], "testMetadata": { "tool": "Slither v0.9.6", "manualReviewHours": 8, "auditor": "Certified Smart Contract Auditor (CSCA)", "date": "2025-12-20" } } ``` ### Performance Test **Metrics to Measure**: * Response time (average, p50, p95, p99) * Throughput (requests per second) * Uptime (percentage over test period) * Resource usage (CPU, memory, network) **Response Example**: ```json { "validationType": "performance-test", "result": "approved", "reasoning": "Agent demonstrated excellent performance under load. Average response time 1.2s, 99.9% uptime over 7-day test period.", "attachments": [ { "name": "Load Test Results", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "Results from 10,000 API calls over 7 days. Peak load: 100 concurrent requests." }, { "name": "Performance Graphs", "uri": "ipfs://bafkrei...", "mimeType": "image/png", "description": "Response time distribution and load curve graphs" } ], "metrics": { "avgResponseTime": 1.2, "p50ResponseTime": 0.9, "p95ResponseTime": 2.1, "p99ResponseTime": 3.5, "uptime": 99.9, "throughput": 50, "testDuration": "7 days", "totalRequests": 10000 } } ``` ### Accuracy Test **Test Methodology**: * Ground truth dataset * Comparison with baseline/control * Error rate calculation * Edge case coverage **Response Example**: ```json { "validationType": "accuracy-test", "result": "approved", "reasoning": "Agent achieved 94% accuracy on 1000-sample test dataset. Matches industry benchmark for blockchain analytics agents.", "attachments": [ { "name": "Test Dataset", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "1000 blockchain transactions with ground truth labels" }, { "name": "Accuracy Report", "uri": "ipfs://bafkrei...", "mimeType": "text/csv", "description": "Per-sample results with predicted vs actual labels" }, { "name": "Confusion Matrix", "uri": "ipfs://bafkrei...", "mimeType": "image/png", "description": "Visualization of classification performance" } ], "metrics": { "accuracy": 0.94, "precision": 0.93, "recall": 0.95, "f1Score": 0.94, "testSamples": 1000, "falsePositives": 30, "falseNegatives": 30 } } ``` ### zkML Proof (zkSNARK) **Purpose**: Zero-knowledge proof of ML model inference without revealing model weights or input data. **Supported Proof Systems**: * **Groth16** (most common, 8000+ validations on Base Sepolia) * **PLONK** (universal setup, more flexible) * **STARK** (no trusted setup, transparent) #### Groth16 Proof Example **Current Format** (used by ZyFi and others): ```json { "validationType": "zkml-proof", "result": "approved", "proof": { "pi_a": ["8070450532247928943", "1234567890123456789", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c", "validationRegistryAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", "chainId": 84532, "circuit": "zyfi-rebalancing-validation", "version": "1.0", "timestamp": 1766206835991 } ``` **ERC-8004 Standard Format** (recommended for new implementations): ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "result": "approved", "reasoning": "Zero-knowledge proof verified. Agent rebalancing algorithm meets specification.", "proofData": { "proof": { "pi_a": ["...", "...", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "circuit": "zyfi-rebalancing-validation", "verifierAddress": "0x4baf957..." } } ``` **Migration Path**: See [Validation Standard - Migration Guide](../03-validation-standard.md#migration-guides) #### PLONK Proof Example ```json { "validationType": "zkml-proof", "result": "approved", "proofData": { "proof": { "A": ["...", "..."], "B": ["...", "..."], "C": ["...", "..."], "Z": ["...", "..."], "T1": ["...", "..."], "T2": ["...", "..."], "T3": ["...", "..."], "Wxi": ["...", "..."], "Wxiw": ["...", "..."], "protocol": "plonk", "curve": "bn254" }, "publicSignals": [...], "circuit": "ml-inference-verification" } } ``` ### TEE Attestation **Purpose**: Verify agent runs in Trusted Execution Environment (Intel SGX, AMD SEV, AWS Nitro). **Response Example**: ```json { "validationType": "tee-attestation", "result": "approved", "reasoning": "Agent verified to run in Intel SGX enclave. Remote attestation successful.", "attachments": [ { "name": "SGX Quote", "uri": "ipfs://bafkrei...", "mimeType": "application/octet-stream", "description": "Intel SGX remote attestation quote" }, { "name": "Attestation Report", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "description": "IAS (Intel Attestation Service) verification report" } ], "attestationData": { "teeType": "intel-sgx", "mrenclave": "0xabc123...", "mrsigner": "0xdef456...", "isvprodid": 1, "isvsvn": 1, "reportData": "0x...", "verified": true, "timestamp": "2025-12-20T05:00:38Z" } } ``` ### Crypto-Economic Validation **Purpose**: Verify economic stake backing agent behavior. **Response Example**: ```json { "validationType": "crypto-economic", "result": "approved", "reasoning": "Agent has staked 10 ETH with slashing conditions. Economic security verified.", "stakeProof": { "amount": "10000000000000000000", "currency": "ETH", "stakingContract": "0xstaking123...", "slashingConditions": [ "Incorrect predictions >10% error rate", "Downtime >1 hour", "Data privacy breach" ], "lockupPeriod": "30 days", "transactionHash": "0x..." } } ``` ## Attachment Pattern for Complex Evidence ### Use Cases 1. **Multi-file Test Suites**: Upload ZIP with all test files 2. **Video Demonstrations**: Screen recordings of agent behavior 3. **Large Datasets**: Benchmark data, test results 4. **Binary Proofs**: zkSNARK proofs, attestation quotes 5. **Documentation**: Detailed methodology, audit reports ### Example: Comprehensive Security Validation ```json { "validationType": "security-audit", "result": "conditional", "reasoning": "Agent passed automated scans with 2 medium-severity recommendations. Recommend implementing before production deployment.", "attachments": [ { "name": "Automated Scan Results", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "size": 150000, "description": "Slither + MythX automated security scan results. 0 critical, 0 high, 2 medium findings." }, { "name": "Manual Review Report", "uri": "ipfs://bafkrei...", "mimeType": "application/pdf", "size": 2048000, "description": "16-page manual code review by certified auditor. Includes recommendations for gas optimization and edge case handling." }, { "name": "Test Suite Results", "uri": "ipfs://bafkrei...", "mimeType": "application/zip", "size": 5000000, "description": "Complete test suite with 250+ unit tests and 50+ integration tests. All tests passing." }, { "name": "Recommendations Document", "uri": "ipfs://bafkrei...", "mimeType": "text/markdown", "size": 10000, "description": "Actionable recommendations for addressing 2 medium-severity findings. Estimated 4-8 hours implementation time." } ] } ``` ## Response Templates ### Template 1: Approved Validation ```json { "agentRegistry": "eip155:CHAIN_ID:0x...", "agentId": AGENT_ID, "validatorAddress": "eip155:CHAIN_ID:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "VALIDATION_TYPE", "result": "approved", "reasoning": "[Clear explanation of what was tested and why it passed]", "attachments": [ { "name": "PRIMARY_EVIDENCE", "uri": "ipfs://...", "mimeType": "application/TYPE", "description": "[Detailed description of evidence]" } ] } ``` ### Template 2: Rejected Validation ```json { "agentRegistry": "eip155:CHAIN_ID:0x...", "agentId": AGENT_ID, "validatorAddress": "eip155:CHAIN_ID:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "VALIDATION_TYPE", "result": "rejected", "reasoning": "[Specific failures and why they disqualify the agent]", "failureDetails": [ { "category": "FAILURE_CATEGORY", "severity": "critical|high|medium|low", "description": "[Detailed description]" } ], "attachments": [ { "name": "FAILURE_EVIDENCE", "uri": "ipfs://...", "mimeType": "application/TYPE", "description": "[Evidence of failure]" } ], "recommendations": [ "Recommendation 1: [Actionable fix]", "Recommendation 2: [Actionable fix]" ] } ``` ### Template 3: Conditional Approval ```json { "result": "conditional", "reasoning": "Agent meets basic criteria but has limitations that users should be aware of.", "conditions": [ "Only use for datasets <10,000 rows", "Not suitable for real-time applications (response time >5s)", "Requires manual verification for high-stakes decisions" ], "attachments": [...] } ``` ## Validation Tiers and Weights When multiple validators validate the same agent, their validations are weighted differently based on validator tier: | Validator Tier | Weight Multiplier | Example | | -------------- | ------------------ | ---------------------------------- | | **Platform** | +30% per validator | 8004scan official validators | | **Official** | +20% per validator | EIP-8004 reference validators | | **Verified** | +10% per validator | KYC'd validators with track record | | **Community** | +5% per validator | Anonymous but reputable validators | **Best Practice**: If you're a verified or platform validator, clearly indicate this in your validation metadata: ```json { "validatorMetadata": { "tier": "verified", "organization": "SecureAudit Inc.", "certifications": ["CSCA", "ISO27001"], "website": "https://secureaudit.com" } } ``` ## Reproducibility ### Include Test Environment Details ```json { "testEnvironment": { "network": "sepolia", "blockNumber": 18500000, "timestamp": "2025-12-20T05:00:38Z", "toolsUsed": ["Slither v0.9.6", "MythX", "Foundry"], "testDuration": "7 days", "infrastructure": "AWS EC2 t3.large" } } ``` ### Provide Reproducible Test Scripts ```json { "attachments": [ { "name": "Test Automation Script", "uri": "ipfs://bafkrei...", "mimeType": "text/x-shellscript", "description": "Bash script to reproduce our validation tests. Requires Foundry and Node.js 18+." } ] } ``` ## Common Mistakes to Avoid ### Mistake 1: Insufficient Evidence ❌ **Bad**: "Looks good to me" βœ… **Good**: Detailed reasoning + multiple evidence attachments ### Mistake 2: Non-Standard Format ❌ **Bad**: Using custom JSON schema without ERC-8004 envelope βœ… **Good**: Wrap custom proofs in ERC-8004 standard format **Migration Example**: ```json // ❌ OLD (Groth16 standalone) { "proof": {...}, "publicSignals": [...], "verifierAddress": "0x..." } // βœ… NEW (ERC-8004 envelope + Groth16) { "agentRegistry": "eip155:84532:0x...", "agentId": 56, "validatorAddress": "eip155:84532:0x...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "proofData": { "proof": {...}, "publicSignals": [...], "protocol": "groth16" } } ``` ### Mistake 3: Vague Rejection Reasons ❌ **Bad**: "Failed security check" βœ… **Good**: "Failed reentrancy test. Attack vector: Contract allows recursive calls to withdraw() function without proper state updates. See attached exploit proof-of-concept." ### Mistake 4: Missing CAIP Format ❌ **Bad**: Using plain addresses ```json { "agentRegistry": "0x8004...", "validatorAddress": "0x4baf..." } ``` βœ… **Good**: Using CAIP-2 and CAIP-10 ```json { "agentRegistry": "eip155:84532:0x8004...", "validatorAddress": "eip155:84532:0x4baf..." } ``` ## Advanced Patterns ### Multi-Validator Consensus For critical validations, coordinate with multiple validators: ```json { "result": "approved", "reasoning": "Consensus validation by 3 platform-tier validators. All reached same conclusion independently.", "consensusMetadata": { "totalValidators": 3, "approvals": 3, "rejections": 0, "validators": ["eip155:1:0x1234...", "eip155:1:0x5678...", "eip155:1:0x9abc..."] } } ``` ### Time-Bound Validations For validations that expire: ```json { "result": "approved", "reasoning": "Security audit valid for 6 months. Re-validation recommended after major updates.", "validUntil": "2026-06-20T05:00:38Z", "renewalRequired": true } ``` ### Staged Validations For complex multi-stage validations: ```json { "result": "approved", "reasoning": "Passed all 3 validation stages.", "stages": [ { "stage": "automated-scan", "result": "passed", "completedAt": "2025-12-18T10:00:00Z" }, { "stage": "manual-review", "result": "passed", "completedAt": "2025-12-19T15:00:00Z" }, { "stage": "penetration-test", "result": "passed", "completedAt": "2025-12-20T05:00:38Z" } ] } ``` ## Resources * [Validation Standard](../03-validation-standard.md) * [Feedback Best Practices](feedback-best-practices.md) * [Agent Metadata Parsing](agent-metadata-parsing.md) * [Groth16 Proof System](https://eprint.iacr.org/2016/260.pdf) * [PLONK Protocol](https://eprint.iacr.org/2019/953.pdf) * 8004scan Validator Dashboard *(coming soon)* --- --- url: /legacy-pre-v1/docs/03-validation-standard.md description: Recommended offchain data format for ERC-8004 validation records --- ## Description Recommended offchain data profile for ERC-8004 validation records This document provides implementation-agnostic guidance for structuring validation request and response data referenced by the `requestUri` and `responseUri` fields in ERC-8004 Validation Registry contracts. ## Document Purpose This profile document offers **practical, non-normative recommendations** for validation data formats used with ERC-8004 Validation Registries, based on real-world usage patterns (analysis of 8,219 production records) and community feedback. ## Relationship to EIP-8004 > **Important**: This is **not** part of the official [EIP-8004](https://eips.ethereum.org/EIPS/eip-8004) specification. **Official EIP-8004** defines: * Validation Registry smart contract interface * Onchain fields: `validatorAddress`, `agentId`, `requestUri`, `responseUri`, `response`, `tag` * URI references to offchain data **This profile** suggests: * Offchain JSON structure for validation requests and responses * Three validation type patterns (crypto-economic, TEE, zkML) * Known custom format recognition (Groth16, PLONK, STARK) * Evidence attachment guidelines The official EIP does not mandate specific offchain formats. These are community-developed guidelines. ## Terminology This document follows conventions defined in [Conventions](00-CONVENTIONS.md), including: * **RFC 2119 keywords**: MUST, SHOULD, MAY * **Field types**: string, number, boolean, object, array * **CAIP formats**: CAIP-2 for blockchain IDs, CAIP-10 for addresses * **Timestamps**: ISO 8601 format in UTC For attachment file patterns, see [Attachment Pattern Guidelines](04-attachment-pattern-standard.md). ## Intended Audience * **Validators**: Creating validation requests and responses * **Agent Developers**: Understanding validation requirements * **Registry Implementers**: Building Validation Registry contracts and indexers * **Explorer Developers**: Parsing and displaying validation data ## Table of Contents 1. [Overview](#overview) 2. [Format Compatibility Approach](#format-compatibility-approach) 3. [Validation Request Profile](#validation-request-profile) 4. [Validation Response Profile](#validation-response-profile) 5. [Known Custom Formats](#known-custom-formats) 6. [Attachment Pattern](#attachment-pattern) 7. [Parse Status Indicators](#parse-status-indicators) 8. [Migration Guide](#migration-guide) 9. [Examples](#examples) ## Overview ### Onchain vs Offchain Data **Onchain** (Validation Registry contract): * `validatorAddress` (address) - Who is validating * `agentId` (uint256) - Which agent * `requestUri` (string) - Link to offchain request data * `requestHash` (bytes32) - Hash commitment (for HTTP URIs) * `responseUri` (string) - Link to offchain response data * `responseHash` (bytes32) - Hash commitment (for HTTP URIs) * `response` (uint8) - Score (0-100) * `tag` (bytes32) - Category/purpose * `lastUpdate` (uint256) - Unix timestamp of last update **Onchain Events** (for indexers): * `ValidationRequest`: `validatorAddress` (indexed), `agentId` (indexed), `requestUri`, `requestHash` (indexed) * `ValidationResponse`: `validatorAddress` (indexed), `agentId` (indexed), `requestHash` (indexed), `response`, `responseUri`, `responseHash`, `tag` > **Note for Indexers**: The `indexed` parameters can be efficiently filtered in event queries. > > **Timestamp Note**: The onchain `lastUpdate` field stores a Unix timestamp (uint256), while the offchain JSON uses `createdAt` in ISO 8601 format. This separation allows human-readable dates in JSON while maintaining efficient onchain storage. **Offchain** (referenced by `requestUri` / `responseUri`): * Detailed validation criteria * Proof data (zkSNARK, TEE attestation, etc.) * Test results and evidence * Context and methodology > **Non-normative - Guiding Principle**: These profiles aim to **guide, not block**. Implementations SHOULD accept all valid JSON data. Non-conforming formats MAY receive informational suggestions but SHOULD NOT be rejected. ## Format Compatibility Approach > **Non-normative**: This section describes 8004scan's recommended approach to handling diverse validation formats. ### Level 1: Recommended Profile βœ… **Parse Status**: `success` (no issues) or `warning` (minor suggestions) The community-recommended profile format for maximum interoperability. **When to Use**: * New validation systems * Multi-chain deployments * Public registries requiring interoperability * Integration with multiple ERC-8004 tools **Benefits**: * βœ… Better indexing and searchability * βœ… Frontend displays all metadata * βœ… Compatible with standard tooling * βœ… Easier integration across platforms ### Level 2: Known Custom Formats 🟑 **Parse Status**: `known_custom` Recognized specialized formats that don't conform to ERC-8004 but are widely used. **Supported Formats**: * **Groth16 zkSNARK Proof** - Complete zero-knowledge proofs * **PLONK Proof** - (Future support planned) * **STARK Proof** - (Future support planned) * **Halo2 Proof** - (Future support planned) **When to Use**: * Existing production systems (e.g., ZyFi protocol) * Specialized proof requirements * Migration period from custom to standard **Limitations**: * ⚠️ Limited metadata extraction * ⚠️ Manual format interpretation required * ⚠️ May not appear in some filtered views ### Level 3: Unknown Formats ⚠️ **Parse Status**: `unknown` Valid JSON that doesn't match any recognized pattern. **Handling**: * Data stored as-is in `offchain_request_data` / `offchain_response_data` * Displayed as raw JSON in UI * No automatic metadata extraction **Recommendation**: Consider migrating to Level 1 (Recommended Profile) for better interoperability, or contact the community to add Level 2 support for your format. ## Validation Request Profile ### Recommended Schema (Level 1) ```json { // ============ REQUIRED FIELDS ============ "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", // ============ RECOMMENDED FIELDS ============ "reasoning": "Request validation for agent rebalancing logic", "deadline": "2025-12-21T05:00:38Z", // ============ OPTIONAL: VALIDATION TYPE PAYLOADS ============ // For crypto-economic validations "job": { "taskDescription": "Validate portfolio rebalancing logic", "expectedOutputFormat": "JSON schema with rebalancing recommendations", "testDataUri": "ipfs://Qm...", "successCriteria": "Optimal allocation within 2% of benchmark" }, // For TEE attestation validations "teeRequest": { "attestationType": "sgx", "requiredEnclave": "ProductID:1,SecurityVersion:2", "measurementHash": "0x..." }, // For zkML proof validations "zkmlRequest": { "circuit": "zyfi-rebalancing-validation", "publicInputs": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c" }, // ============ OPTIONAL: BOUNTY ============ "bounty": { "amount": "1000000000000000000", "token": "eip155:84532:0x...", "conditions": "Paid upon successful validation within 24 hours" }, // ============ OPTIONAL: ATTACHMENTS ============ "attachments": [ { "name": "Test Dataset", "uri": "ipfs://Qmxxx...", "mimeType": "application/json", "size": 50000, "description": "Sample portfolio data for rebalancing validation", "uploadedAt": "2025-12-20T05:00:00Z" } ] } ``` ### Required Fields | Field | Type | Format | Description | | ------------------ | ------ | -------- | ------------------------------------------------------------------- | | `agentRegistry` | string | CAIP-10 | Agent's identity registry address (e.g., `eip155:84532:0x8004C...`) | | `agentId` | number | uint256 | Agent token ID | | `validatorAddress` | string | CAIP-10 | Validator's wallet address (e.g., `eip155:84532:0x4baf...`) | | `createdAt` | string | ISO 8601 | Request creation timestamp | | `validationType` | string | enum | One of: `crypto-economic`, `tee-attestation`, `zkml-proof` | ### Recommended Fields | Field | Type | Description | | ----------- | ----------------- | --------------------------------------- | | `reasoning` | string | Explanation of why validation is needed | | `deadline` | string (ISO 8601) | Expected response deadline | ### Optional Fields by Validation Type **Crypto-Economic** (`job` object): * `taskDescription` - What the agent should do * `expectedOutputFormat` - Format specification * `testDataUri` - Test data location * `successCriteria` - How success is measured **TEE Attestation** (`teeRequest` object): * `attestationType` - TEE type (e.g., "sgx", "sev", "tdx") * `requiredEnclave` - Enclave requirements * `measurementHash` - Expected measurement **zkML Proof** (`zkmlRequest` object): * `circuit` - Circuit identifier * `publicInputs` - Public inputs array * `verifierAddress` - Verifier contract address ## Validation Response Profile ### Recommended Schema (Level 1) ```json { // ============ REQUIRED FIELDS ============ "requestHash": "0x5c1a08c66c0489030f05990a83534280ee08da7cd944dc353bf4b661c5c96657", "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "agentId": 56, "response": 100, "createdAt": "2025-12-20T06:00:00Z", // ============ RECOMMENDED FIELDS ============ "result": "passed", "reasoning": "Agent successfully passed all validation tests", "confidence": 0.95, // ============ OPTIONAL: VALIDATION TYPE PROOFS ============ // For crypto-economic validations "executionProof": { "outputUri": "ipfs://Qmyyy...", "executionTime": "2.5s", "resourceUsage": { "cpu": "0.8 cores", "memory": "512MB", "network": "10MB" } }, // For TEE attestation validations "teeAttestation": { "quote": "0x...", "quoteSignature": "0x...", "reportData": "0x...", "timestamp": "2025-12-20T05:30:00Z" }, // For zkML proof validations "zkmlProof": { "proof": { "pi_a": ["...", "...", "1"], "pi_b": [[...], [...], ["1", "0"]], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifiedAt": "2025-12-20T05:45:00Z" }, // ============ OPTIONAL: ATTACHMENTS ============ "attachments": [ { "name": "Validation Report", "uri": "ipfs://Qmzzz...", "mimeType": "application/pdf", "size": 2048000, "description": "Comprehensive validation report with test results", "uploadedAt": "2025-12-20T05:50:00Z" } ] } ``` ### Required Fields | Field | Type | Format | Description | | ------------------ | ------ | --------------------- | ------------------------------ | | `requestHash` | string | bytes32 hex | Hash of the validation request | | `validatorAddress` | string | CAIP-10 | Validator's wallet address | | `agentId` | number | uint256 | Agent token ID | | `response` | number | 0-100 (uint8 onchain) | Validation score | | `createdAt` | string | ISO 8601 | Response creation timestamp | ### Recommended Fields | Field | Type | Values | Description | | ------------ | ------ | ----------------------------- | ------------------------------ | | `result` | string | `passed`, `failed`, `partial` | Validation result | | `reasoning` | string | - | Explanation of the result | | `confidence` | number | 0.0-1.0 | Confidence level in the result | ## Known Custom Formats ### Groth16 zkSNARK Proof **Format Type**: `groth16_zksnark` **Parse Status**: `known_custom` **Use Case**: Zero-knowledge proof validation (e.g., ZyFi rebalancing) ```json { // ============ PROOF STRUCTURE ============ "proof": { "pi_a": ["8070450532247928943", "1234567890123456789", "1"], "pi_b": [ ["...", "..."], ["...", "..."], ["1", "0"] ], "pi_c": ["...", "...", "1"], "protocol": "groth16", "curve": "bn128" }, // ============ PUBLIC SIGNALS ============ "publicSignals": ["4190804445", "1"], // ============ VERIFICATION INFO ============ "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c", "validationRegistryAddress": "0x8004C269D0A5647E51E121FeB226200ECE932d55", // ============ METADATA ============ "chainId": 84532, "circuit": "zyfi-rebalancing-validation", "version": "1.0", "timestamp": 1734675235991 } ``` **Known Usage**: * **ZyFi Protocol**: 8,000+ validations on Base Sepolia * **Circuit**: `zyfi-rebalancing-validation` * **Verifier**: `0x4baf957830423f36978039e32d95ee958aa0560c` **Detection Criteria**: * Has `proof` object with `pi_a`, `pi_b`, `pi_c` fields * Has `publicSignals` array * Has `verifierAddress` or `validationRegistryAddress` ## Attachment Pattern ### Overview Inspired by v1 frontend, the attachment pattern allows adding multiple evidence files to validation requests or responses. ### Attachment Object Schema ```typescript interface AttachmentFile { // Required name: string; // Display name (e.g., "Security Audit Report") uri: string; // IPFS/HTTPS/Arweave URI mimeType: string; // MIME type (e.g., "application/pdf") size: number; // File size in bytes // Optional description?: string; // Context: test environment, tools, timestamps uploadedAt?: string; // Upload timestamp (ISO 8601) } ``` ### Supported File Types * βœ… **Documents**: PDF, Word, Markdown * βœ… **Images**: PNG, JPEG, WebP, GIF * βœ… **Videos**: MP4, WebM (size limits apply) * βœ… **Data**: JSON, CSV, XML * βœ… **Archives**: ZIP, TAR * βœ… **Any other format** ### Usage Examples #### Example 1: Test Environment Info ```json { "name": "Load Test Results", "uri": "ipfs://QmXxx...", "mimeType": "application/json", "size": 50000, "description": "Conducted on testnet (Sepolia) on 2025-12-20 at 10:00 UTC. Agent handled 1000 req/sec with 99.9% uptime.", "uploadedAt": "2025-12-20T10:00:00Z" } ``` #### Example 2: Security Audit ```json { "name": "Security Audit Report", "uri": "ipfs://QmYyy...", "mimeType": "application/pdf", "size": 2048000, "description": "Automated scan using Slither v0.9.6 and Mythril v0.23.15. Manual review by certified auditor.", "uploadedAt": "2025-12-20T09:00:00Z" } ``` #### Example 3: Benchmark Data ```json { "name": "Benchmark Data", "uri": "ipfs://QmZzz...", "mimeType": "text/csv", "size": 100000, "description": "10,000 iterations, AWS c5.xlarge instance, Node.js v20.10.0, isolated network environment.", "uploadedAt": "2025-12-20T08:00:00Z" } ``` ## Parse Status Indicators When querying validation data via the 8004scan API, each record includes a `parse_status` field indicating format compliance. | Status | Meaning | UI Display | Action Required | | -------------- | ---------------------------------------- | --------------------- | ------------------ | | `success` | ERC-8004 compliant, no warnings | βœ… Green checkmark | None | | `warning` | ERC-8004 compliant, minor suggestions | 🟑 Yellow warning | Review suggestions | | `known_custom` | Recognized custom format (e.g., Groth16) | 🟑 Custom badge | Consider migrating | | `unknown` | Unrecognized format | ⚠️ Grey question mark | Update to standard | | `error` | Parse/fetch failure | ❌ Red error | Fix URI/data | ### Frontend Integration Example ```typescript function getStatusBadge(parseStatus: string) { switch (parseStatus) { case 'success': return βœ… Standard case 'warning': return 🟑 Warning case 'known_custom': return 🟑 Custom Format case 'unknown': return ⚠️ Unknown case 'error': return ❌ Error } } ``` ## Migration Guide ### From Groth16 to ERC-8004 Standard **Current Format** (Level 2 - Known Custom): ```json { "proof": {...}, "publicSignals": [...], "verifierAddress": "0x4baf957...", "chainId": 84532, "circuit": "zyfi-rebalancing-validation" } ``` **Option 1: Minimal Upgrade** (Add ERC-8004 envelope): ```json { // Add ERC-8004 required fields "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", // Wrap existing proof in proofData "zkmlProof": { "proof": {...}, "publicSignals": [...], "protocol": "groth16", "circuit": "zyfi-rebalancing-validation" } } ``` **Option 2: Full Upgrade** (Use attachments): ```json { // ERC-8004 envelope "agentRegistry": "eip155:84532:0x8004C269...", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957...", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", // Main explanation "reasoning": "Agent rebalancing logic validated using zkSNARK proof", // Upload proof as separate attachment "attachments": [ { "name": "Groth16 Proof", "uri": "ipfs://bafkrei...", "mimeType": "application/json", "size": 4096, "description": "ZyFi rebalancing validation circuit proof", "uploadedAt": "2025-12-20T05:00:00Z" } ] } ``` ## Examples ### Example 1: Complete zkML Validation Request ```json { "agentRegistry": "eip155:84532:0x8004C269D0A5647E51E121FeB226200ECE932d55", "agentId": 56, "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "createdAt": "2025-12-20T05:00:38Z", "validationType": "zkml-proof", "reasoning": "Validate agent's portfolio rebalancing algorithm using zero-knowledge proof", "deadline": "2025-12-21T05:00:38Z", "zkmlRequest": { "circuit": "zyfi-rebalancing-validation", "publicInputs": ["4190804445", "1"], "verifierAddress": "0x4baf957830423f36978039e32d95ee958aa0560c" }, "attachments": [ { "name": "Test Portfolio Data", "uri": "ipfs://QmXxx...", "mimeType": "application/json", "size": 50000, "description": "Sample portfolio with 100 assets for validation testing", "uploadedAt": "2025-12-20T04:00:00Z" } ] } ``` ### Example 2: Complete Validation Response with Groth16 Proof ```json { "requestHash": "0x5c1a08c66c0489030f05990a83534280ee08da7cd944dc353bf4b661c5c96657", "validatorAddress": "eip155:84532:0x4baf957830423f36978039e32d95ee958aa0560c", "agentId": 56, "response": 100, "createdAt": "2025-12-20T06:00:00Z", "result": "passed", "reasoning": "Agent's rebalancing logic validated successfully. All test cases passed.", "confidence": 1.0, "zkmlProof": { "proof": { "pi_a": ["8070450532247928943", "1234567890123456789", "1"], "pi_b": [ ["12345...", "67890..."], ["11111...", "22222..."], ["1", "0"] ], "pi_c": ["99999...", "88888...", "1"], "protocol": "groth16", "curve": "bn128" }, "publicSignals": ["4190804445", "1"], "verifiedAt": "2025-12-20T05:45:00Z" }, "attachments": [ { "name": "Validation Report", "uri": "ipfs://QmYyy...", "mimeType": "application/pdf", "size": 1024000, "description": "Comprehensive validation report with detailed test results and methodology", "uploadedAt": "2025-12-20T05:50:00Z" } ] } ``` ## See Also * [Feedback Standard](02-feedback-standard.md) - Reputation Registry offchain data format * [Agent Metadata Standard](01-agent-metadata-standard.md) - AgentURI metadata format * [Validation Best Practices](implementation/validation-best-practices.md) - Implementation guide * [Sources & References](reference/sources.md) - Methodology and data sources --- --- url: /docs/extensions/05-value-decimals-patterns.md --- # Value Decimals Patterns (ERC-8004 Extension) > **Status**: Draft > **Created**: 2026-01-30 ## Introduction The transition from a fixed 0-100 `score` to a flexible `value` (`int128`) and `valueDecimals` (`uint8`) system in ERC-8004 v2.0 opens up a wide range of use cases for agent feedback. This document outlines standard patterns and best practices for utilizing this system effectively to capture diverse metrics like uptime, financial yield, latency, and binary verifications. ## Core Concept The feedback system uses a fixed-point arithmetic model similar to ERC-20 tokens: * **`value` (`int128`)**: The raw integer value stored on-chain. * **`valueDecimals` (`uint8`)**: The number of decimal places to interpret the value. * **`tag1` (`string`)**: The identifier that defines *what* is being measured. To get the "real world" number: $$ \text{Real Value} = \frac{\text{value}}{10^{\text{valueDecimals}}} $$ ## Standard Patterns To ensure composability across the ecosystem, agents and clients SHOULD adhere to these standard patterns for common metrics. ### 1. Percentages and Probability For metrics representing a fraction of 100 or a probability. * **Recommended `tag1`**: `uptime`, `successRate`, `confidence` * **Recommended `valueDecimals`**: 2 (allows for 99.99%) or 4 (allows for 99.9999%) * **Example**: 99.77% Uptime * `value`: `9977` * `valueDecimals`: `2` * `Calculation`: $9977 / 10^2 = 99.77$ ### 2. Binary Status / Flags For boolean states (True/False). * **Recommended `tag1`**: `reachable`, `ownerVerified`, `kycCleared` * **Recommended `valueDecimals`**: 0 * **Values**: `1` for True, `0` for False. * **Example**: Endpoint is reachable * `value`: `1` * `valueDecimals`: `0` ### 3. Financial Metrics For revenues, costs, or yields. * **Recommended `tag1`**: `revenues`, `dailyCost`, `tradingYield` * **Recommended `valueDecimals`**: * `0` or `2` for fiat-pegged values (e.g., USD cents). * `6` or `18` for crypto-native values (USDC, ETH). * **Example**: $560.00 Revenue * `value`: `560` * `valueDecimals`: `0` (if representing whole dollars) or `56000` / `2` (cents) * **Example**: -3.2% Yield * `value`: `-32` * `valueDecimals`: `1` ### 4. Time and Latency For duration measurements. * **Recommended `tag1`**: `responseTime`, `processingTime`, `blockDelay` * **Recommended `valueDecimals`**: 0 * **Unit Convention**: * Milliseconds (ms) for `responseTime` * Seconds (s) for `processingTime` * Blocks for `blockDelay` * **Example**: 560ms Response Time * `value`: `560` * `valueDecimals`: `0` ### 5. Ratings and Scores For subjective or objective ratings on a specific scale. * **Recommended `tag1`**: `quality`, `accuracy`, `starred` * **Recommended `valueDecimals`**: 1 (allows for 4.5 stars) * **Example**: 4.5/5 Stars * `value`: `45` * `valueDecimals`: `1` ## Domain-Specific Patterns Beyond general metrics, specific industries can standardize on the following patterns to ensure interoperability among specialized agents. ### 6. AI & LLM Agents Metrics specific to Large Language Model performance and costs. * **Throughput (Tokens per Second)** * `tag1`: `tps` * `valueDecimals`: 1 * *Example*: 45.5 tok/s β†’ `value: 455`, `decimals: 1` * **Cost Efficiency** (e.g., Cost per 1M tokens) * `tag1`: `costPer1M` * `valueDecimals`: 6 (Micro-USD or Gwei) * *Example*: $0.50 β†’ `value: 500000`, `decimals: 6` ### 7. DeFi & Trading Agents Risk and return metrics for autonomous financial agents. * **Sharpe Ratio** (Risk-adjusted return) * `tag1`: `sharpeRatio` * `valueDecimals`: 2 * *Example*: Ratio of 2.55 β†’ `value: 255`, `decimals: 2` * **Max Drawdown** (Risk metric) * `tag1`: `maxDrawdown` * `valueDecimals`: 2 * *Example*: -15.40% β†’ `value: -1540`, `decimals: 2` (Note the negative sign) ### 8. DePIN & Physical Infrastructure For agents managing hardware, sensors, or location-based services. * **Geospatial Coordinates** (GPS) * `tag1`: `latitude` / `longitude` * `valueDecimals`: 6 (Standard GPS precision) * *Example*: NYC Lat 40.712800 β†’ `value: 40712800`, `decimals: 6` * **Signal Strength** (RSSI/dBm) * `tag1`: `signalStrength` * `valueDecimals`: 0 * *Example*: -75 dBm β†’ `value: -75`, `decimals: 0` * **Network Bandwidth** * `tag1`: `uploadSpeed` / `downloadSpeed` * `valueDecimals`: 1 (Mbps) * *Example*: 100.5 Mbps β†’ `value: 1005`, `decimals: 1` ## Comprehensive Reference Table | Metric Category | `tag1` (Convention) | `value` Example | `valueDecimals` | Human Readable | Notes | | :-------------- | :------------------- | :-------------- | :-------------- | :------------- | :------------------------------------------ | | **Boolean** | `reachable` | 1 | 0 | True | 1=True, 0=False | | | `ownerVerified` | 1 | 0 | True | | | **Quality** | `starred` | 87 | 0 | 87/100 | Classic 0-100 score | | | `f1Score` | 945 | 3 | 0.945 | | | **Performance** | `uptime` | 9999 | 2 | 99.99% | | | | `successRate` | 985 | 1 | 98.5% | | | **Latency** | `responseTime` | 250 | 0 | 250ms | Default unit: ms | | | `blocktimeFreshness` | 2 | 0 | 2 blocks | Default unit: blocks | | **Financial** | `revenues` | 150050 | 2 | 1500.50 | Currency usually implied by context or tag2 | | | `tradingYield` | -155 | 2 | -1.55% | Negative values supported | | **AI / LLM** | `tps` | 505 | 1 | 50.5 tok/s | | | **DeFi Risk** | `sharpeRatio` | 210 | 2 | 2.10 | | | | `maxDrawdown` | -1250 | 2 | -12.50% | | | **DePIN/Geo** | `latitude` | 40712800 | 6 | 40.712800 | Standard GPS precision | | | `signalStrength` | -75 | 0 | -75 dBm | | | **Hardware** | `gpuMemory` | 24 | 0 | 24 GB | Context needed | ## Best Practices 1. **Tag Consistency**: Always use `camelCase` for `tag1`. 2. **Explicit Units**: If the unit isn't obvious (like `revenues`), consider using `tag2` to specify it (e.g., `tag1="revenues"`, `tag2="USD"`). 3. **Negative Values**: Utilize the signed nature of `int128` for metrics like loss, drift, or deviations. 4. **Handling Overflow**: `int128` is large ($10^{38}$), but extremely high precision decimals (e.g., 18) combined with large values can still overflow in off-chain calculations if not handled with BigInt libraries. 5. **Aggregation**: When aggregating metrics (e.g., calculating average response time), ensure you only aggregate feedback with the exact same `tag1` AND `valueDecimals` to avoid magnitude errors. If decimals differ, normalize them first. ## Migration from Score (v1.x) If your system relies on the legacy `score` (0-100): * Treat `score` as `tag1="quality"` (or empty tag), `value=score`, `valueDecimals=0`. * 100 becomes `value=100`, `valueDecimals=0`.