Minimal sync RPC between two AI agents (Python port of @p-vbordei/agent-phone). Self-custody keys, Noise-framework handshake, DID-bound WebSocket.
Project description
agent-phone (Python)
Idiomatic Python port of @p-vbordei/agent-phone. Minimal sync RPC between two AI agents — Noise-XK handshake over WebSocket, DID-bound peer identity, framed binary transport, self-custody keys. Wire-format-identical with the TS reference: the C4 hex vector matches byte-for-byte.
What's in the box
- Noise-XK handshake (X25519 + ChaCha20Poly1305 + BLAKE2s + HKDF)
- DID-bound peer identity (Ed25519 → X25519 via SHA-512 + RFC 7748 clamp)
- Length-prefixed frame transport (ChaChaPoly seal/open)
- WebSocket client + server (
websocketsasyncio) - Session lifecycle (connect, call, stream, close)
- Backpressure (credit-based streaming with auto-refresh at the half-mark)
Install
pip install agent-phone
# or, for development:
uv sync --extra dev
Quickstart
import asyncio
from agent_phone import (
ClientOptions, ServerOptions, connect, create_server,
encode_did_key, generate_key_pair,
)
async def main() -> None:
resp, init = generate_key_pair(), generate_key_pair()
resp_did = encode_did_key(resp.public_key)
server = create_server(ServerOptions(
did=resp_did, private_key=resp.private_key,
handlers={"echo": lambda p: p},
))
await server.listen(0, hostname="127.0.0.1")
port = server.address().port
client = await connect(ClientOptions(
url=f"ws://127.0.0.1:{port}",
did=encode_did_key(init.public_key),
private_key=init.private_key,
responder_did=resp_did,
))
print(await client.call("echo", {"hi": 1})) # {'hi': 1}
await client.close()
await server.close()
asyncio.run(main())
uv run python examples/quickstart.py
# server listening on 127.0.0.1:<port>
# noise-xk handshake complete; channel authenticated
# echo result : {'hello': 'agent-phone'}
# closed cleanly
How it relates
| Implementation | Status | Wire format |
|---|---|---|
@p-vbordei/agent-phone (TypeScript) |
Reference | source of truth |
agent-phone (Python, this repo) |
Port | byte-identical |
agent-phone (Rust) |
Port | byte-identical |
Conformance
The v0.1 spec defines four conformance clauses; all four pass against the TS test suite.
- C1 — Handshake DID-binding. Swap the responder's static mid-handshake → initiator aborts deterministically at message 2 (AEAD fails).
tests/test_conformance.py::test_c1_handshake_did_binding. - C2 — Streaming backpressure. Server emits 10 000 chunks, client grants 8 at a time → outstanding chunks stay bounded; every chunk arrives in order.
test_c2_streaming_backpressure. - C3 — Graceful cancel. Cancel mid-stream → server stops within one frame, session stays open for further RPCs.
test_c3_graceful_cancel. - C4 — Frame determinism. Canonical envelope bytes match the TS hex vector byte-for-byte.
test_c4_frame_determinismreadsvectors/c4.json, which mirrors the TS suite.
uv run pytest -v
# 31 passed
Architecture
Module map, dependency choices (hand-rolled Noise XK on cryptography + manual X25519), Ed25519→X25519 derivation gotcha, byte-determinism invariants, and testing strategy: see docs/architecture.md.
Development
git clone https://github.com/p-vbordei/agent-phone-py
cd agent-phone-py
uv sync --extra dev
uv run pytest -v
uv run ruff check .
Contributions welcome — see CONTRIBUTING.md. Any change to noise.py, frame.py, or envelope.py must keep the C4 hex vector passing; that's the wire-format contract.
License
Apache-2.0 — 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 kindred_agent_phone-0.1.0.tar.gz.
File metadata
- Download URL: kindred_agent_phone-0.1.0.tar.gz
- Upload date:
- Size: 26.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6927b3a878b311918b24bc8ab1cbc0659cd21325a7b9b5df36173b128755302
|
|
| MD5 |
4af521b9d5f2ab9cf0763f41a0eb5088
|
|
| BLAKE2b-256 |
707981718ed9a15848606cb90dc128a5731325a766c07b62d73c2a8343ecaeaf
|
Provenance
The following attestation bundles were made for kindred_agent_phone-0.1.0.tar.gz:
Publisher:
publish.yml on p-vbordei/agent-phone-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kindred_agent_phone-0.1.0.tar.gz -
Subject digest:
d6927b3a878b311918b24bc8ab1cbc0659cd21325a7b9b5df36173b128755302 - Sigstore transparency entry: 1591085795
- Sigstore integration time:
-
Permalink:
p-vbordei/agent-phone-py@f8fefec7ac16caba37cdb4a63d4b0bc9ce32940d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/p-vbordei
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f8fefec7ac16caba37cdb4a63d4b0bc9ce32940d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file kindred_agent_phone-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kindred_agent_phone-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.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 |
547a2559ccdbb54ba717ad9f9f83335f23a5bc016060fac56673229f4ebfe394
|
|
| MD5 |
a9253a435793c43d91ee4184e581fdfa
|
|
| BLAKE2b-256 |
718e815813fd0d06d48f5c53c48ac83348bfabbd61f2436996dbb52d0e5331db
|
Provenance
The following attestation bundles were made for kindred_agent_phone-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on p-vbordei/agent-phone-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
kindred_agent_phone-0.1.0-py3-none-any.whl -
Subject digest:
547a2559ccdbb54ba717ad9f9f83335f23a5bc016060fac56673229f4ebfe394 - Sigstore transparency entry: 1591085803
- Sigstore integration time:
-
Permalink:
p-vbordei/agent-phone-py@f8fefec7ac16caba37cdb4a63d4b0bc9ce32940d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/p-vbordei
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f8fefec7ac16caba37cdb4a63d4b0bc9ce32940d -
Trigger Event:
workflow_dispatch
-
Statement type: