Skip to main content

sm-bridge

PyPI Python License

The universal on-ramp to the NANDA agent-internet.

sm-bridge lets any agent source — your own registry, an AI catalog, an ANS registry, or a single domainless agent — join the NANDA Index through one small library, and emerge carrying a normalized, cryptographically verifiable proof of trust. The Index stays a quilt of registries (one entry per registry, never one per agent); the bridge is how you get onto it.

The core is just FastAPI + Pydantic. Verification and transparency-log features live in optional extras, so you only pull cryptography when you use it.

What it does

  • Onboard any source to the quilt. A registry-scale source (like ANS, with its own resolver) joins as one entry and resolution is delegated back to it — the bridge never mirrors its agents. A source with no registry of its own (a catalog, a did:key agent) is hosted locally.
  • Verify each source with a pluggable trust profile and normalize the result to one proof block: VERIFIED / FAILED / NOT_VERIFIED. Every VERIFIED is a real signature, DNS, or Merkle check — absent live infrastructure you get an honest NOT_VERIFIED(reason), never a mocked pass.
  • Serve the NANDA discovery surfaces as drop-in FastAPI routers: /nanda/index, /nanda/resolve, /nanda/deltas, /.well-known/nanda.json, plus an AI-Catalog gateway.

Trust profiles today: ed25519-agentcard, ans-scitt (ANS SCITT receipts), ans-txt (ANS DNS discovery), dns-aid (SVCB + DNSSEC + DANE), jws-catalog (signed AI-Catalog), and nanda-delegation (did:key delegation chains). See docs/trust-profiles.md.

Install

pip install sm-bridge                 # core: FastAPI routers, models, delta sync
pip install "sm-bridge[trust]"        # + verification adapters (ed25519/SCITT/DNS-AID/JWS/delegation)
pip install "sm-bridge[trust,tlog]"   # + RFC 6962 transparency log & conformance self-test

Requires Python 3.11+.

Onboard and verify

from sm_bridge import SmBridge, SimpleAgent, SimpleAgentConverter, ANSEntryConverter, TrustRegistry
from sm_bridge.trust.ed25519_agentcard import Ed25519AgentCardProfile
from sm_bridge.trust.ans_scitt import AnsScittProfile

# A source with no registry of its own → hosted locally.
conv = SimpleAgentConverter(registry_id="quilt", provider_name="Q", provider_url="https://q.example")
conv.register(SimpleAgent(id="finance", name="Finance Agent", description="does finance"))

bridge = SmBridge(
    registry_id="quilt", provider_name="Q", provider_url="https://q.example",
    converter=conv,
    trust_registry=TrustRegistry([Ed25519AgentCardProfile(), AnsScittProfile()]),
    # A registry-scale source (ANS) → one entry, resolution delegated back to it.
    entries=[ANSEntryConverter(registry_name="acme-ans", resolver_endpoint="https://ans.acme.example")],
)

# GET /nanda/resolve?agent=finance          → agent facts + a normalized proof block
# GET /nanda/registries/acme-ans/resolve    → a delegation pointer (the quilt never mirrors ANS's agents)

Command line

The same verification is available from the terminal ([trust] extra):

sm-bridge verify ans-scitt   --receipt receipt.cbor --root-keys root-keys.txt
sm-bridge verify jws-catalog --catalog ai-catalog.json --signature sig.jws --jwks jwks.json
sm-bridge verify agent-card  --card card.json --signature-b64 <b64> --pubkey key.pem
sm-bridge verify dns-aid     --fqdn agent.example.com [--dane]
sm-bridge verify delegation  --evidence delegation-bundle.json

Exit code 0 = VERIFIED, 1 = FAILED, 2 = NOT_VERIFIED.

Runnable demos

Two offline, self-contained scenarios (see examples/):

python examples/demo1_switchboard.py            # one query → an ANS registry (delegated) + a non-ANS catalog (verified)
python examples/demo2_domainless_delegation.py  # a domainless did:key earns scoped, revocable delegation

Serve a NANDA-compatible registry

If you just want to expose your own agents on NANDA, mount the routers and register agents:

from fastapi import FastAPI
from sm_bridge import SmBridge, SimpleAgent

bridge = SmBridge(
    registry_id="my-registry",
    provider_name="My Company",
    provider_url="https://example.com",
    base_url="https://registry.example.com",
)

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"},
    ],
))

app = FastAPI()
app.include_router(bridge.router)            # /nanda/* endpoints
app.include_router(bridge.wellknown_router)  # /.well-known/nanda.json (RFC 8615)

You get:

  • GET /nanda/index — list public agents (with a correct total_count for pagination)
  • GET /nanda/resolve?agent=my-agent — resolve a single agent
  • GET /nanda/deltas?since=0 — change feed for synchronization
  • GET /.well-known/nanda.json — registry discovery document

Integrate an existing registry

Implement the converter protocol to expose your own data model, without copying agents into a second store:

from typing import Iterator

from sm_bridge import (
    AbstractAgentConverter, SmAgentFacts, SmEndpoints, SmCapabilities, SmSkill,
    DeltaStore, create_sm_router,
)


class MyRegistryConverter(AbstractAgentConverter):
    def __init__(self, db):
        super().__init__(registry_id="my-registry", provider_name="My Company",
                         provider_url="https://example.com")
        self.db = db

    def to_sm(self, agent) -> SmAgentFacts:
        return SmAgentFacts(
            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=SmEndpoints(static=[agent.endpoint_url]),
            capabilities=SmCapabilities(modalities=agent.capabilities),
            skills=[SmSkill(id=s.id, description=s.desc) for s in agent.skills],
        )

    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"

To attach real verification at resolve time, add a trust_evidence(agent) -> (profile_id, evidence) method to your converter and inject a TrustRegistry — the resolved facts then carry a ProofResult.

Delta sync & AI-Catalog gateway

  • Delta storeDeltaStore tracks upserts/deletes with a monotonic cursor for registry-to-registry synchronization; subclass PersistentDeltaStore to back it with a database. The default HTTP sync transport is the [federation] extra.
  • AI-Catalog gatewaycreate_gateway_router(delta_store, base_url=..., domain=...) serves /.well-known/ai-catalog.json, /agents/{slug}, and A2A /cards/{slug}.json alongside the /nanda/* router.

Transparency log & conformance

The [tlog] extra adds an RFC 6962 Merkle tree over the delta log, a signed checkpoint, and inclusion/consistency proofs, plus a conformance self-test (sm_bridge.conformance) that verifies the checkpoint signature, recomputes the root, checks append-only growth, and detects tampering.

Verifiable Agent Feed ([feed])

The [feed] extra projects the delta log as a signed, hash-chained Verifiable Agent Feedalongside /nanda/deltas, not replacing it. sm_bridge.feed.build_delta_feed(deltas, identity, ...) returns a signed feed-page a peer subscribes to with ?since=<cursor>; read_delta_feed(page) verifies it for authenticity and completeness (no dropped or reordered delta) and returns the verified records. Where /nanda/deltas asks a puller to trust the server for completeness, the feed lets a subscriber prove it. The extra is opt-in; the core never imports sm-feed.

Documentation

Related packages

Part of the sm-* trust stack:

Package Role
sm-bridge (this package) Onboard any agent source to the NANDA Index, with a normalized verifiable proof of trust
sm-arp Agency Receipt Protocol — signed receipts for what an agent did
sm-conformance Signed, offline-verifiable conformance badges

License

MIT


Aligned with Project NANDA. Built by Stellarminds.ai.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sm_bridge-0.8.0.tar.gz (65.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sm_bridge-0.8.0-py3-none-any.whl (78.9 kB view details)

Uploaded Python 3

File details

Details for the file sm_bridge-0.8.0.tar.gz.

File metadata

  • Download URL: sm_bridge-0.8.0.tar.gz
  • Upload date:
  • Size: 65.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for sm_bridge-0.8.0.tar.gz
Algorithm Hash digest
SHA256 8097d05ff26916d3259fa6329afd902f768f3b1478823dbac502de5fd65114e3
MD5 a0d29d92cfff5c4c91bcf1a89f45bfb3
BLAKE2b-256 f1199f71d7b4784fc7211cea58be5098af088fe83ae023e1713e82d4b9fe98ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for sm_bridge-0.8.0.tar.gz:

Publisher: release.yml on Sharathvc23/sm-bridge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sm_bridge-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: sm_bridge-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 78.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for sm_bridge-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 681aae181094d2fcec81da15f6cab9841a9fc1a752be044a9abca1b060c6fdca
MD5 4745f64591876228b33d3a53f3b61a41
BLAKE2b-256 68ce585f96a64f2d967d571947cfee7e27d1fad9944a4b71f1b5c3390c409379

See more details on using hashes here.

Provenance

The following attestation bundles were made for sm_bridge-0.8.0-py3-none-any.whl:

Publisher: release.yml on Sharathvc23/sm-bridge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.1

2 files

0.4.0

2 files

0.3.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page