A Python library for building NANDA-compatible AI agent registries.
NANDA (Network of AI Agents in Decentralized Architecture) is the protocol for federated AI agent discovery and communication. This library provides the primitives needed to make your agent registry interoperable with the NANDA ecosystem.
- NANDA AgentFacts Models - Pydantic models implementing the projnanda/agentfacts-format specification
- FastAPI Router - Drop-in endpoints for
/nanda/index,/nanda/resolve,/nanda/deltas - Delta Store - Change tracking for registry synchronization
- Converter Interface - Abstract pattern for integrating with your existing registry
pip install nanda-bridgeOr install from source:
git clone https://github.com/lyraspace/nanda-bridge
cd nanda-bridge
pip install -e .from fastapi import FastAPI
from nanda_bridge import NandaBridge, SimpleAgent
# Create the bridge
bridge = NandaBridge(
registry_id="my-registry",
provider_name="My Company",
provider_url="https://example.com",
base_url="https://registry.example.com"
)
# Register agents
bridge.register_agent(SimpleAgent(
id="my-agent",
name="My Agent",
description="An agent that does things",
namespace="production",
labels=["chat", "tool-use"],
skills=[
{"id": "summarize", "description": "Summarizes text"},
{"id": "translate", "description": "Translates between languages"}
]
))
# Mount the router
app = FastAPI()
app.include_router(bridge.router)This gives you:
GET /nanda/index- List all public agentsGET /nanda/resolve?agent=my-agent- Resolve a single agentGET /nanda/deltas?since=0- Get changes for syncGET /nanda/.well-known/nanda.json- Registry discovery
For existing registries with their own data models:
from nanda_bridge import (
AbstractAgentConverter,
NandaAgentFacts,
NandaProvider,
NandaEndpoints,
NandaCapabilities,
NandaSkill,
DeltaStore,
create_nanda_router,
)
from typing import Iterator
class MyRegistryConverter(AbstractAgentConverter):
def __init__(self, db_connection):
super().__init__(
registry_id="my-registry",
provider_name="My Company",
provider_url="https://example.com"
)
self.db = db_connection
def to_nanda(self, agent) -> NandaAgentFacts:
return NandaAgentFacts(
id=f"did:web:example.com:agents:{agent.id}",
handle=self.build_handle(agent.namespace, agent.id),
agent_name=agent.display_name,
label=agent.category,
description=agent.description,
version=agent.version,
provider=self.build_provider(),
endpoints=NandaEndpoints(static=[agent.endpoint_url]),
capabilities=NandaCapabilities(modalities=agent.capabilities),
skills=[NandaSkill(id=s.id, description=s.desc) for s in agent.skills],
metadata={
"x_my_registry": {
"internal_id": agent.internal_id,
"created_at": agent.created_at.isoformat(),
}
}
)
def list_agents(self, limit: int, offset: int) -> Iterator:
return self.db.query_agents(limit=limit, offset=offset)
def get_agent(self, agent_id: str):
return self.db.get_agent(agent_id)
def is_public(self, agent) -> bool:
return agent.visibility == "public"
# Create router with custom converter
converter = MyRegistryConverter(db_connection)
delta_store = DeltaStore()
router = create_nanda_router(
converter=converter,
delta_store=delta_store,
registry_id="my-registry",
base_url="https://registry.example.com",
provider_name="My Company",
provider_url="https://example.com"
)
app = FastAPI()
app.include_router(router)The core data structure for agent metadata:
from nanda_bridge import NandaAgentFacts
facts = NandaAgentFacts(
id="did:web:example.com:agents:my-agent",
handle="@my-registry:production/my-agent",
agent_name="My Agent",
label="assistant",
description="An AI assistant",
version="1.0.0",
provider=NandaProvider(
name="My Company",
url="https://example.com"
),
endpoints=NandaEndpoints(
static=["https://api.example.com/agents/my-agent"]
),
capabilities=NandaCapabilities(
modalities=["text", "tool-use"],
authentication=NandaAuthentication(methods=["did-auth"])
),
skills=[
NandaSkill(
id="urn:my-registry:cap:summarize:v1",
description="Summarizes long documents",
inputModes=["text"],
outputModes=["text"]
)
],
metadata={
"x_my_registry": {
"custom_field": "custom_value"
}
}
)NANDA handles follow the format @registry:namespace/agent-id:
handle = NandaAgentFacts.create_handle(
registry="my-registry",
namespace="production",
agent_id="my-agent"
)
# Returns: "@my-registry:production/my-agent"Track changes for registry synchronization:
from nanda_bridge import DeltaStore, NandaAgentFacts
store = DeltaStore()
# Record an agent creation/update
delta = store.add("upsert", agent_facts)
print(f"Recorded delta with seq={delta.seq}")
# Get all changes since seq 0
deltas = store.since(0)
# Get next sequence number for polling
next_seq = store.next_seqFor production, extend PersistentDeltaStore to persist to a database:
from nanda_bridge import PersistentDeltaStore
class PostgresDeltaStore(PersistentDeltaStore):
def __init__(self, dsn: str):
super().__init__()
self.conn = psycopg2.connect(dsn)
def _persist(self, delta):
# INSERT INTO nanda_deltas ...
pass
def _load_since(self, seq):
# SELECT * FROM nanda_deltas WHERE seq > ...
passAdvertise MCP tools that agents can use:
from nanda_bridge import NandaBridge, NandaTool
bridge = NandaBridge(
registry_id="my-registry",
provider_name="My Company",
provider_url="https://example.com",
tools=[
NandaTool(
tool_id="search",
description="Search the web",
endpoint="https://api.example.com/mcp/search",
params=["query", "limit"]
),
NandaTool(
tool_id="calculate",
description="Perform calculations",
endpoint="https://api.example.com/mcp/calculate",
params=["expression"]
)
]
)The library automatically serves /.well-known/nanda.json for registry discovery:
{
"registry_id": "my-registry",
"registry_did": "did:web:registry.example.com",
"namespaces": ["did:web:example.com:*"],
"index_url": "https://registry.example.com/nanda/index",
"resolve_url": "https://registry.example.com/nanda/resolve",
"deltas_url": "https://registry.example.com/nanda/deltas",
"tools_url": "https://registry.example.com/nanda/tools",
"provider": {
"name": "My Company",
"url": "https://example.com"
},
"capabilities": ["agentfacts", "deltas", "mcp-tools"]
}To join the NANDA network:
- Deploy your registry with the NANDA bridge endpoints
- Ensure
/.well-known/nanda.jsonis accessible - Contact the MIT NANDA team to register as a federated peer
- (Optional) Implement Quilt-compatible sync or gossip mechanisms for real-time or near-real-time federation
| Package | Question it answers |
|---|---|
nanda-model-provenance |
"Where did this model come from?" (identity, versioning, provider, NANDA serialization) |
nanda-model-card |
"What is this model?" (unified metadata schema — type, status, risk level, metrics, weights hash) |
nanda-model-integrity-layer |
"Does this model's metadata meet policy?" (rule-based checks) |
nanda-model-governance |
"Has this model been cryptographically approved for deployment?" (approval flow with signatures, quorum, scoping, revocation) |
nanda-bridge (this package) |
"How do I expose this to the NANDA network?" (FastAPI router, AgentFacts models, delta sync) |
- Project NANDA - ProjectNANDA.org
- NANDA Adapter - Official NANDA SDK
- NANDA Quilt - Federated registry specification
MIT License - see LICENSE
Contributions welcome! Please read our contributing guidelines and submit pull requests.
Developed by stellarminds.ai and open-sourced for projectnanda.org.