AGNTCY's Agent Directory: content-addressed discovery, no price field
A directory that can tell you which agents can summarize a contract, prove who published them, and scan them for malicious code — but cannot tell you what any of them costs.
The Agent Directory Service (ADS) is the discovery layer of AGNTCY, the project Cisco open sourced in March 2025 and contributed to the Linux Foundation on 29 July 2025, with Cisco, Dell Technologies, Google Cloud, Oracle and Red Hat as formative members and more than 65 supporting companies.
It is the most engineering-dense of the agent registries. Where the MCP Registry is a REST API over a database and x402 Bazaar is an index built from settlement traffic, ADS is a peer-to-peer system: OCI artifacts addressed by content identifier, a Kademlia distributed hash table for routing, Sigstore for provenance, SPIFFE for federation. It is also the one whose implementation is furthest from its own specification.
We read the IETF draft end to end, audited the dir and oasf repositories at HEAD, and crawled the public staging registry on 6 August 2026. This is what we found.
The specification
The normative text lives in agntcy/dir-spec as a single file, draft-mp-agntcy-ads-02, an independent submission by Luca Muscariello and Ramiz Polic of Cisco. At the commit we audited (846e475, 6 July 2026) the draft is roughly 9,500 words. Its academic companion is arXiv 2509.18787, "The AGNTCY Agent Directory Service: Architecture and Implementation" (Muscariello, Pandey, Polic, submitted 23 September 2025).
The storage design is the strongest part. An agent record is an OASF document packaged as an OCI artifact, so the directory inherits container registry infrastructure it did not have to build: authentication, signing tooling, vulnerability scanners, CDN distribution. The manifest carries hard requirements. artifactType MUST be application/vnd.agntcy.dir.record.v1+json. config MUST reference the empty descriptor application/vnd.oci.empty.v1+json. Layer index 0 MUST use application/vnd.agntcy.oasf.types.{version}.Record+json and MUST carry its content inline as base64 in the data field. Skills, domains, locators and modules become their own layers, each with annotations under keys like agntcy.oasf.skill/name. An optional subject descriptor points at a previous record, which is how version history is expressed.
Consumers MUST reconstruct records by pulling the manifest, decoding layer 0, fetching each remaining blob, verifying its SHA-256 digest against the descriptor, and validating the merged object against the OASF schema version named in the annotations. Content addressing does the work that signatures do elsewhere: substitution is structurally detectable, independent of transport.
Discovery is a two-level DHT keyed on skills
ADS separates capability lookup from content location. The first mapping goes from skill to content identifiers; the second from content identifier to the libp2p peer IDs that hold it. Both live in a Kademlia DHT — the same go-libp2p-kad-dht implementation that underpins IPFS. A query for "natural language processing agents in finance" resolves each taxonomy term to a CID set, intersects the sets, then resolves the surviving CIDs to peers, and only then pulls the records over the OCI distribution protocol.
One design decision governs everything downstream: every query MUST include at least one skill criterion. Domain-only and module-only queries are explicitly unsupported, because skills are the DHT's primary key. Domain and module act as filters applied to a skill-derived result set, not as independent axes.
That makes the skill taxonomy the load-bearing wall of the whole system. And taxonomies drift.
The record has eleven fields
The schema lives in agntcy/oasf — 328 stars, released as v1.1.0 on 10 July 2026, with schema/version.json on main reading 1.2.0-dev. On main the taxonomy holds 18 skill categories with 392 leaf skills, 24 domain categories with 165 leaves, and 12 module definitions split into Core (language_model, prompt, agentskills, evaluation, observability) and Integration (mcp, a2a, agentspec, and a deprecated acp_manifest).
The Record object itself is small. It has exactly eleven attributes: name, version, schema_version, description, authors, annotations, created_at, skills, domains, locators, modules. That list is byte-identical between tag v1.0.0 and current main.
payments_integration skill, a finance_and_business/payments domain. No monetary field exists on the record, on the evaluation module, or anywhere else. The evaluation_data object carries overall_rating, overall_scores and referred_evaluations, and nothing more.
This matters because the draft promises the opposite. Its introduction says the directory lets you "evaluate performance characteristics including cost, latency, and resource requirements," and asks "what combination of skills and costs optimizes for task B?" Its three worked examples show records with evaluation_data.cost_per_million_tokens: 2.50, cost_per_image: 0.05, and cost_per_problem: 0.10, alongside performance_metrics, capabilities and registries blocks. None of those fields exist in the schema the implementation validates against. The examples also use pre-1.1.0 skill and domain names (natural_language_processing, images_computer_vision, analytical_skills, finance_and_banking) that were renamed when the taxonomy was reorganized.
The search API confirms the gap independently. The RecordQuery enum in dir supports queries by name, version, skill ID, skill name, locator, module, domain, author, creation date, schema version, annotation, description, plus VERIFIED, TRUSTED, SCAN_SEVERITY and SCAN_SAFE. There is no cost dimension to query, because there is no cost to store.
Trust: Sigstore, well-known JWKS, and scanners
Signing is keyless by default. The SignService — explicitly marked "a client-side service and is not available on the server" — signs records through Fulcio and logs to Rekor using an OIDC token, or with a cosign key file if you prefer to manage your own. Signatures, public keys and trust metadata are stored as OCI referrer objects attached to the record.
Naming is where ADS is quietly ahead of its peers. Records can carry a name like cisco.com/agent, and a backend scheduler verifies that the record's signing key is authorized by that domain by fetching https://<domain>/.well-known/jwks.json (RFC 7517) and matching key identifiers. Resolution accepts Docker-style references: name for all versions newest first, name:version, name@cid, or name:version@cid for a hash-verified lookup. This is the same trick the MCP Registry uses for DNS namespaces and Web Bot Auth uses for its signature directory — a domain you already control becomes the identity anchor, with no registration authority in the middle. We wrote about that pattern in Web Bot Auth.
The third trust layer is scanning, and it is live. Records in the public network carry agntcy.dir.security.v1.ScanReport referrers. One we pulled at random was produced on 22 July 2026 by SCANNER_TYPE_SKILL version 2.0.11, running behavioral, bytecode, pipeline, static and trigger analyzers, returning isSafe: true with a single informational finding: MANIFEST_MISSING_LICENSE. Agent records get treated as supply-chain artifacts, which is the correct instinct.
What the public network actually contains
AGNTCY runs a public staging network at ads.outshift.io: a gRPC API behind an OIDC gateway, a Dex issuer at idp.ads.outshift.io, a SPIRE bundle endpoint at spire.ads.outshift.io, and an OCI registry at store.ads.outshift.io. Joining it is not a signup. Per the dir-staging onboarding guide, you must run your own SPIRE server, federate its trust domain with theirs over the https_web bundle profile, and expose four public DNS names with Let's Encrypt certificates through an ingress controller. "Federation is required before you can discover or publish agents."
The OCI registry, however, is world-readable. On 6 August 2026 we crawled it.
# the whole public network is one repository
$ curl -s https://store.ads.outshift.io/v2/_catalog
{"repositories":["dir"]}
# tags are base32 CIDv1; paginated at 1,000 per page
$ while more; do curl -s ".../v2/dir/tags/list?n=1000&last=$last"; done
9814 tags
# random sample of 600 manifests, classified by annotation
ScanReport 345
record 116
Signature 74
PublicKey 65
Extrapolating the record share of that sample to the full tag list gives roughly 1,900 agent records in the public directory. Every sampled record declared org.agntcy.dir/oasf-version: 1.0.0.
We then read 60 of those records in full. Forty-five carried the core/language_model/agentskills module and fifteen carried integration/mcp. The authors were GitHub, Microsoft (spelled both Microsoft and microsoft), NVIDIA, Anthropic, Google, RedHatInsights and arm. In other words, the public directory is mostly imported agent skills and MCP server descriptors harvested from vendor repositories, not agents that registered themselves.
Two numbers from that read are worth sitting with. Only 15 of 60 records carried a locator — three quarters of the sample describe a capability with no address at which to invoke it. And the single most common skill was retrieval_augmented_generation/retrieval_of_information, present on 36 of 60 records. That leaf no longer exists in current OASF: v1.0.0 had 15 top-level skill categories including retrieval_augmented_generation; main has 18, with RAG demoted to ai_ml_engineering/retrieval_augmented_generation and retrieval_of_information deleted outright. The most-used index key in the live network is not in the current taxonomy. For a DHT whose primary key is the skill name and whose queries are required to include one, that is not a cosmetic problem.
The spec and the running network disagree
Every non-referrer manifest we pulled looked like this:
{
"artifactType": "application/vnd.oci.image.manifest.v1+json",
"layers": [{ "mediaType": "application/json", "size": 7030 }],
"annotations": {
"org.agntcy.dir/type": "record",
"org.agntcy.dir/name": "github-actions-efficiency",
"org.agntcy.dir/oasf-version": "1.0.0"
}
}
Compare that with the draft: artifactType MUST be application/vnd.agntcy.dir.record.v1+json, layer 0 MUST be a typed OASF media type with inline base64 data, and skills, domains and locators MUST be separate annotated layers. The deployed network does none of it. It stores one opaque JSON blob and puts the searchable metadata in org.agntcy.dir/* annotations instead. Some of the gap is version skew — dir-staging pins server v1.3.0 while the repository is at v1.6.2 (29 July 2026) — but the artifact specification is the part of the draft with the most MUST clauses, and nothing in production honors it.
There is a second, quieter gap. The July 2026 addition to the draft is an interoperability section with AI Catalog, a thin discovery envelope maintained by the Agent Card Working Group under the Linux Foundation and still marked a draft document. ADS projects records into catalog entries keyed on modules: integration/mcp becomes application/mcp-server-card+json, integration/a2a becomes application/a2a-agent-card+json, agentskills becomes application/agentskill+md, and a record with two or more known modules becomes a nested catalog. Records with no known module are not projectable at all.
But the shapes do not line up. The AI Catalog entry requires identifier, type, and exactly one of url or data, with displayName optional and identifiers recommended in a urn:air form. The ADS draft and the dir protobuf both require identifier, display_name and media_type — a field the target specification calls type — and mint identifiers as urn:ai:org.agntcy:cid:<cid>, verified in the repository's own catalog tests. An interoperability layer whose required field names differ from the specification it interoperates with will interoperate with exactly one implementation.
And the discovery surface that generic clients are supposed to use is closed. GET /.well-known/ai-catalog.json on the public host returns 401 {"error": "Unauthenticated", "message": "missing credentials"}, as does /v1/agents. A well-known URI behind authentication is a contradiction in terms.
There is no global network yet
One line in server/routing/config/config.go at HEAD (a37aba3, 5 August 2026) explains more than any architecture diagram:
var DefaultBootstrapPeers = []string{
// TODO: once we deploy our bootstrap nodes, we should update this
}
Eighteen months after the repository was created and six minor releases in, a fresh node joins no network by default. Autosync is off by default under an explicitly deny-by-default policy, and the relay service is off unless you are publicly reachable. The Kademlia machinery is real and tested, but the "Internet of Agents" is currently a set of private overlays plus one Cisco-operated staging instance you join by federating a SPIFFE trust domain.
That is a defensible enterprise choice — it is essentially the model we described in the enterprise-managed authorization piece, where the corporate identity provider decides who gets in. It is simply not the permissionless discovery the framing implies.
What it means for LLM4Agents
ADS answers a question our stack does not: given a capability, which agents claim to have it, who vouches for them, and has anyone scanned them. Content addressing plus Sigstore plus domain-verified names is a better provenance story than anything in the MCP Registry, and the scan-report referrer is a genuinely good idea we should copy in spirit.
What it does not answer is the question that makes an agent usable by another agent without a human in the loop: what does one call cost, and how do I pay for it. The word x402 appears zero times in the draft. The flagship reference application, coffeeAgntcy, ships a payment MCP server whose create_payment tool returns a hardcoded "payment_id": "stub_payment_id" for $100.00 USD, with a comment noting that a real system would enforce access control. There are no stablecoins anywhere in the repository.
That is the same shape we found in the Universal Commerce Protocol: a well-built negotiation and discovery layer with the settlement rail left as someone else's problem. And it is the same conclusion we reached auditing ERC-8004 — a directory entry is a claim, and claims without economic anchoring drift toward noise. Three quarters of the records in the public network having no locator is that drift, measured.
Concretely: ADS is a good place to be listed and a bad place to be billed. It slots above our gateway as an enterprise-side catalog, not as a replacement for the settlement path. The record is deliberately thin, the annotation map is free-form, and the module system is the designed extension point — so the missing price is an opening, not a wall.
Staying on the frontier
In order, from cheapest to most ambitious.
Publish a signed record. Build an OASF record for the LLM4Agents MCP server with an integration/mcp module and a real locator, sign it keyless through Fulcio and Rekor, and claim the name llm4agents.com/gateway by serving /.well-known/jwks.json. Domain-verified naming costs one static file and puts us in the small minority of records that are both addressable and attributable.
Carry the price in annotations. Until OASF has a monetary field, publish pricing under a reverse-DNS annotation namespace (com.llm4agents.x402.accepts) that mirrors the x402 accepts object verbatim, so a client that already speaks x402 can pay directly from the directory entry without a discovery round trip.
Serve our own catalog. Publish /.well-known/ai-catalog.json on our domain, unauthenticated, listing the gateway and each paid MCP tool. It is a small document, it is the interoperability envelope both the Agent Card WG and ADS have converged on, and shipping it open is a differentiator against a public network that returns 401 on the same path.
Propose the payment module upstream. Modules are how OASF extends. An integration/x402 module — payment requirements, accepted networks, price scheme — is the right contribution, and the same play we flagged for UCP's open governance. Discovery layers that cannot express price will keep pushing the question down to the settlement layer anyway; better to define it once.
Pin the taxonomy. Whatever we publish, record which OASF version each skill identifier came from and re-publish on rename. The retrieval_of_information deletion shows what happens otherwise: an index key that no longer exists, in a system where the index key is mandatory.
Then measure. Run a private DIR node against our own bootstrap set, load our catalog plus the public staging records, and compare capability-query latency and recall against a straight MCP Registry crawl. If the DHT does not beat a hosted index at our scale, we have learned something cheap; if it does, we already have the record format and the signing pipeline in place.
Discovery tells you who. Settlement tells you whether.
An OpenAI-compatible gateway where agents pay per call in stablecoins — no directory required.
Register your agent