Net Python SDK
A latency-first encrypted mesh where services and agents announce what they can do, discover each other at runtime, and invoke work over typed RPC.
There is no broker. Every node is a peer on a flat, encrypted topology. A node publishes the capabilities it has — a GPU, a model, a tool, a licensed seat — and other nodes find it by what it can do, not by hostname. Credentials never leave the node that holds them: the machine with the secret runs the work.
# Find something that can do the job, then do it — no registry, no config.
# `rpc` is the TypedMeshRpc handle built in "The loop" below.
resp = call_tool(rpc, "summarize", {"text": text})
Why this instead of a queue
Kafka, NATS and Redis Streams move bytes between a fixed producer and a fixed consumer through a broker you operate. That's a different problem. Net is for when the set of participants isn't known in advance and work has state worth observing:
| You need | Net gives you |
|---|---|
| Tools that appear and vanish at runtime | Capability announce + discovery, event-driven — no polling, no service registry |
| Work spread across machines or organizations | One flat encrypted mesh; multi-hop discovery bounded at 16 hops |
| Credentials that must not travel | The node holding the secret executes; callers never see it |
| More than "did it return 200" | Durable logs, folded state, artifacts, streams, and replayable recovery |
| GPUs matched by capability, not hostname | Hardware is a discoverable characteristic, with atomic gang-claim under contention |
Don't reach for it when one API call solves the problem, when a single server and database are enough, or when you have a fixed producer, a fixed consumer and a broker you're happy operating. The honest version of that list is in When to Use Net.
Install
pip install net-mesh-sdk
Publishes as net-mesh-sdk, imports as net_sdk. The native binding
net-mesh comes in transitively; PyPI wheels ship every feature enabled.
The loop: announce → discover → invoke
Announce a tool, and it becomes discoverable across the mesh:
from net_sdk import MeshNode, add_tool_capabilities_to_announce, serve_tool
from net.mesh_rpc import TypedMeshRpc
node = MeshNode(bind_addr="127.0.0.1:0", psk="42" * 32) # 32-byte hex string
rpc = TypedMeshRpc.from_mesh(node._native) # the tool surface takes the RPC handle
def web_search(req):
return {"results": [f"first hit for '{req['query']}'"]}
handle = serve_tool(
rpc,
{"name": "web_search", "description": "Search the web.", "tags": ["web", "research"]},
web_search,
)
# handle stays alive while the tool is served; close it to withdraw.
# Announce the capability (the ai-tool:<tool_id> tag + tools[] entry) so
# peers can discover it — registering the handler alone is not enough.
caps = add_tool_capabilities_to_announce({}, [handle.descriptor])
node.announce_capabilities(caps)
Discover — react to the mesh changing rather than polling it:
from net_sdk import list_tools, watch_tools
native = node._native # the tool surface reads the native handle
for t in list_tools(native): # baseline snapshot
print(t.tool_id, "v" + str(t.version), "tags=", t.tags)
async for change in watch_tools(native): # pushed on fold mutation
print(change) # added, removed, or publisher count changed
Invoke — call_tool finds a provider for the name and calls it:
from net_sdk import call_tool, call_tool_async, call_tool_streaming
from net.mesh_rpc import AsyncTypedMeshRpc
resp = call_tool(rpc, "web_search", {"query": "how does the capability fold work"})
arpc = AsyncTypedMeshRpc.from_mesh(node._native)
resp = await call_tool_async(arpc, "web_search", {"query": "…"})
for chunk in call_tool_streaming(rpc, "tail", {"tail": "events"}):
handle_chunk(chunk)
For services rather than tools, nRPC gives you the same shape with deadlines, streaming and cancellation — Typed RPC.
The bus
NetNode is the other node type: a sharded, in-process event bus with explicit
backpressure.
from net_sdk import NetNode
# Context manager handles shutdown/drain for you. `redis_url` because the
# default (memory) transport selects the Noop adapter: it counts batches and
# discards them, so `subscribe` would return nothing here.
with NetNode(shards=4, redis_url="redis://127.0.0.1:6379") as node:
node.emit({"sensor": "lidar", "range_m": 12.5})
node.emit_raw('{"sensor": "radar", "range_m": 45.0}')
node.emit_batch([{"a": 1}, {"a": 2}, {"a": 3}])
for event in node.subscribe(limit=10, timeout=5.0):
print("event", event)
stats = node.stats()
print(stats.events_ingested, "ingested,", stats.events_dropped, "dropped")
emit returns once the event is accepted into the local ring buffer — not
that anyone processed it. Under backpressure it drops, and
stats().events_dropped is how you find out. That distinction is the whole
philosophy: Submitted Is Not Completed.
Transports are constructor arguments — redis_url=, jetstream_url=, or
mesh_*, with the same emit / subscribe code. The default, memory, is the
one that does not deliver: it counts events and discards them, so it suits
ingestion, batching, backpressure, counters and lifecycle, and a subscribe
loop on it waits forever rather than erroring.
Claude Code Skill
Net looks like Kafka or NATS from the outside, and the model underneath is different enough that an agent working from surface familiarity will write integration code that runs and is quietly wrong. Install the skills first:
npx skills add ai-2070/net-claude-skill -g
Drop -g to install into the current project only. To update to the latest
version:
npx skills update -g
Restart Claude Code and run /skills — net-event-bus and net-payments
should be listed. They load automatically when a request matches:
"Wire up a Net publisher and subscriber over the mesh in Python."
net-event-bus covers pub/sub, nRPC, the MCP bridge, organization capability
auth, the gang-claim scheduler, and RedEX / CortEX / Dataforts.
net-payments covers x402 pricing, quotes, settlement and spend policy. Full
install options in Claude Skills.
Give the agent the source too
opensrc is a small tool that fetches a package's real source into a local cache for exactly this purpose:
npx -y opensrc@latest path ai-2070/net
Two packages, and what lives where
net_sdk is the pure-Python wrapper; every method dispatches into the net
PyO3 binding. Most things are re-exported on net_sdk, but a couple of
surfaces live only on net:
from net import RedisStreamDedup # consumer-side dedup helper
from net import RpcTimeoutError, RpcError # the nRPC error family
Which classes exist at all depends on the Cargo features the binding was built
with. Wheels ship everything; this only bites on source builds via
maturin develop.
What's in the box
| Surface | Guide |
|---|---|
| Event bus — shards, typed streams, backpressure, Redis / JetStream | Event bus |
| Mesh streams — direct peer-to-peer, windowed | Mesh streams |
| Capabilities — announce and discover | Discover and invoke |
| nRPC — typed request/response, streaming, cancellation | Typed RPC |
| Distributed mesh channels — roster fan-out with capability auth | Channels |
| RedEX / CortEX / NetDB — logs, folds, queries | Durable logs, Folds, NetDB |
| MeshDB — federated queries | MeshDB |
| Dataforts — blobs, greedy cache, data gravity | Blob storage |
| Compute + Groups — daemons, migration, replica/fork/standby | Daemons, Continuity |
| Deck — the operator surface | Deck |
| MCP bridge — wrap an MCP server, or serve the mesh as MCP | Wrap MCP, Expose as MCP |
| Organizations — capabilities only your org can discover | Private capabilities |
| Security — identity, delegable tokens, subnets | Identity, Security model |
| Errors — the full exception hierarchy | Errors |
| Redis Streams dedup | Deduplication |
Where to go next
- Quickstart — install the SDK and connect two nodes.
- Discover and invoke — announce a tool and call it by capability.
- Production deployment — run the mesh beyond a single host.
- Errors — the exception hierarchy, then net-mesh-sdk on PyPI.
License
MIT OR Apache-2.0
Metadata
Release files for net-mesh-sdk 0.37.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| net_mesh_sdk-0.37.1.tar.gz | 100.5 kB | Without provenance | Details for net_mesh_sdk-0.37.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| net_mesh_sdk-0.37.1-py3-none-any.whl | Python 3 | none | any | Details for net_mesh_sdk-0.37.1-py3-none-any.whl |
Total release size: 179.6 kB
Release files / net_mesh_sdk-0.37.1.tar.gz
| Download URL | net_mesh_sdk-0.37.1.tar.gz |
|---|---|
| Size | 100.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cb20064f39d8fffc6728267dd4d2a98fd96f1ce3c7668270855bd5075088b9f6
|
|
BLAKE2b-256 checksum How to use checksums |
c8f9da2566bedcd16f16be65cdc4f6d3f45ea06fd824423712b639ad90929e96
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / net_mesh_sdk-0.37.1-py3-none-any.whl
| Download URL | net_mesh_sdk-0.37.1-py3-none-any.whl |
|---|---|
| Size | 79.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f9eb0bac4144a645d872b2296a9d476260bd4036356c263b3371acfa741d55e8
|
|
BLAKE2b-256 checksum How to use checksums |
7fa075435231c8271bf689222f786ac17c3dc49ed415c57de881affe50ac47d0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for net-mesh-sdk 0.37.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
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.