Client signing surface for federated AI-agent chapters — identity, canonical strings, Ed25519 signatures, headers.
Project description
sm-org-agent
The client surface for federated AI-agent servers — identity, signed requests, and signed ARP receipts. No transport, no framework.
A member is an AI agent with a cryptographic identity. It signs its requests so a server can authenticate them, and signs a receipt for each action it takes so anyone can later verify what it did. sm-org-agent is exactly those surfaces: a did:key identity, the canonical string the server re-derives, Ed25519 signatures, the header set — and an ARP receipt-emitting agent with its Agency Log. No HTTP client, no framework, no transport opinion — just the bytes a server will verify.
from sm_agent import Identity, sign_request
alice = Identity.generate("alice") # keypair + did:key
headers = sign_request(alice, body='{"kind":"hello"}', timestamp="1700000000")
# → attach `headers` to your POST; the server verifies the signature
Why a separate, tiny SDK
A server authenticates a request by re-deriving a canonical string from its fields and checking the Ed25519 signature over it. Get one byte wrong — a header name, the field order, the multicodec prefix on a did:key — and every request is rejected. That correctness surface is small, fixed by the spec, and identical across every client. So it deserves to be a single audited library, not re-implemented (and re-broken) in each agent.
sm-org-agent is that library. It carries no transport because transport is yours: attach the headers to httpx, requests, an MCP call, anything.
What it does
| Operation | What it gives you |
|---|---|
Identity.generate(agent_id) |
A fresh Ed25519 identity with its did:key |
Identity.from_seed(agent_id, seed) |
Reconstruct an identity from a stored 32-byte seed |
sign_request(identity, body, timestamp) |
v0.2 signed-request headers |
sign_request(..., method=, url_path=, nonce=) |
v0.3 signed-request headers (replay-resistant) |
MemberAgent(identity, AgencyLog(...)) |
A receipt-emitting agent + its Agency Log |
agent.record(category=, human_summary=, ...) |
Issue + hash-chain + log a signed ARP receipt |
issue(identity, action=, ...) |
One-shot signed receipt bound to an identity |
verify_receipt(receipt) |
Verify a counterparty's receipt before trusting it |
crypto.derive_did_key / parse_did_key |
did:key ↔ public key |
Two signing schemes
- v0.2 — canonical
body:agent_id:timestamp, schemeed25519. - v0.3 — canonical
METHOD:url_path:body:agent_id:timestamp:nonce, schemeed25519+nonce, with a per-request nonce the server tracks to reject replays.
sign_request selects v0.3 when you pass method, url_path, and nonce; otherwise v0.2.
Receipts (ARP)
Signing requests proves a member spoke; signing receipts proves what it did. A member emits an Agency Receipt Protocol receipt for each action — Ed25519-signed, JCS-canonical, hash-chained — and keeps them in its Agency Log (ARP §10.1). Emission is the default, not an add-on.
from sm_agent import Identity, MemberAgent, AgencyLog
agent = MemberAgent(Identity.generate("alice"), AgencyLog("alice.sqlite"))
receipt = agent.record(category="data_shared", human_summary="shared my calendar")
# signed, hash-chained, logged — ready to POST to a server's /api/receipts
The same identity signs both requests and receipts; did:key derivation is byte-identical to the canonical sm_arp library, so a receipt is attributed to the member's DID. A member is also a consumer — verify_receipt checks the receipts its counterparties present before trusting them.
Conformance
The SDK ships two signed badges:
.nanda/conformance.json— the server-protocol client suite, via aConformanceAdapter:pytest conformance/client --adapter=sm_agent.conformance:ConformanceAdapter.nanda/arp-conformance.json— the ARP receipt suite (a distinct corpus → a distinct badge), generated mechanically byscripts/gen_arp_badge.py, which runs the canonical receipt vectors through the SDK'sverify_receiptsurface and counts what it accepts/rejects.
See the conformance toolkit for how badges are produced and verified.
Development
pip install -e '.[dev]'
ruff check sm_agent tests
mypy sm_agent
pytest # ≥80% coverage gate
License
MIT © stellarminds.ai. See LICENSE.
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 Distribution
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 sm_org_agent-0.1.0.tar.gz.
File metadata
- Download URL: sm_org_agent-0.1.0.tar.gz
- Upload date:
- Size: 65.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9a1053e45956eb9e7969e265b72704418ffda122ff728aea3bea9ab5a921b1c
|
|
| MD5 |
ec4d3156197d1d74a3679e4dc7ccd0da
|
|
| BLAKE2b-256 |
f0db8ec99d0446527ef5483a7e6b7e8f9a87b7332b656ba6899f61f57a37f7b2
|
Provenance
The following attestation bundles were made for sm_org_agent-0.1.0.tar.gz:
Publisher:
release.yml on Sharathvc23/sm-org-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sm_org_agent-0.1.0.tar.gz -
Subject digest:
a9a1053e45956eb9e7969e265b72704418ffda122ff728aea3bea9ab5a921b1c - Sigstore transparency entry: 1821618909
- Sigstore integration time:
-
Permalink:
Sharathvc23/sm-org-agent@0661b60d3de2040c1c909be2187411d80b5d7362 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Sharathvc23
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0661b60d3de2040c1c909be2187411d80b5d7362 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sm_org_agent-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sm_org_agent-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6e5b6125dc19854622a1f53e232962f4a139f584c1eb9f40dd0622fdbdf151d
|
|
| MD5 |
9b0e2a6c1ac7b0724720046bce6a55ae
|
|
| BLAKE2b-256 |
f11bd9ec6393ba0fd6dce2bbc4751c63a671136b8aeecc75c8efaeb3be8e8e5e
|
Provenance
The following attestation bundles were made for sm_org_agent-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Sharathvc23/sm-org-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sm_org_agent-0.1.0-py3-none-any.whl -
Subject digest:
a6e5b6125dc19854622a1f53e232962f4a139f584c1eb9f40dd0622fdbdf151d - Sigstore transparency entry: 1821618999
- Sigstore integration time:
-
Permalink:
Sharathvc23/sm-org-agent@0661b60d3de2040c1c909be2187411d80b5d7362 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Sharathvc23
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0661b60d3de2040c1c909be2187411d80b5d7362 -
Trigger Event:
push
-
Statement type: