跳到主要内容

AGNTCY Directory (dir) — 架构与原理

30 秒导读: dir 是 AGNTCY “Internet of Agents” 里的目录服务——你把一个 AI agent 的能力描述(技能、领域、部署位置)写成一条记录,dir 给它算一个全球唯一的内容指纹(CID)、存进镜像仓库、在P2P 网络里宣告“我这有这条记录”,别的节点就能按能力搜到它并拉回来。再配上密码学签名 + 域名校验,让“这个 agent 是 cisco.com 发的、内容没被改过”可被验证。把它想成 agent 世界的 DNS + npm + Docker Registry 三合一


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

  • 一句话定义: dir(Directory)是一个分布式的 AI agent 目录:发布、交换、发现“关于 agent 的信息”。它不运行 agent,只登记和分发 agent 的描述记录

  • 解决什么问题 / 给谁用: 假设你写了一个会做“机器学习数据清洗”的 agent,想让别人(或别的 agent)能按能力找到它——就像在 npm 上 search machine-learning,或者像 DNS 那样把名字解析到具体地址。dir 就是这层基础设施,给 agent 开发者、agent 运行时(orchestrator)、以及做 agent 市场的人用。

  • 它能做什么(功能):

    • 把一条 agent 描述记录存起来并给它一个不可篡改的内容 ID(CID)。
    • P2P 网络里发布(announce)和发现(search)记录,按技能 / 领域 / 模块等标签匹配。
    • Sigstore 给记录签名,并校验签名 + 域名所有权(类似“这个包确实是 cisco.com 发布的”)。
    • 给记录起人类可读的名字(cisco.com/agent:v1.0.0),像 Docker tag 一样解析。
    • 提供 CLI(dirctl)+ gRPC API + Go/Python/JS SDK + HTTP 网关
  • 用起来什么样: 一条最小的命令行交互(子命令注册见 cli/cmd/root.goRootCmd.AddCommand,:118 起;cli/cli.go 只是 main() 入口,各子命令实现散在 cli/cmd/ 的子目录):

    # 把一条 OASF 记录推入本地目录,拿回它的 CID
    dirctl push record.json
    # → baeabc123...(这就是这条记录的全球唯一指纹)

    # 按技能在网络里搜索别的 peer 发布的记录
    dirctl routing search --skill "AI/Machine Learning" --min-score 1

    # 把搜到的 CID 拉回本地
    dirctl pull baeabc123...
  • 一句话直觉/类比:dir 想成 “agent 的 BitTorrent + Docker Registry”:

    • 内容寻址(CID)= BitTorrent 的 infohash:ID 由内容算出来,内容一变 ID 就变,天然防篡改。
    • DHT 宣告 = BitTorrent 的 tracker / DHT:“谁有这块内容”,而不是把内容本身塞进 DHT。
    • OCI 仓库 = Docker Registry:真正的字节存这里,按 CID 当 tag 取。

本节不碰底层代码。下一节给你整个系统“怎么转”的全景。


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

dir 的服务端(server/)是一个 gRPC 服务进程,注册了一组各管一摊的子服务。它们围绕一条记录的生命周期协作:算指纹 → 存 → 索引 → 宣告 → 被发现 → 被验证

部件一句话职责

部件干什么在哪个文件
Store(StoreService)内容寻址存储:Push/Pull/Lookup/Delete,把记录存进 OCI 仓库server/store/oci/oci.go
Routing(RoutingService)P2P 发布/发现:DHT 宣告 CID + 拉取式标签发现 + 本地标签缓存server/routing/routing.go
Search(SearchService)本地数据库二级索引:按 name/skill/domain 等做通配查询server/controller/search.go
Sign(SignService,客户端侧)用 Sigstore(cosign)给记录签名,签名作为 referrer 附件存储client/sign.go
Naming(NamingService)名字解析(name:version@cid)+ 域名所有权校验状态proto/agntcy/dir/naming/v1/naming_service.proto
Sync(SyncService)节点间单向同步(从远端 registry 复制记录)server/controller/sync.go
Reconciler独立后台进程:索引、registry 同步、周期性重新校验名字reconciler/README.md
HTTP Gateway把 gRPC 包成 HTTP/UI(AI Finder 目录浏览器)server/gateway/

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

下图怎么读:从上到下是一条记录从“被推入”到“被别的节点发现”的生命周期;左边是本地节点,右边是网络对端。

你 (dirctl / SDK)
│ push record.json

┌───────────────────────────────────────────────┐
│ 本地 dir 节点 │
│ │
│ ① StoreController.Push │
│ • OASF schema 校验记录合法 │
│ • OCI 存字节 → 算出 CID(内容指纹) │
│ • 写入本地搜索数据库(二级索引) │
│ │ CID │
│ ▼ │
│ ② RoutingController.Publish │
│ • 本地 KV 记下 “/records/CID” + 标签 │
│ • DHT.Provide(CID):向网络宣告“我有它” │───┐ DHT 宣告
│ • GossipSub 广播标签(可选,快路径) │ │
└───────────────────────────────────────────────┘ │

┌──────────────────────────────────────┐
│ 远端 dir 节点 │
│ ③ 收到 CID 宣告通知 │
│ • 缓存里没有? → RPC 拉回记录 │
│ • 从内容里抽出标签(技能/领域) │
│ • 把标签按 CID/PeerID 缓存进本地 KV │
│ │
│ ④ 用户 search --skill "AI" │
│ • 只查本地缓存的标签(不打网络) │
│ • OR 逻辑打分,过 min-score 阈值 │
│ • 返回 {CID, peer, 匹配分} │
│ ⑤ pull(CID) → 直接从源 peer 取字节 │
└──────────────────────────────────────┘

三个要记住的设计支点:

  1. 内容寻址是地基。 记录的 ID 不是数据库自增主键,而是对内容算的 SHA-256 → CID。所以同一条记录在任何节点上 ID 都一样,且改一个字节 ID 就变(详见 01)。

  2. DHT 只放“谁有”,不放“是什么”。 网络层只宣告 Provide(CID)(我这有这块内容),标签(技能/领域)靠对端把内容拉回来现抽——这叫拉取式发现(pull-based discovery),是为了绕开 DHT 只能可靠到达 ~20 个最近 peer 的限制(详见 02)。

  3. 可信是叠加层,不是必需层。 签名和域名校验是附加在记录上的 referrer 附件,谁需要谁验,不影响存储/发现的主路径(详见 03)。


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

按“一条记录的旅程”从存到发现到验证,由浅入深:

  1. 01 · 内容寻址存储 — Push 一条记录:OASF 校验 → OCI 存字节 → 算 CID → CID 一致性自检。理解“为什么 ID 等于内容指纹”。先读这章,后面全建立在 CID 上。

  2. 02 · 路由与发现 — Publish/List/Search 三件套。重点理解拉取式发现:DHT 只宣告 CID,标签靠拉内容现抽 + 本地缓存,Search 是“查本地缓存 + OR 打分”。这是整个项目工程含量最高的一章。

  3. 03 · 可信:签名与命名 — referrer 附件机制、Sigstore keyless/key 签名、域名所有权校验。理解“怎么把‘谁发的、没被改’做成可验证”。

  4. 04 · 搜索索引与边界 — 本地数据库二级索引(通配查询,区别于路由层的标签搜索)、系统边界与局限、巧妙之处、横向对比、全局代码地图。


4. 一分钟把它讲给别人

dir 是 agent 的分布式目录。你 push 一条 OASF 格式的 agent 描述,它对内容算 SHA-256 得到一个 CIDv1 指纹当 ID,把字节存进本地 OCI 镜像仓库(server/store/oci/oci.goPush),并立刻在本地搜索数据库建索引。然后 Publish 通过 libp2p DHT 的 Provide(CID) 向网络宣告“我提供这块内容”。别的节点收到宣告后,把记录拉回去、从内容里抽出技能/领域标签、缓存到本地——所以每个节点的搜索都是查本地缓存、不打网络,可扩展到上百 peer。可信由叠加的 referrer 附件提供:Sigstore 签名(client/sign.go)+ 域名所有权校验。它刻意只管目录,不管 agent 运行