SocioLogic
Back to Blog
Technology

Designing an Agent Registry That Doesn't Suck

Lessons from npm, Docker Hub, and twenty years of package registry mistakes

I've been building SocioLogic's verified agent registry for about six months now, and I want to share what we've learned. Some of it is technical. Some of it is about the decisions that seem small but turn out to determine whether anyone actually uses the thing.

Fair warning: this is a technical post. I'm going to talk about schema design, discovery mechanisms, and the tradeoffs we're navigating. If you want the "why agent registries matter" pitch, Marcus wrote a good piece on verification. This post is about the how.

What We're Actually Building

An agent registry is, at its simplest, a directory. Agent services register themselves. Other agents (or humans) search for services matching their needs. The registry provides enough information to decide whether to connect and how.

If that sounds like a package registry (npm, PyPI, Docker Hub), you're right. The problems are similar. The mistakes are similar too, and we've tried to learn from them.

Schema Design: The Hard Part

The first question is: what information do you need about an agent service to make it useful?

We went through probably a dozen schema iterations. The early ones were too simple (just a name, description, and endpoint). The middle ones were too complex (we had a 47-field schema at one point that nobody would have filled out). Here's where we landed.

The Agent Card

Every registered agent publishes an "agent card" as a JSON-LD document at /.well-known/agent.json. JSON-LD because it's machine-readable, extensible, and compatible with existing web standards. We didn't want to invent a new format when a perfectly good one already existed.

The core fields:

{
  "@context": "https://schema.sociologic.dev/agent/v1",
  "@type": "AgentService",
  "name": "SocioLogic Persona Research",
  "description": "Query synthetic personas...",
  "provider": {
    "name": "SocioLogic",
    "url": "https://sociologic.dev",
    "verified": true
  },
  "capabilities": [...],
  "pricing": {...},
  "transport": {
    "protocol": "mcp",
    "endpoint": "https://relay.sociologic.dev"
  }
}

Let me walk through the design decisions.

Capabilities: The Vocabulary Problem

This was the hardest part. How do you describe what an agent can do in a way that's both human-readable and machine-queryable?

We tried free-text descriptions first. Useless for machine discovery. Then we tried a fixed taxonomy. Too rigid. You can't anticipate every category of agent capability, and a taxonomy that's wrong is worse than no taxonomy at all because it forces services into ill-fitting boxes.

What we settled on is a hybrid: structured capability objects with both a category tag from a controlled vocabulary and a free-text description. The categories enable broad search ("find me agents that do data analysis"). The descriptions enable nuance ("specifically, this agent analyzes customer churn patterns in SaaS businesses").

"capabilities": [
  {
    "category": "research/persona-query",
    "description": "Interview synthetic personas...",
    "inputSchema": { ... },
    "outputSchema": { ... }
  }
]

The input and output schemas are optional but strongly recommended. They let a calling agent know exactly what to send and what to expect back, without trial and error.

We maintain the controlled vocabulary as a living document. New categories get added when enough agents need them. It's a governance problem as much as a technical one, and honestly, we don't have it fully figured out yet.

Pricing: Per-Request Economics

Most agent services charge per request via x402 (HTTP 402 + USDC on Base). The pricing section of the agent card describes what a request costs:

"pricing": {
  "model": "per-request",
  "currency": "USDC",
  "network": "base",
  "costs": [
    {
      "capability": "research/persona-query",
      "amount": "0.02",
      "unit": "per query"
    }
  ]
}

This lets a calling agent calculate costs before making a request. Important when you're building autonomous workflows where agents need to make spending decisions without human approval for each call.

Verification Status

The verified field is boolean, but behind it sits a multi-step verification process. We check: does the service respond? Does it do what it claims? Does it handle edge cases gracefully? Does it try to exfiltrate data or make unexpected network calls?

We run these checks periodically, not just at registration. A service that was verified last month might have pushed a bad update. We're not fully continuous yet (we check weekly), but we're working toward real-time monitoring.

Discovery: Why .well-known Matters

We chose the /.well-known/agent.json path for a specific reason. It follows the RFC 8615 convention for well-known URIs, the same pattern used by /.well-known/openid-configuration, /.well-known/security.txt, and similar standards.

This means discovery can happen in two ways:

  1. Registry search: Query our registry API for agents matching specific capabilities. This is how most discovery happens today.
  2. Direct resolution: If you know an agent's domain, fetch its card directly from the .well-known path. No registry needed. This is decentralized discovery, and it matters because it means our registry isn't a single point of failure.

The DNS analogy is intentional. DNS doesn't own domain names. It maps them. Similarly, our registry doesn't own agent identities. It indexes and verifies them. The source of truth is the agent card at the agent's own domain.

Lessons from Package Registries

We studied what went right and wrong with npm, Docker Hub, and PyPI. Some lessons:

From npm: namespace squatting is real

npm had (still has) a massive problem with people registering package names they don't intend to use, or registering names similar to popular packages for malicious purposes (typosquatting). We require domain verification as part of registration. You can only register an agent card for a domain you control. This doesn't eliminate all impersonation, but it raises the bar substantially.

From Docker Hub: trust signals need to be visible

Docker learned the hard way that users will pull any image that matches their search, regardless of provenance. Their "Official Images" and "Verified Publisher" badges helped, but they came late. We built verification status into the agent card schema from day one. An unverified agent works fine, but every client that reads the card knows it's unverified.

From PyPI: dependency confusion attacks

When an agent calls another agent that calls another agent, you have a dependency chain. The same supply chain attacks that hit package managers apply here. We're still working on this. Our current approach is to log the full call chain for verified agents, so if something goes wrong you can trace it. But preventing malicious transitive dependencies in agent networks is an unsolved problem. I'm not going to pretend otherwise.

What We Got Wrong (So Far)

Some honest mistakes from our first iterations:

Over-specifying the schema. Our v0.2 schema had fields for "response time SLA," "uptime guarantee," and "data retention policy." Almost nobody filled them out. We moved them to an optional extensions section. Core schema should be what people will actually provide.

Under-investing in search. A registry is only useful if you can find things in it. Our initial search was keyword-based and terrible. We've since added semantic search (embed the query, compare against capability embeddings) and it's dramatically better. Should have done this from the start.

Assuming humans would do the registering. We built a nice web form for registration. Turns out, most registrations come from CI/CD pipelines. The API needed to be the primary interface, not the web UI. Lesson: in agent infrastructure, agents are the users.

Open Questions

We still don't have good answers for:

  • Versioning: When an agent updates its capabilities, what happens to workflows that depend on the old version? We support version fields but don't enforce compatibility. This will bite us eventually.
  • Reputation: Beyond binary verified/unverified, should agents have reputation scores? Based on what? Self-reported reliability claims are worthless. We're considering aggregate metrics from actual usage, but privacy implications are real.
  • Federation: Should there be one registry or many? We lean toward "many, with interop," but haven't built the federation protocol yet.

If you're building in this space or thinking about agent discovery, I'd genuinely like to hear your perspective. The problems are hard enough that no single team is going to solve them all. Find me on LinkedIn or open an issue on our schema repo.

Agent Registry
Schema Design
JSON-LD
Agent Discovery
Infrastructure

About Dr. Sarah Chen

Where Data Meets Human Behavior at SocioLogic

Behavioral economist turned AI researcher. Applying rigorous methodology to synthetic user research.

More from Dr. Sarah Chen

Technology

MCP Is the TCP/IP of Agents. Here's What's Missing.

Model Context Protocol nails tool invocation and streaming. But discovery, payments, verification, and trust are completely absent from the spec. Someone has to build those layers.

18 min read
Technology

Running AI Agents on the Edge: Why Latency Matters

A 200ms API call is fine for a human. But when Agent A calls Agent B calls Agent C, that 200ms becomes 600ms, and your user is staring at a spinner wondering what went wrong.

12 min read
Technology

Personas at Scale: What Happens When You Create 10,000 Synthetic Buyers

We created 10,000 synthetic buyer personas in a single cohort to find out where our system breaks. It broke in ways we didn't expect.

14 min read

Try Synthetic User Research Today

Get started with a $1 pilot credit. No credit card required.

Designing an Agent Registry: Technical Deep Dive | SocioLogic | SocioLogic