mesh-peer-registry
A small, shared, language-agnostic peer registry for the mesh network used by hermes-mesh, openclaw-mesh, and diploid-mesh.
Peers register with an Ed25519 public key and a webhook URL, then discover each other over a simple HTTP API. The server never holds private keys.
About
mesh-peer-registry provides a centralized but state-light way for mesh agents to announce themselves to one another:
- Peers register an Ed25519 public key and a webhook URL under a unique name.
- Registration, deregistration, and refresh requests are signed by the peer's private key, so the registry can trust the public key it stores.
- Other peers query the registry to find a recipient's webhook URL and public key.
- Mesh messages are signed by the sender and verified by the receiver against the sender's public key from the registry.
The signing protocol uses compact, deterministic, sorted-key JSON, making it straightforward to implement in other runtimes (e.g. the Node.js implementation in openclaw-mesh).
Cross-harness mesh
mesh-peer-registry is the shared backbone that lets agents from different harnesses talk to each other:
- Hermes agents speak through
hermes-mesh. - OpenClaw agents speak through
openclaw-mesh. - diploid-agent agents speak through
diploid-mesh.
All three share:
- The bracketed
[mesh]envelope format and Ed25519 wire signatures. - The same local vault layout (
mesh/agents/<name>/identity.yaml). - The same optional
mesh-peer-registryserver for multi-host discovery.
This means a Hermes fleet agent can mesh_send to a diploid agent, and the diploid agent can reply to an OpenClaw agent, with the same identity and envelope format everywhere.
Features
- HTTP API for register, list, get, refresh, and deregister operations.
- Ed25519 signatures on all mutating requests.
- SQLite-backed store by default, with the path configurable via
--store. - TTL + reaper — peers can register with a TTL in seconds; a background reaper removes expired peers and refreshes keep them alive.
- CLI server launcher.
- Python client (
RegistryClient) with built-in signing. - No private keys kept by the registry.
Quick start
Install and run the server over plain HTTP for local development:
pip install mesh-peer-registry
MESH_REGISTRY_ALLOW_INSECURE=1 mesh-peer-registry --port 8646 --store ~/.mesh/registry.sqlite
The server will listen on http://127.0.0.1:8646 and store peers in ~/.mesh/registry.sqlite.
For production, serve over HTTPS with --ssl-cert / --ssl-key and set MESH_REGISTRY_HSTS=1 to emit Strict-Transport-Security headers.
CLI options
| Option | Default | Description |
|---|---|---|
--host |
127.0.0.1 |
Bind host. |
--port |
8646 |
Bind port. |
--store |
~/.mesh/registry.sqlite |
SQLite store file path. |
--reaper-interval |
60.0 |
Interval in seconds between TTL reaping passes. |
--admin-token |
— | Token required for /health and /metrics. |
--ssl-cert / --ssl-key |
— | Optional TLS certificate and key for HTTPS. |
--behind-proxy |
false |
Trust X-Forwarded-Proto and X-Forwarded-For from a reverse proxy. |
--rate-limit |
0 |
Maximum registrations per IP per minute (0 disables). |
--hsts |
false |
Emit Strict-Transport-Security for HTTPS responses. |
Environment variables mirror the flags and middleware settings:
MESH_REGISTRY_ALLOW_INSECURE— set to1to allow plain HTTP requests.MESH_REGISTRY_BEHIND_PROXY— set to1to enable proxy header handling.MESH_REGISTRY_RATE_LIMIT— per-IP registration limit per minute (0disables).MESH_REGISTRY_HSTS— set to1to emit HSTS headers.MESH_REGISTRY_PIN— when set, the client verifies the server certificate SPKI matches this SHA-256 hex digest.
API
| Method | Path | Description |
|---|---|---|
POST |
/register |
Register or update a peer. Body must include name, url, public_key. Optional: role, description, ttl (seconds). Signed with X-Mesh-Signature. |
GET |
/peers |
List peers. Query params: role, limit, offset. Returns {peers, total, limit, offset}. |
GET |
/peers/{name} |
Get one peer. |
POST |
/peers/{name}/refresh |
Refresh last_seen for a peer (prevents TTL expiry). Signed with X-Mesh-Signature. |
DELETE |
/peers/{name} |
Deregister a peer. Signed with X-Mesh-Signature. |
GET |
/health |
Health check. Requires X-Admin-Token if --admin-token is set. |
GET |
/metrics |
Basic registry metrics. Requires X-Admin-Token if --admin-token is set. |
All registration, refresh, and deregistration requests must include a valid Ed25519 signature in the X-Mesh-Signature header over the sorted JSON body (or the action payload for refresh/deregister).
Python client
from mesh_peer_registry.crypto import generate_keypair
from mesh_peer_registry.client import RegistryClient
private, public = generate_keypair()
# For plain HTTP development, allow_insecure=True is required unless the
# server is configured with MESH_REGISTRY_ALLOW_INSECURE=1.
client = RegistryClient(
"http://127.0.0.1:8646",
private,
public,
allow_insecure=True,
pin=None,
)
# For HTTPS production with certificate pinning:
# client = RegistryClient(
# "https://registry.example.com",
# private,
# public,
# pin="sha256-hex-of-server-certificate-spki",
# )
client.register(
"agent0",
"http://127.0.0.1:8645/mesh/receive",
role="operator",
description="Hermes operator node",
ttl=3600,
)
print(client.list_peers())
# Keep the registration alive before the TTL expires.
client.refresh("agent0")
# Later, deregister.
client.deregister("agent0")
Verifying a message
Receivers fetch the sender's public key from the registry and verify the X-Mesh-Signature header:
from mesh_peer_registry.crypto import verify_message
from mesh_peer_registry.client import RegistryClient
# Read-only lookup can use an empty keypair and allow_insecure for local HTTP.
client = RegistryClient(
"http://127.0.0.1:8646",
"",
"",
allow_insecure=True,
)
peer = client.get_peer("agent0")
# body is the raw request body; signature is from the X-Mesh-Signature header.
ok = verify_message(peer.public_key, body, signature)
When X-Mesh-Timestamp is included in the signed payload (optional, controlled by MESH_SIGN_TIMESTAMP on the sender), the receiver should prepend f"{timestamp}\n" to the body before verification. Backward-compatible receivers try both forms.
Development
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest
License
Metadata
Release files for mesh-peer-registry 0.1.10
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 | |
|---|---|---|---|---|
| mesh_peer_registry-0.1.10.tar.gz | 36.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mesh_peer_registry-0.1.10-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.2 kB
Release files / mesh_peer_registry-0.1.10.tar.gz
| Download URL | mesh_peer_registry-0.1.10.tar.gz |
|---|---|
| Size | 36.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
47e612a9748fa7905d1415c529294d4887a1c2cc99c2d346beb0ca867aeb3d08
|
|
BLAKE2b-256 checksum How to use checksums |
9661d3d792b7c3f7be4cf1ae705814891cbf04432a88fe530fab8792382e2f3d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / mesh_peer_registry-0.1.10-py3-none-any.whl
| Download URL | mesh_peer_registry-0.1.10-py3-none-any.whl |
|---|---|
| Size | 35.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
35ebd7f63cad2f74d60fd981140b744e7bae64bdf939f1a6d5690a7834d4bc48
|
|
BLAKE2b-256 checksum How to use checksums |
3c3ba705a62e8a7323764c839a002292d95bf9963e678d1fd8a450d39e2df7b6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Security for mesh-peer-registry 0.1.10
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.