Zero-allocation mesh networking middleware for autonomous robot fleets, edge-AI swarms, and multi-agent systems
Project description
omnimesh — Python SDK
Decentralized mesh networking for autonomous robot fleets and edge-AI systems.
Native Rust performance. Pure Python API. Cryptographically signed messages.
pip install omnimesh
Overview
omnimesh lets robots, AI nodes, and IoT devices communicate over a cryptographically secured mesh network. Each node has a unique identity (DID) derived from an Ed25519 keypair. Messages are signed automatically — tampering is detected and rejected.
import omnimesh
# Each client = one node in the mesh
robot = omnimesh.Client(mode="lightweight", listen_port=9001)
print(robot.did) # unique 64-char hex identity
Modes
| Mode | Transport | Crypto | Use Case |
|---|---|---|---|
"development" |
In-process memory | Optional | Unit tests, CI, single-process demos |
"lightweight" |
TCP | Verify if signed | Multi-process, same machine or LAN |
"production" |
TCP + TLS | Required (rejects unsigned) | Fleet deployment |
# Testing (no network, instant)
client = omnimesh.Client(mode="development")
# Real networking between processes
client = omnimesh.Client(mode="lightweight", listen_port=9001)
# Production with mandatory signature enforcement
client = omnimesh.Client(mode="production", listen_port=9001)
Peer Discovery
Nodes find each other by registering peers manually. Each node needs to know:
- The peer's DID (64-char hex string)
- The peer's IP:port
# On Robot A (port 9001)
robot_a = omnimesh.Client(mode="lightweight", listen_port=9001)
# On Robot B (port 9002)
robot_b = omnimesh.Client(mode="lightweight", listen_port=9002)
# Tell A where B is, and tell B where A is
robot_a.register_peer(robot_b.did, "192.168.1.42:9002")
robot_b.register_peer(robot_a.did, "192.168.1.41:9001")
For same-machine testing, use 127.0.0.1 with different ports.
Sending Messages
Agent Commands (general-purpose)
client.send_agent_command(
target_did_hex=peer_did, # Who to send to
command_type="pick", # Command name
target_id=b"robot-1", # Target identifier
payload_data=b"shelf-A12", # Arbitrary bytes
)
Motion Commands (ROS 2 geometry_msgs/Twist compatible)
client.send_motion_command(
target_did_hex=peer_did,
linear_x=1.5, # Forward velocity (m/s)
linear_y=0.0,
linear_z=0.0,
angular_x=0.0,
angular_y=0.0,
angular_z=0.8, # Turn rate (rad/s)
deadline_ns=0, # 0 = no deadline
)
Heartbeats (telemetry)
client.send_heartbeat(
target_did_hex=peer_did,
uptime_ms=60000, # Node uptime
cpu=75, # CPU usage %
mem_kb=4096, # Memory usage
epoch=1, # Monotonic counter
)
LLM Queries (edge AI inference)
client.send_llm_query(
target_did_hex=peer_did,
prompt="What is the optimal path?",
system_prompt="You are a navigation AI.",
model="llama3",
)
Receiving Messages
Blocking (with timeout)
# Waits up to 5 seconds, returns None if no message arrives
# GIL is released — other Python threads can run while waiting
msg = client.receive(timeout_ms=5000)
Non-blocking
msg = client.try_receive() # Returns immediately
Message format
All messages are Python dicts:
{
"type": "agent_command", # Message type
"sender_did": "a58a9b3b...", # Who sent it
"received_at_us": 1780382..., # Receive timestamp (microseconds)
"command_type": "pick", # Type-specific fields...
"target_did": "...",
"payload": [115, 104, ...], # Bytes as list of ints
}
Convert payload to bytes: bytes(msg["payload"])
Message types and fields
msg["type"] |
Fields |
|---|---|
"agent_command" |
command_type, target_did, payload |
"motion_command" |
linear_x/y/z, angular_x/y/z, deadline_ns |
"heartbeat" |
uptime_ms, cpu_usage, mem_usage_kb, epoch |
"llm_query" |
prompt, system_prompt, model |
"llm_response" |
response, latency_us |
"inference_result" |
model_id, confidence, label, latency_us |
Lifecycle Management
# Check queue depth
print(client.inbox_len())
# Graceful shutdown (stops background threads)
client.shutdown()
# Check state
client.is_shutdown() # True after shutdown()
# Drain remaining messages after shutdown
while True:
msg = client.try_receive()
if msg is None:
break
process(msg)
Production Deployment
Two Robots on a LAN
Robot A (192.168.1.41):
import omnimesh
robot_a = omnimesh.Client(mode="production", listen_port=9000)
# Register all known peers
robot_a.register_peer(ROBOT_B_DID, "192.168.1.42:9000")
robot_a.register_peer(ROBOT_C_DID, "192.168.1.43:9000")
# Send commands
robot_a.send_motion_command(ROBOT_B_DID, linear_x=1.0)
# Receive
while True:
msg = robot_a.receive(timeout_ms=1000)
if msg:
handle_message(msg)
Robot B (192.168.1.42):
import omnimesh
robot_b = omnimesh.Client(mode="production", listen_port=9000)
robot_b.register_peer(ROBOT_A_DID, "192.168.1.41:9000")
while True:
msg = robot_b.receive(timeout_ms=1000)
if msg and msg["type"] == "motion_command":
execute_velocity(msg["linear_x"], msg["angular_z"])
Fleet Coordinator Pattern
import omnimesh
coordinator = omnimesh.Client(mode="production", listen_port=9000)
# Register fleet
fleet = {
"picker": ("aabb...", "192.168.1.10:9000"),
"transporter":("ccdd...", "192.168.1.11:9000"),
"placer": ("eeff...", "192.168.1.12:9000"),
}
for name, (did, addr) in fleet.items():
coordinator.register_peer(did, addr)
# Assign tasks
for name, (did, _) in fleet.items():
coordinator.send_agent_command(did, f"task-{name}", b"", b"zone-A")
# Collect heartbeats
while True:
msg = coordinator.receive(timeout_ms=5000)
if msg and msg["type"] == "heartbeat":
print(f"Node {msg['sender_did'][:8]}: cpu={msg['cpu_usage']}%")
Thread Safety
The client is fully thread-safe. receive() releases the Python GIL, so other threads can run concurrently.
import omnimesh
import threading
client = omnimesh.Client(mode="lightweight", listen_port=9001)
def sender():
while True:
client.send_heartbeat(peer_did, uptime_ms=1000, cpu=50, mem_kb=2048, epoch=1)
time.sleep(1)
def receiver():
while True:
msg = client.receive(timeout_ms=1000)
if msg:
process(msg)
threading.Thread(target=sender, daemon=True).start()
threading.Thread(target=receiver, daemon=True).start()
Security Model
- Every node has an Ed25519 keypair generated at startup
- The DID is the public key (32 bytes, displayed as 64-char hex)
- Every message is signed with BLAKE3(header + payload) → Ed25519
- The receiver verifies the signature using the sender's DID as the public key
- In production mode, unsigned messages are rejected
- Tampered messages fail verification and are silently dropped
Error Handling
# Invalid DID format
try:
client.send_agent_command("not-a-valid-did", "test", b"", b"")
except ValueError as e:
print(e) # "DID must be exactly 32 bytes (64 hex chars)"
# Sending after shutdown
try:
client.shutdown()
client.send_agent_command(peer_did, "test", b"", b"")
except ValueError as e:
print(e) # "Client has been shut down"
# Invalid mode
try:
omnimesh.Client(mode="invalid")
except ValueError as e:
print(e) # "mode must be 'development', 'lightweight', or 'production'"
API Reference
omnimesh.Client(mode="development", listen_port=None)
Create a mesh node.
Parameters:
mode—"development","lightweight", or"production"listen_port— TCP port to listen on (required for lightweight/production)
Properties:
.did→ 64-char hex string (node identity)
Methods:
| Method | Description |
|---|---|
register_peer(did_hex, addr) |
Register a peer's DID and IP:port |
send_agent_command(did, cmd, target_id, payload) |
Send a command |
send_motion_command(did, lx, ly, lz, ax, ay, az, deadline) |
Send velocity |
send_heartbeat(did, uptime_ms, cpu, mem_kb, epoch) |
Send telemetry |
send_llm_query(did, prompt, system_prompt, model) |
Send AI query |
receive(timeout_ms) |
Block until message or timeout |
try_receive() |
Non-blocking receive |
inbox_len() |
Messages in queue |
shutdown() |
Graceful stop |
is_shutdown() |
Check if stopped |
Requirements
- Python 3.8+
- Platforms: Windows (pre-built), Linux/macOS (via GitHub Actions on release)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file omnimesh-1.0.1-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: omnimesh-1.0.1-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b70d8e0c6782e224b87e3bec519a8bf85c0863a6f1443b8e4d6042660e5c2a28
|
|
| MD5 |
c8ead7ba6407e94c4dc1f0fbe95910ed
|
|
| BLAKE2b-256 |
dd67f3a174b019b31766c7c2d96cf68f96bffaf685b21784967a64e4cb21d80a
|