sm-bridge 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sm_bridge-0.3.1/.gitignore +87 -0
- sm_bridge-0.3.1/LICENSE +21 -0
- sm_bridge-0.3.1/PKG-INFO +390 -0
- sm_bridge-0.3.1/README.md +340 -0
- sm_bridge-0.3.1/pyproject.toml +110 -0
- sm_bridge-0.3.1/sm_bridge/__init__.py +107 -0
- sm_bridge-0.3.1/sm_bridge/converter.py +461 -0
- sm_bridge-0.3.1/sm_bridge/federation.py +154 -0
- sm_bridge-0.3.1/sm_bridge/gateway.py +186 -0
- sm_bridge-0.3.1/sm_bridge/models.py +345 -0
- sm_bridge-0.3.1/sm_bridge/py.typed +0 -0
- sm_bridge-0.3.1/sm_bridge/router.py +377 -0
- sm_bridge-0.3.1/sm_bridge/store.py +189 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# PyInstaller
|
|
28
|
+
*.manifest
|
|
29
|
+
*.spec
|
|
30
|
+
|
|
31
|
+
# Installer logs
|
|
32
|
+
pip-log.txt
|
|
33
|
+
pip-delete-this-directory.txt
|
|
34
|
+
|
|
35
|
+
# Unit test / coverage reports
|
|
36
|
+
htmlcov/
|
|
37
|
+
.tox/
|
|
38
|
+
.nox/
|
|
39
|
+
.coverage
|
|
40
|
+
.coverage.*
|
|
41
|
+
.cache
|
|
42
|
+
nosetests.xml
|
|
43
|
+
coverage.xml
|
|
44
|
+
*.cover
|
|
45
|
+
*.py,cover
|
|
46
|
+
.hypothesis/
|
|
47
|
+
.pytest_cache/
|
|
48
|
+
|
|
49
|
+
# Translations
|
|
50
|
+
*.mo
|
|
51
|
+
*.pot
|
|
52
|
+
|
|
53
|
+
# Environments
|
|
54
|
+
.env
|
|
55
|
+
.venv
|
|
56
|
+
env/
|
|
57
|
+
venv/
|
|
58
|
+
ENV/
|
|
59
|
+
env.bak/
|
|
60
|
+
venv.bak/
|
|
61
|
+
|
|
62
|
+
# IDEs
|
|
63
|
+
.idea/
|
|
64
|
+
.vscode/
|
|
65
|
+
*.swp
|
|
66
|
+
*.swo
|
|
67
|
+
*~
|
|
68
|
+
|
|
69
|
+
# Jupyter Notebook
|
|
70
|
+
.ipynb_checkpoints
|
|
71
|
+
|
|
72
|
+
# mypy
|
|
73
|
+
.mypy_cache/
|
|
74
|
+
.dmypy.json
|
|
75
|
+
dmypy.json
|
|
76
|
+
|
|
77
|
+
# Ruff
|
|
78
|
+
.ruff_cache/
|
|
79
|
+
|
|
80
|
+
# macOS
|
|
81
|
+
.DS_Store
|
|
82
|
+
|
|
83
|
+
# Windows Zone.Identifier alternate data streams
|
|
84
|
+
*:Zone.Identifier
|
|
85
|
+
|
|
86
|
+
# Benchmarks
|
|
87
|
+
.benchmarks/
|
sm_bridge-0.3.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Project NANDA Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
sm_bridge-0.3.1/PKG-INFO
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sm-bridge
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: A Python library for building NANDA-compatible AI agent registries
|
|
5
|
+
Project-URL: Homepage, https://github.com/Sharathvc23/sm-bridge
|
|
6
|
+
Project-URL: Documentation, https://github.com/Sharathvc23/sm-bridge#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/Sharathvc23/sm-bridge.git
|
|
8
|
+
Project-URL: Issues, https://github.com/Sharathvc23/sm-bridge/issues
|
|
9
|
+
Author-email: StellarMinds <hello@stellarminds.ai>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: a2a,agent-registry,ai-agents,decentralized-identity,did,fastapi,mcp,nanda
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Framework :: FastAPI
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: fastapi>=0.100.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: httpx>=0.24.0; extra == 'all'
|
|
29
|
+
Requires-Dist: sm-model-card>=0.1.0; extra == 'all'
|
|
30
|
+
Requires-Dist: sm-model-governance>=0.1.0; extra == 'all'
|
|
31
|
+
Requires-Dist: sm-model-integrity-layer>=0.1.0; extra == 'all'
|
|
32
|
+
Requires-Dist: sm-model-provenance>=0.1.0; extra == 'all'
|
|
33
|
+
Provides-Extra: card
|
|
34
|
+
Requires-Dist: sm-model-card>=0.1.0; extra == 'card'
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: httpx>=0.24.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
41
|
+
Provides-Extra: federation
|
|
42
|
+
Requires-Dist: httpx>=0.24.0; extra == 'federation'
|
|
43
|
+
Provides-Extra: governance
|
|
44
|
+
Requires-Dist: sm-model-governance>=0.1.0; extra == 'governance'
|
|
45
|
+
Provides-Extra: integrity
|
|
46
|
+
Requires-Dist: sm-model-integrity-layer>=0.1.0; extra == 'integrity'
|
|
47
|
+
Provides-Extra: provenance
|
|
48
|
+
Requires-Dist: sm-model-provenance>=0.1.0; extra == 'provenance'
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
# SM Bridge
|
|
52
|
+
|
|
53
|
+
A Python library for building NANDA-compatible AI agent registries.
|
|
54
|
+
|
|
55
|
+
**[NANDA](https://projectnanda.org)** (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.
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- **NANDA AgentFacts Models** - Pydantic models implementing the [projnanda/agentfacts-format](https://github.com/projnanda) specification
|
|
60
|
+
- **FastAPI Router** - Drop-in endpoints for `/nanda/index`, `/nanda/resolve`, `/nanda/deltas`
|
|
61
|
+
- **Delta Store** - Change tracking for registry synchronization
|
|
62
|
+
- **Converter Interface** - Abstract pattern for integrating with your existing registry
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install git+https://github.com/Sharathvc23/sm-bridge.git
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Or install from source:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
git clone https://github.com/Sharathvc23/sm-bridge
|
|
74
|
+
cd sm-bridge
|
|
75
|
+
pip install -e .
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
### Basic Usage
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from fastapi import FastAPI
|
|
84
|
+
from sm_bridge import SmBridge, SimpleAgent
|
|
85
|
+
|
|
86
|
+
# Create the bridge
|
|
87
|
+
bridge = SmBridge(
|
|
88
|
+
registry_id="my-registry",
|
|
89
|
+
provider_name="My Company",
|
|
90
|
+
provider_url="https://example.com",
|
|
91
|
+
base_url="https://registry.example.com"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Register agents
|
|
95
|
+
bridge.register_agent(SimpleAgent(
|
|
96
|
+
id="my-agent",
|
|
97
|
+
name="My Agent",
|
|
98
|
+
description="An agent that does things",
|
|
99
|
+
namespace="production",
|
|
100
|
+
labels=["chat", "tool-use"],
|
|
101
|
+
skills=[
|
|
102
|
+
{"id": "summarize", "description": "Summarizes text"},
|
|
103
|
+
{"id": "translate", "description": "Translates between languages"}
|
|
104
|
+
]
|
|
105
|
+
))
|
|
106
|
+
|
|
107
|
+
# Mount routers
|
|
108
|
+
app = FastAPI()
|
|
109
|
+
app.include_router(bridge.router) # /nanda/* endpoints
|
|
110
|
+
app.include_router(bridge.wellknown_router) # /.well-known/nanda.json (RFC 8615)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This gives you:
|
|
114
|
+
|
|
115
|
+
- `GET /nanda/index` - List all public agents (with correct `total_count` for pagination)
|
|
116
|
+
- `GET /nanda/resolve?agent=my-agent` - Resolve a single agent
|
|
117
|
+
- `GET /nanda/deltas?since=0` - Get changes for sync
|
|
118
|
+
- `GET /.well-known/nanda.json` - Registry discovery (RFC 8615 compliant)
|
|
119
|
+
|
|
120
|
+
### Custom Registry Integration
|
|
121
|
+
|
|
122
|
+
For existing registries with their own data models:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from sm_bridge import (
|
|
126
|
+
AbstractAgentConverter,
|
|
127
|
+
SmAgentFacts,
|
|
128
|
+
SmProvider,
|
|
129
|
+
SmEndpoints,
|
|
130
|
+
SmCapabilities,
|
|
131
|
+
SmSkill,
|
|
132
|
+
DeltaStore,
|
|
133
|
+
create_sm_router,
|
|
134
|
+
)
|
|
135
|
+
from typing import Iterator
|
|
136
|
+
|
|
137
|
+
class MyRegistryConverter(AbstractAgentConverter):
|
|
138
|
+
def __init__(self, db_connection):
|
|
139
|
+
super().__init__(
|
|
140
|
+
registry_id="my-registry",
|
|
141
|
+
provider_name="My Company",
|
|
142
|
+
provider_url="https://example.com"
|
|
143
|
+
)
|
|
144
|
+
self.db = db_connection
|
|
145
|
+
|
|
146
|
+
def to_sm(self, agent) -> SmAgentFacts:
|
|
147
|
+
return SmAgentFacts(
|
|
148
|
+
id=f"did:web:example.com:agents:{agent.id}",
|
|
149
|
+
handle=self.build_handle(agent.namespace, agent.id),
|
|
150
|
+
agent_name=agent.display_name,
|
|
151
|
+
label=agent.category,
|
|
152
|
+
description=agent.description,
|
|
153
|
+
version=agent.version,
|
|
154
|
+
provider=self.build_provider(),
|
|
155
|
+
endpoints=SmEndpoints(static=[agent.endpoint_url]),
|
|
156
|
+
capabilities=SmCapabilities(modalities=agent.capabilities),
|
|
157
|
+
skills=[SmSkill(id=s.id, description=s.desc) for s in agent.skills],
|
|
158
|
+
metadata={
|
|
159
|
+
"x_my_registry": {
|
|
160
|
+
"internal_id": agent.internal_id,
|
|
161
|
+
"created_at": agent.created_at.isoformat(),
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def list_agents(self, limit: int, offset: int) -> Iterator:
|
|
167
|
+
return self.db.query_agents(limit=limit, offset=offset)
|
|
168
|
+
|
|
169
|
+
def get_agent(self, agent_id: str):
|
|
170
|
+
return self.db.get_agent(agent_id)
|
|
171
|
+
|
|
172
|
+
def is_public(self, agent) -> bool:
|
|
173
|
+
return agent.visibility == "public"
|
|
174
|
+
|
|
175
|
+
# Create router with custom converter
|
|
176
|
+
converter = MyRegistryConverter(db_connection)
|
|
177
|
+
delta_store = DeltaStore()
|
|
178
|
+
|
|
179
|
+
nanda_router, wellknown_router = create_sm_router(
|
|
180
|
+
converter=converter,
|
|
181
|
+
delta_store=delta_store,
|
|
182
|
+
registry_id="my-registry",
|
|
183
|
+
base_url="https://registry.example.com",
|
|
184
|
+
provider_name="My Company",
|
|
185
|
+
provider_url="https://example.com"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
app = FastAPI()
|
|
189
|
+
app.include_router(nanda_router)
|
|
190
|
+
app.include_router(wellknown_router)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Models
|
|
194
|
+
|
|
195
|
+
### SmAgentFacts
|
|
196
|
+
|
|
197
|
+
The core data structure for agent metadata:
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
from sm_bridge import SmAgentFacts
|
|
201
|
+
|
|
202
|
+
facts = SmAgentFacts(
|
|
203
|
+
id="did:web:example.com:agents:my-agent",
|
|
204
|
+
handle="@my-registry:production/my-agent",
|
|
205
|
+
agent_name="My Agent",
|
|
206
|
+
label="assistant",
|
|
207
|
+
description="An AI assistant",
|
|
208
|
+
version="1.0.0",
|
|
209
|
+
provider=SmProvider(
|
|
210
|
+
name="My Company",
|
|
211
|
+
url="https://example.com"
|
|
212
|
+
),
|
|
213
|
+
endpoints=SmEndpoints(
|
|
214
|
+
static=["https://api.example.com/agents/my-agent"]
|
|
215
|
+
),
|
|
216
|
+
capabilities=SmCapabilities(
|
|
217
|
+
modalities=["text", "tool-use"],
|
|
218
|
+
authentication=SmAuthentication(methods=["did-auth"])
|
|
219
|
+
),
|
|
220
|
+
skills=[
|
|
221
|
+
SmSkill(
|
|
222
|
+
id="urn:my-registry:cap:summarize:v1",
|
|
223
|
+
description="Summarizes long documents",
|
|
224
|
+
inputModes=["text"],
|
|
225
|
+
outputModes=["text"]
|
|
226
|
+
)
|
|
227
|
+
],
|
|
228
|
+
metadata={
|
|
229
|
+
"x_my_registry": {
|
|
230
|
+
"custom_field": "custom_value"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Handle Format
|
|
237
|
+
|
|
238
|
+
NANDA handles follow the format `@registry:namespace/agent-id`:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
handle = SmAgentFacts.create_handle(
|
|
242
|
+
registry="my-registry",
|
|
243
|
+
namespace="production",
|
|
244
|
+
agent_id="my-agent"
|
|
245
|
+
)
|
|
246
|
+
# Returns: "@my-registry:production/my-agent"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Delta Store
|
|
250
|
+
|
|
251
|
+
Track changes for registry synchronization:
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
from sm_bridge import DeltaStore, SmAgentFacts
|
|
255
|
+
|
|
256
|
+
store = DeltaStore()
|
|
257
|
+
|
|
258
|
+
# Record an agent creation/update
|
|
259
|
+
delta = store.add("upsert", agent_facts)
|
|
260
|
+
print(f"Recorded delta with seq={delta.seq}")
|
|
261
|
+
|
|
262
|
+
# Get all changes since seq 0
|
|
263
|
+
deltas = store.since(0)
|
|
264
|
+
|
|
265
|
+
# Get next sequence number for polling
|
|
266
|
+
next_seq = store.next_seq
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
For production, extend `PersistentDeltaStore` to persist to a database:
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
from sm_bridge import PersistentDeltaStore
|
|
273
|
+
|
|
274
|
+
class PostgresDeltaStore(PersistentDeltaStore):
|
|
275
|
+
def __init__(self, dsn: str):
|
|
276
|
+
super().__init__()
|
|
277
|
+
self.conn = psycopg2.connect(dsn)
|
|
278
|
+
|
|
279
|
+
def _persist(self, delta):
|
|
280
|
+
# INSERT INTO nanda_deltas ...
|
|
281
|
+
pass
|
|
282
|
+
|
|
283
|
+
def _load_since(self, seq):
|
|
284
|
+
# SELECT * FROM nanda_deltas WHERE seq > ...
|
|
285
|
+
pass
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## MCP Tools
|
|
289
|
+
|
|
290
|
+
Advertise MCP tools that agents can use:
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
from sm_bridge import SmBridge, SmTool
|
|
294
|
+
|
|
295
|
+
bridge = SmBridge(
|
|
296
|
+
registry_id="my-registry",
|
|
297
|
+
provider_name="My Company",
|
|
298
|
+
provider_url="https://example.com",
|
|
299
|
+
tools=[
|
|
300
|
+
SmTool(
|
|
301
|
+
tool_id="search",
|
|
302
|
+
description="Search the web",
|
|
303
|
+
endpoint="https://api.example.com/mcp/search",
|
|
304
|
+
params=["query", "limit"]
|
|
305
|
+
),
|
|
306
|
+
SmTool(
|
|
307
|
+
tool_id="calculate",
|
|
308
|
+
description="Perform calculations",
|
|
309
|
+
endpoint="https://api.example.com/mcp/calculate",
|
|
310
|
+
params=["expression"]
|
|
311
|
+
)
|
|
312
|
+
]
|
|
313
|
+
)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Registry Discovery
|
|
317
|
+
|
|
318
|
+
The library serves `/.well-known/nanda.json` at the domain root (RFC 8615) via the separate `wellknown_router`:
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
"registry_id": "my-registry",
|
|
323
|
+
"registry_did": "did:web:registry.example.com",
|
|
324
|
+
"namespaces": ["did:web:example.com:*"],
|
|
325
|
+
"index_url": "https://registry.example.com/nanda/index",
|
|
326
|
+
"resolve_url": "https://registry.example.com/nanda/resolve",
|
|
327
|
+
"deltas_url": "https://registry.example.com/nanda/deltas",
|
|
328
|
+
"tools_url": "https://registry.example.com/nanda/tools",
|
|
329
|
+
"provider": {
|
|
330
|
+
"name": "My Company",
|
|
331
|
+
"url": "https://example.com"
|
|
332
|
+
},
|
|
333
|
+
"capabilities": ["agentfacts", "deltas", "mcp-tools"]
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Federating with NANDA
|
|
338
|
+
|
|
339
|
+
To join the NANDA network:
|
|
340
|
+
|
|
341
|
+
1. Deploy your registry with the NANDA bridge endpoints
|
|
342
|
+
2. Ensure `/.well-known/nanda.json` is accessible
|
|
343
|
+
3. Contact the MIT NANDA team to register as a federated peer
|
|
344
|
+
4. (Optional) Implement incremental sync or gossip mechanisms for real-time or near-real-time federation
|
|
345
|
+
|
|
346
|
+
## AI Catalog gateway
|
|
347
|
+
|
|
348
|
+
`create_gateway_router` serves the AI Catalog discovery endpoints for the agents in a
|
|
349
|
+
`DeltaStore`, alongside the `/nanda/*` router (the two surfaces are independent):
|
|
350
|
+
|
|
351
|
+
```python
|
|
352
|
+
from fastapi import FastAPI
|
|
353
|
+
from sm_bridge import DeltaStore, create_gateway_router
|
|
354
|
+
|
|
355
|
+
delta_store = DeltaStore()
|
|
356
|
+
|
|
357
|
+
app = FastAPI()
|
|
358
|
+
app.include_router(
|
|
359
|
+
create_gateway_router(delta_store, base_url="https://reg.example.com", domain="example.com")
|
|
360
|
+
)
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
| Endpoint | Returns |
|
|
364
|
+
|----------|---------|
|
|
365
|
+
| `GET /.well-known/ai-catalog.json` | `CatalogDocument` — all agents |
|
|
366
|
+
| `GET /agents/{slug}` | `CatalogEntry` — a pointer to the agent's card |
|
|
367
|
+
| `GET /cards/{slug}.json` | A2A `AgentCard` (full `SmAgentFacts` included under `_meta`) |
|
|
368
|
+
|
|
369
|
+
Each `SmAgentFacts` is translated into a `CatalogEntry` and an A2A `AgentCard` whose `url`
|
|
370
|
+
is the agent's runtime. Point a NANDA index at `base_url` (as a `hosting_path=registry`
|
|
371
|
+
entry) to make the agents discoverable through the AI Catalog flow.
|
|
372
|
+
|
|
373
|
+
## Related Packages
|
|
374
|
+
|
|
375
|
+
| Package | Question it answers |
|
|
376
|
+
|---------|-------------------|
|
|
377
|
+
| [`sm-model-provenance`](https://github.com/Sharathvc23/sm-model-provenance) | "Where did this model come from?" (identity, versioning, provider, NANDA serialization) |
|
|
378
|
+
| [`sm-model-card`](https://github.com/Sharathvc23/sm-model-card) | "What is this model?" (unified metadata schema — type, status, risk level, metrics, weights hash) |
|
|
379
|
+
| [`sm-model-integrity-layer`](https://github.com/Sharathvc23/sm-model-integrity-layer) | "Does this model's metadata meet policy?" (rule-based checks) |
|
|
380
|
+
| [`sm-model-governance`](https://github.com/Sharathvc23/sm-model-governance) | "Has this model been cryptographically approved for deployment?" (approval flow with signatures, quorum, scoping, revocation) |
|
|
381
|
+
| `sm-bridge` (this package) | "How do I expose this to the NANDA network?" (FastAPI router, AgentFacts models, delta sync) |
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
## License
|
|
385
|
+
|
|
386
|
+
MIT
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
*Personal research contributions aligned with [Project NANDA](https://projectnanda.org) standards. [Stellarminds.ai](https://stellarminds.ai)*
|