DUADPDUADP

Protocol Documentation

Complete reference for the Decentralized Universal AI Discovery Protocol — endpoints, SDK usage, federation, and architecture.

Overview

DUADP is a federated discovery protocol for AI agents. It enables any agent, skill, or tool to be discovered across the open web without depending on a central registry.

The protocol is built on three layers:

DNS + WebFinger

Nodes advertise via DNS TXT records. Clients resolve agents using WebFinger (RFC 7033). Zero infrastructure beyond a domain.

Gossip Federation

Peer nodes exchange registrations via gossip protocol. Publish once, propagate everywhere. Eventual consistency across the mesh.

DID Identity

Every node has a did:web identity. Agent manifests carry verifiable credentials. Trust is cryptographic.

Quick Start

1. Install the package

terminal
npm install @bluefly/duadp

2. Check the reference node

terminal
curl https://discover.duadp.org/.well-known/duadp | jq .

3. Discover agents

terminal
curl https://discover.duadp.org/api/v1/agents | jq .agents[].name

4. Search across everything

terminal
curl "https://discover.duadp.org/api/v1/search?q=code+review" | jq .

5. Publish an agent

terminal
curl -X POST https://discover.duadp.org/api/v1/publish \
  -H "Content-Type: application/json" \
  -d @my-agent-manifest.json

Discovery API

Core endpoints for discovering agents, skills, and tools on a DUADP node. All responses are JSON.

GET/.well-known/duadp

Node capabilities, version, and supported features

Response
{
  "protocol": "DUADP",
  "version": "0.1.0",
  "node": "discover.duadp.org",
  "mcp_tools": 17,
  "federation": "enabled",
  "identity": {
    "did": "did:web:discover.duadp.org",
    "type": "reference-node"
  }
}
GET/api/v1/agents

List all registered agents with pagination

Response
{
  "agents": [
    {
      "id": "agt_doc123",
      "name": "document-analyzer",
      "version": "2.1.0",
      "description": "Advanced document analysis",
      "capabilities": ["text-extraction", "entity-recognition"],
      "provider": "anthropic"
    }
  ],
  "total": 42,
  "limit": 50,
  "offset": 0
}
GET/api/v1/skills

Discover available skills across agents

Response
{
  "skills": [
    {
      "name": "code-review",
      "description": "Automated code review with security analysis",
      "agents": ["agt_review01", "agt_sec02"]
    }
  ],
  "total": 18
}
GET/api/v1/tools

List published MCP-compatible tools

Response
{
  "tools": [
    {
      "name": "file-search",
      "protocol": "MCP",
      "description": "Full-text file search with regex support"
    }
  ],
  "total": 31
}

Full-text search across all registered agents, skills, and tools. Supports capability-based filtering, taxonomy paths, and faceted results.

GET/api/v1/search

Query Parameters

ParamTypeDescription
qstringSearch query (natural language)
capabilitystringFilter by capability (repeatable)
typestringagent, skill, or tool
sortstringrelevance, created_at, name
limitintegerResults per page (default 50, max 100)
offsetintegerPagination offset
Example: Multi-capability search
curl "https://discover.duadp.org/api/v1/search?q=document+analysis&capability=text-extraction&capability=entity-recognition"
Response with facets
{
  "results": [
    {
      "id": "agt_doc123",
      "name": "document-analyzer",
      "relevance_score": 0.95,
      "capabilities": ["text-extraction", "entity-recognition"],
      "description": "Advanced document analysis with OCR"
    }
  ],
  "total": 15,
  "facets": {
    "capabilities": { "text-extraction": 15, "entity-recognition": 12 },
    "types": { "agent": 10, "skill": 3, "tool": 2 }
  }
}

Registry

Publish agents, skills, and tools to the network. Validate OSSA manifests before publishing.

POST/api/v1/publish
Publish an agent
curl -X POST https://discover.duadp.org/api/v1/publish \
  -H "Content-Type: application/json" \
  -d '{
    "ossa_version": "0.4.6",
    "name": "my-agent",
    "version": "1.0.0",
    "description": "My custom agent",
    "capabilities": ["text-generation"],
    "llm": { "provider": "anthropic", "model": "claude-sonnet-4-20250514" }
  }'
POST/api/v1/validate
Validate before publishing
curl -X POST https://discover.duadp.org/api/v1/validate \
  -H "Content-Type: application/json" \
  -d @my-agent-manifest.json

# Response:
# { "valid": true, "schema_version": "0.4.6", "errors": [], "warnings": [] }

Federation

DUADP nodes form a federated mesh. Nodes discover each other via DNS, register as peers, and synchronize registrations via a gossip protocol.

How it works

  1. A node advertises itself via a DNS TXT record: _duadp.example.com TXT "v=DUADP1 url=https://example.com/.well-known/duadp"
  2. Other nodes discover it via DNS lookup or manual registration
  3. Peer nodes exchange registrations via /api/v1/federation/gossip
  4. Agents published on one node propagate across the mesh
GET /api/v1/federation/list — Known peers
curl https://discover.duadp.org/api/v1/federation/list

# {
#   "peers": [
#     { "url": "https://registry.example.com", "did": "did:web:registry.example.com", "status": "active" },
#     { "url": "https://agents.corp.io", "did": "did:web:agents.corp.io", "status": "active" }
#   ],
#   "total": 2
# }
POST /api/v1/federation/register — Join the mesh
curl -X POST https://discover.duadp.org/api/v1/federation/register \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://my-node.example.com",
    "did": "did:web:my-node.example.com",
    "capabilities": ["agents", "skills", "tools"]
  }'
POST /api/v1/federation/gossip — Sync registrations
curl -X POST https://discover.duadp.org/api/v1/federation/gossip \
  -H "Content-Type: application/json" \
  -d '{
    "source": "did:web:my-node.example.com",
    "timestamp": "2026-03-06T12:00:00Z",
    "entries": [
      { "type": "agent", "id": "agt_new01", "action": "register", "manifest": { ... } }
    ]
  }'
GET /api/v1/federation/peers — Active connections
curl https://discover.duadp.org/api/v1/federation/peers

Identity & Governance

GET /api/v1/identity/node — DID-based node identity
curl https://discover.duadp.org/api/v1/identity/node

# {
#   "did": "did:web:discover.duadp.org",
#   "type": "reference-node",
#   "publicKey": "...",
#   "created": "2026-01-15T00:00:00Z",
#   "endpoints": {
#     "discovery": "https://discover.duadp.org/.well-known/duadp",
#     "federation": "https://discover.duadp.org/api/v1/federation/register"
#   }
# }
GET /api/v1/governance — Node governance policies
curl https://discover.duadp.org/api/v1/governance

# {
#   "policies": {
#     "registration": "open",
#     "validation": "ossa-schema-required",
#     "federation": "auto-accept",
#     "retention_days": 365,
#     "rate_limits": { "publish": "100/hour", "search": "1000/hour" }
#   }
# }

Operations

GET /api/v1/health
curl https://discover.duadp.org/api/v1/health

# { "status": "healthy", "uptime": "47d 12h", "version": "0.1.0" }
GET /api/v1/metrics
curl https://discover.duadp.org/api/v1/metrics

# {
#   "agents_registered": 42,
#   "skills_registered": 18,
#   "tools_registered": 31,
#   "peers_connected": 2,
#   "searches_24h": 1247,
#   "publishes_24h": 8
# }

SDK Usage

TypeScript

Install
npm install @bluefly/duadp
TypeScript — discover, search, publish
import { UadpClient, resolveGaid } from '@bluefly/duadp';

const client = new UadpClient('https://discover.duadp.org');

// Discover the node
const manifest = await client.discover();
console.log(manifest.node_name, manifest.protocol_version);

// List agents
const agents = await client.listAgents({ limit: 10 });
console.log(`Found ${agents.meta.total} agents`, agents.data);

// List skills and tools
const skills = await client.listSkills();
const tools = await client.listTools();

// Search across everything
const results = await client.search({
  q: 'document analysis',
  kind: 'agent',
  trust_tier: 'verified-signature',
  facets: true,
});

// Publish an agent (requires token)
const authed = new UadpClient('https://discover.duadp.org', {
  token: process.env.DUADP_TOKEN,
});
await authed.publishAgent({
  name: 'my-agent',
  version: '1.0.0',
  description: 'Custom document analyzer',
  capabilities: ['text-extraction'],
});

// Resolve a GAID URI directly
const { client: resolved, kind, name } = resolveGaid(
  'duadp://skills.sh/skills/web-search'
);
const skill = await resolved.getSkill(name);

// Federation
const federation = await client.getFederation();
await authed.registerAsPeer({
  url: 'https://my-node.example.com',
  did: 'did:web:my-node.example.com',
});

// Advanced: reputation, governance, health
const rep = await client.getAgentReputation('duadp://acme.com/agents/scanner');
const gov = await client.getGovernance();
const health = await client.getHealth();

Python

Install
pip install duadp
Python — discover, search, publish
from duadp import DuadpClient

client = DuadpClient("https://discover.duadp.org")

# Discover the node
manifest = client.discover()
print(f"{manifest['protocol']} v{manifest['version']}")

# List agents
agents = client.list_agents(limit=10)
print(f"Found {agents['total']} agents")
for agent in agents["agents"]:
    print(f"  {agent['name']} — {agent['description']}")

# List skills and tools
skills = client.list_skills()
tools = client.list_tools()

# Search across everything
results = client.search(
    q="document analysis",
    capability="text-extraction",
    kind="agent",
)
for r in results["results"]:
    print(f"  {r['name']} (score: {r['relevance_score']})")

# Publish an agent
import os
authed = DuadpClient("https://discover.duadp.org", token=os.environ["DUADP_TOKEN"])
authed.publish_agent({
    "ossa_version": "0.4.6",
    "name": "my-agent",
    "version": "1.0.0",
    "description": "Custom document analyzer",
    "capabilities": ["text-extraction"],
})

# Federation
peers = client.federation_list()
authed.federation_register({
    "url": "https://my-node.example.com",
    "did": "did:web:my-node.example.com",
})

# Governance & health
governance = client.governance()
health = client.health()

Advanced Patterns

Multi-Capability Filtering

Chain capability params to find agents matching multiple requirements:

curl "https://discover.duadp.org/api/v1/search?capability=text-extraction&capability=entity-recognition&capability=ocr"

Federated Search

Federated search is the core differentiator of DUADP. When a client sets federated=true, the query fans out to every registered peer node in the mesh. Results stream back, are deduplicated by content hash, and merged into a single ranked response — all transparent to the caller.

How It Works

  1. Client sends query with federated=true
  2. Node fans out the query to all healthy peers in parallel
  3. Each peer searches its local registry and returns results
  4. Originating node deduplicates by content_hash or GAID
  5. Results are merged, ranked by relevance, and tagged with source node DID
  6. Circuit breaker skips peers that are slow or unreachable

Query Parameters

federatedboolean — enable mesh-wide search (default: false)
max_hopsinteger — propagation depth limit (default: node config, typically 2)
timeout_msinteger — per-peer timeout in milliseconds (default: 5000)
include_sourceboolean — include source node DID on each result (default: true)
Federated search with source attribution
curl "https://discover.duadp.org/api/v1/search?q=contract+analysis&federated=true" | jq .

{
  "data": [
    {
      "kind": "Agent",
      "metadata": { "name": "contract-analyzer", "version": "2.1.0" },
      "identity": { "gaid": "agent://agents.enterprise.io/agents/contract-analyzer" },
      "_source": { "node_id": "did:web:agents.enterprise.io", "node_name": "Enterprise AI" }
    },
    {
      "kind": "Skill",
      "metadata": { "name": "legal-review", "version": "1.0.0" },
      "identity": { "gaid": "agent://community-agents.dev/skills/legal-review" },
      "_source": { "node_id": "did:web:community-agents.dev", "node_name": "Community Agents" }
    }
  ],
  "meta": {
    "total": 7,
    "federated": true,
    "sources": [
      { "node_name": "discover.duadp.org", "count": 3 },
      { "node_name": "Enterprise AI", "count": 2 },
      { "node_name": "Community Agents", "count": 2 }
    ]
  }
}
TypeScript SDK — federated search
import { DuadpClient, deduplicateResources } from '@bluefly/duadp';

const client = new DuadpClient('https://discover.duadp.org');

// Federated search across the entire mesh
const results = await client.search({
  q: 'contract analysis',
  federated: true,
  trust_tier: 'verified-signature',
  facets: true,
});

console.log(`${results.meta.total} results from ${results.meta.sources?.length} nodes`);

// Results are already deduplicated, but you can also dedup manually:
const unique = deduplicateResources(results.data);
Python SDK — federated search
from duadp import DuadpClient

async with DuadpClient("https://discover.duadp.org") as client:
    results = await client.search(
        q="contract analysis",
        federated=True,
        trust_tier="verified-signature",
    )
    for r in results.data:
        print(f"{r.kind}: {r.metadata.name} (from {r._source.node_name})")

Circuit Breaker Behavior

The SDK includes a built-in circuit breaker. If a peer fails 3 consecutive requests, it enters degraded state and is excluded from federated queries for 24 hours. After the cooldown, the next query probes it again. If it responds, it returns to healthy state. This prevents one slow node from degrading the entire mesh.

Running Your Own Node

DUADP is designed so any organization can run its own discovery node. You control your agent registry, your data stays on your infrastructure, and you choose which peers to federate with. The reference implementation runs on Node.js with SQLite — zero external dependencies.

1DNS Configuration

Add a DNS TXT record so other nodes can discover yours automatically. The record tells the federation mesh where to find your .well-known/duadp.json manifest.

DNS TXT Record
# Add this to your DNS zone
_duadp.yourdomain.com  IN  TXT  "v=DUADP1 url=https://yourdomain.com"

# Verify it propagated
dig TXT _duadp.yourdomain.com +short
# → "v=DUADP1 url=https://yourdomain.com"

2Deploy the Server

The reference node is a lightweight Express server with SQLite storage. Deploy via npm or Docker.

Option A: npm
npm install @bluefly/duadp

# Start the server
DUADP_NODE_NAME="My Registry" \
DUADP_PORT=3000 \
DUADP_DID="did:web:yourdomain.com" \
  npx duadp-server

# Server starts at http://localhost:3000
# Manifest: /.well-known/duadp.json
# API: /api/v1/agents, /skills, /tools
Option B: Docker
docker run -d \
  --name duadp-node \
  -p 3000:3000 \
  -e DUADP_NODE_NAME="My Registry" \
  -e DUADP_DID="did:web:yourdomain.com" \
  -v duadp-data:/data \
  ghcr.io/blueflyio/duadp-node:latest

# Data persists in the volume
# SQLite DB at /data/duadp.db

3Configure Your Node

Customize your node via environment variables or a config file.

Environment variables
DUADP_NODE_NAME="My Agent Registry"     # Human-readable name
DUADP_DID="did:web:yourdomain.com"       # W3C DID for identity
DUADP_PORT=3000                          # Server port
DUADP_DB_PATH="./data/duadp.db"          # SQLite database location
DUADP_FEDERATION_GOSSIP=true             # Enable gossip protocol
DUADP_FEDERATION_MAX_HOPS=2              # Gossip propagation depth
DUADP_CEDAR_CATALOG_PATH="./policies/"   # Cedar policy directory
DUADP_LOG_LEVEL="info"                   # Logging verbosity

4Join the Federation

Register your node with the reference node (or any peer) to join the mesh. Once registered, agents you publish will propagate to other nodes via gossip.

Register with the reference node
# Register your node
curl -X POST https://discover.duadp.org/api/v1/federation/register \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourdomain.com",
    "name": "My Agent Registry",
    "node_id": "did:web:yourdomain.com",
    "capabilities": ["agents", "skills", "tools", "federation"]
  }'

# Response:
# {
#   "success": true,
#   "peer": {
#     "url": "https://yourdomain.com",
#     "name": "My Agent Registry",
#     "status": "healthy",
#     "skill_count": 0,
#     "agent_count": 0
#   }
# }

# Verify federation
curl https://discover.duadp.org/api/v1/federation | jq '.peers[] | .name'

5Publish Agents

Now publish agents to your node. They'll automatically propagate across the mesh.

Publish an agent to your node
curl -X POST https://yourdomain.com/api/v1/publish \
  -H "Content-Type: application/json" \
  -d '{
    "apiVersion": "ossa/v0.5",
    "kind": "Agent",
    "metadata": {
      "name": "my-custom-agent",
      "version": "1.0.0",
      "description": "My custom AI agent",
      "tags": ["custom", "enterprise"]
    },
    "identity": {
      "gaid": "agent://yourdomain.com/agents/my-custom-agent",
      "did": "did:web:yourdomain.com:agents:my-custom-agent"
    },
    "spec": {
      "agent_type": "worker",
      "llm": { "provider": "anthropic", "model": "claude-sonnet-4-20250514" }
    }
  }'

# Agent is now discoverable on your node AND across the federation

Architecture

Each DUADP node is self-contained: Express HTTP server, SQLite database, optional Cedar policy engine. Nodes have no shared state — they synchronize via gossip. The reference implementation is ~2,000 lines of TypeScript with zero runtime dependencies beyond Express and better-sqlite3. You can also implement the protocol in any language — the spec is the REST API surface defined in the OpenAPI spec.

Resources