跳到主要内容

ERC-8004 Trustless Agents 参考实现 — 架构与原理

30 秒导读: 这是一套以太坊智能合约,把 "AI agent 之间怎么在没有预先信任下打交道" 拆成三个极简的链上注册表——身份(每个 agent 是一枚 ERC-721 NFT)、声誉(任何人可给带符号的定点评分)、验证(指定第三方独立复核工作)。链上只存能被别的合约读取、聚合的 "锚点" 和事件;真正的大块数据(注册资料、评价详情、验证证据)放到 URI(通常 IPFS)走链下。它解决的核心问题:两个互不认识的 agent(或人与 agent),如何跨组织边界发现彼此、评价彼此、核验彼此,而不必先建立信任关系。


1. 这是什么(零基础也能懂)

一句话定义: ERC-8004 是一个 "可信 agent" 的链上目录 + 打分 + 复核标准,本仓库是它的参考实现(三个 Solidity 合约 + 测试 + 部署脚本)。

解决什么问题 / 给谁用。 设想一个开放的 agent 经济:你的 agent 想雇另一个 agent 干活(比如做一次数据分析),但两边素不相识。三个问题立刻冒出来:

问题白话由谁回答
它是谁?这个 agent 有没有一个稳定、可寻址、可转让的身份身份注册表(Identity)
它靠谱吗?过去和它打过交道的人给了什么评价声誉注册表(Reputation)
这次干得对吗?这一单具体工作,有没有独立第三方核验过验证注册表(Validation)

三个注册表分别回答这三问,合起来就是 "无预先信任(trustless)" 的地基。

它能做什么(功能):

  • 把一个 agent 注册成一枚 NFT,带一份链下注册资料(agentURI)和任意键值元数据。
  • 给 agent 绑定一个经签名验证的收款钱包(agentWallet)。
  • 让任何人对 agent 留下带符号、带小数的评分(支持负值,如 -3.2% 的收益率)。
  • 让 agent 请求某个指定验证者复核工作,验证者回一个 0–100 的分数 + 证据 URI。
  • 所有动作都发事件,链下索引器可据此聚合出排行榜、信誉分。

用起来什么样。 一次最小的端到端流程(示意):

// 示意,非源码 —— 演示三个注册表如何串起来
uint256 agentId = identity.register("ipfs://agent-card.json"); // ① 注册身份,拿到 agentId
reputation.giveFeedback(agentId, 87, 0, "starred", "", "", "", 0); // ② 有人打了 87/100 的分
validation.validationRequest(validator, agentId, "ipfs://job.json", hash); // ③ 请求独立复核
// 验证者随后调用 validation.validationResponse(hash, 95, ...) 给出 95 分

一句话直觉/类比: 把它想成 agent 世界的 "工商注册 + 大众点评 + 第三方质检",但三者都写在公开可组合的链上账本里,任何合约都能读。


2. 顶层全景(它大概怎么转)

怎么读这张图: 从左到右是 "先有身份,才谈得上声誉和验证";声誉和验证两表都在构造时锚定同一个身份表,靠 agentId 串联;重数据一律不上链,只把 URI + 哈希写进事件。

┌──────────────────────────────┐
注册 agent ─────────► │ ① 身份注册表 (Identity) │
(register) │ agent = ERC-721 NFT │
│ agentId · agentURI · wallet │
└───────────────┬────────────────┘
│ 两表构造时传入它的地址
│ 所有写操作先问 "agentExists?"
┌─────────────────────┴─────────────────────┐
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ ② 声誉注册表 (Reputation) │ │ ③ 验证注册表 (Validation) │
│ 任何人 giveFeedback │ │ agent 请求 → 指定验证者回应 │
│ int128 value + decimals │ │ requestHash 承诺 · 0-100 │
└───────────┬────────────────┘ └───────────┬────────────────┘
│ │
└──────────────► 事件 + 链下 URI/IPFS ◄───┘
(索引器聚合排行榜 / 信誉分,链上只存锚点)

部件一句话职责:

部件干什么在哪个文件
身份注册表把 agent 铸成 NFT,管 URI、元数据、收款钱包src/IdentityRegistry.sol
声誉注册表收集对 agent 的带符号定点评分,可撤销、可回应src/ReputationRegistry.sol
验证注册表记录 "请求复核 → 验证者回应" 的一问一答src/ValidationRegistry.sol
部署脚本按依赖顺序部署三表(身份先行)script/Deploy.s.sol

主线走一遍(高层,不进代码):

  1. agent 调 register(),身份表铸一枚 NFT,分配 agentId,并把 agentURI 指向链下的注册资料(IdentityRegistry.sol:270 _mintAgent)。
  2. 用过它的人调 giveFeedback,把一条评分写进声誉表——无需预授权,任何人可写,链下再靠可信名单过滤(ReputationRegistry.sol:90)。
  3. agent(或其操作者)调 validationRequest,点名一个独立验证者;验证者调 validationResponse 回一个 0–100 分(ValidationRegistry.sol:89:146)。
  4. 三表全程只发事件、只存 URI + 哈希;排行榜、加权信誉这类重计算留给链下索引器。

3. 阅读地图(建议顺序)

按 "由浅入深" 读:先在本页建立全景,再逐个注册表下钻,最后看部署与规范演进。

顺序章节讲什么适合谁先读
0这是什么 · 全景 · 阅读地图本页:三表全景与主线所有人
1身份注册表:agent 即 NFTERC-721 铸造、元数据、EIP-712/ERC-1271 钱包验证、转让即清空钱包想懂身份地基
2声誉注册表:带符号定点评分int128 value + uint8 valueDecimals 定点数、撤销/回应、链上聚合与 gas 陷阱想懂打分模型
3验证注册表:独立复核与承诺哈希requestHash 承诺、防自证、一请求多次回应、pending 与不存在的区分想懂第三方核验
4部署、集成与规范演进部署依赖顺序、链下集成约定、Jan 2026 规范相对旧版的改动想落地部署

4. 巧妙之处(可带走的技术)

这几个设计决策是本实现的 "精华",不显然但值得借鉴:

  • 身份即 NFT,白嫖整套 NFT 基建。 agent 直接是 ERC-721 token,天然可转让、可在钱包/市场里浏览,tokenURI 复用为 agentURI;不用另造一套身份系统(IdentityRegistry.sol:31 合约声明 is ERC721URIStorage)。

  • 收款钱包要 "对方签名认领",且转让即作废。 绑定 agentWallet 时,新钱包必须用 EIP-712 签名(合约钱包走 ERC-1271 回退)证明自己愿意收款,防止把别人地址栽赃成收款方(IdentityRegistry.sol:186 setAgentWallet)。NFT 一旦转手,_transfer 把钱包重置为零地址,逼新主人重新认领(IdentityRegistry.sol:318)。

  • 评分用带符号定点数,而非裸 uint8 分数。 int128 value + uint8 valueDecimals 一套两字段,既能表 87/100 的评分,也能表 -3.2% 的收益、99.77% 的在线率(ReputationRegistry.sol:42 Feedback 结构)。链上聚合时先找最大小数位再归一化求和,避免精度错配(ReputationRegistry.sol:198 getSummary)。

  • 声誉去掉了预授权,把反女巫甩给链下。 Jan 2026 版明确 "无需 pre-authorization,任何人可 giveFeedback",垃圾评分靠链下按可信评价者过滤,而不是在链上做昂贵的准入(ReputationRegistry.sol:80 注释与函数)。

  • 验证用 "承诺哈希 + 防自证" 保证独立性。 requestHash 强制非空且全局唯一、不可被覆盖(防劫持),且验证者不能是 agent 主人或请求发起人(防自己给自己盖章)(ValidationRegistry.sol:112:117)。

  • 读函数诚实地为链下服务。 getSummary/readAllFeedback 明确标注 "给链下用,热门 agent 不加 clientAddresses 过滤会撞 gas 上限";getValidationStatus 靠返回值 + requestExists 区分 "不存在 / 待处理 / 已回应" 三态(ReputationRegistry.sol:198ValidationRegistry.sol:198)。


5. 代码地图(导航索引)

grep 符号名比行号抗漂移。下表是各主题的真实入口:

主题文件路径符号名
agent 铸造(NFT + 初始化钱包)src/IdentityRegistry.sol_mintAgent
三种注册重载src/IdentityRegistry.solregister
收款钱包签名认领src/IdentityRegistry.solsetAgentWallet / unsetAgentWallet
转让即清空钱包src/IdentityRegistry.sol_transfer
保留键 agentWallet 保护src/IdentityRegistry.solsetMetadata
留下评分(无需预授权)src/ReputationRegistry.solgiveFeedback
评分数据结构(定点数)src/ReputationRegistry.solFeedback
撤销 / 回应评分src/ReputationRegistry.solrevokeFeedback / appendResponse
链上聚合(归一化求和)src/ReputationRegistry.solgetSummary
请求验证(防自证 + 承诺哈希)src/ValidationRegistry.solvalidationRequest
验证者回应src/ValidationRegistry.solvalidationResponse
三态状态查询(含 responseHash)src/ValidationRegistry.solgetValidationStatus
按依赖顺序部署三表script/Deploy.s.solDeploy.run

事件锚点(链下索引器订阅这些):Registered / AgentWalletSet / MetadataSet(身份)、NewFeedback / FeedbackRevoked / ResponseAppended(声誉)、ValidationRequest / ValidationResponse(验证)。定义见各自 src/interfaces/I*.sol

依据:合约声明 IdentityRegistry.sol:31;_mintAgent IdentityRegistry.sol:270;setAgentWallet IdentityRegistry.sol:186;_transfer 重置钱包 IdentityRegistry.sol:318;giveFeedback 无预授权 ReputationRegistry.sol:80,90;Feedback 结构 ReputationRegistry.sol:42;getSummary 归一化 ReputationRegistry.sol:198;validationRequest 防自证/唯一性 ValidationRegistry.sol:112,117;getValidationStatus 三态 ValidationRegistry.sol:198;部署顺序 script/Deploy.s.sol:33,38,43。以上引用 as-of commit 2e5e79d