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.

Upgrade from 0.6.0 or earlier. 0.7.0 fixes a flaw in /nanda/resolve: an identifier scoped to a different registry (@other-registry:ns/foo, or a did:web under another host) was reduced to a bare id and answered locally, carrying this registry's proof block, with nothing to tell the caller the scope had been ignored. Such an identifier is now rejected with 400.

0.7.0 and 0.8.0 also change behaviour deliberately: no certification block is emitted unless the source declared one, conformance_level is computed rather than asserted, ns:agent is no longer split to agent, and the delta log is append-only. See CHANGELOG.md before upgrading.

Requires Python 3.11 or later. MIT licensed.

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 store — DeltaStore 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 gateway — create_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 Feed — alongside /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

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

Auditing this registry

This package serves records, which makes it a thing the corroboration stack audits rather than a consumer of it. Two instances serving the same agents are swept by sm-divergence in CI and must corroborate to AGREE; a divergence means this registry is misrepresenting its own data.

That check has a limit, and it is pinned as a test rather than left implied: two instances of the same code misbehaving identically agree with each other. So the converter also records what it supplied that the source did not — provenance, carrying invented, defaulted and dropped — because nothing downstream can infer it. See ARCHITECTURE.md.

License

MIT


Aligned with Project NANDA. Built by Stellarminds.ai.

Metadata

Release files for sm-bridge 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sm-bridge 0.9.0
File Size Uploaded Provenance Actions
sm_bridge-0.9.0.tar.gz 67.8 kB With provenance Details for sm_bridge-0.9.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for sm-bridge 0.9.0
File Interpreter ABI Platform Actions
sm_bridge-0.9.0-py3-none-any.whl Python 3 none any Details for sm_bridge-0.9.0-py3-none-any.whl

Total release size: 149.6 kB

Release files / sm_bridge-0.9.0.tar.gz

Download URL sm_bridge-0.9.0.tar.gz
Size 67.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b2729065979813971abaa6ddf49ff03a25d26cd0a8a751045607ade42cbe1625
BLAKE2b-256 checksum
How to use checksums
c6bb05a1f148cf72e54769a0acfb5e22984f582eeb10693300fd69a16c56473d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Release files / sm_bridge-0.9.0-py3-none-any.whl

Download URL sm_bridge-0.9.0-py3-none-any.whl
Size 81.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2cce0a39eb48d60cb08d37596b3fbdaf624d4fa6b863772fd4e3aaaf86f7c265
BLAKE2b-256 checksum
How to use checksums
268f7f073b25ca96a8f9a8b25ac77dc215f719136f22a89f741ddf321aed95e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Security for sm-bridge 0.9.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for sm_bridge-0.9.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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