Skip to main content
Give each device (phone, laptop, desktop app) its own keypair so the gateway can tell them apart, revoke one without rotating everyone, and reject anyone who claims another device’s id.
Only the core wire contract has shipped (PR #6001). Ed25519 signature verification, the device store, per-device tokens and a praisonai devices CLI belong to the wrapper gateway and are not yet shipped — track issue #5998 for the roadmap. Until then, core only fixes the wire shape, the fingerprint and the exact signed bytes.

Quick Start

1

Compute the device id

The device id is the hex SHA-256 of the decoded public-key bytes — never a value the client picks.
2

Sign the challenge

Build a DeviceAuth, take its canonical signing_payload(agent_id) bytes, and sign them. Ed25519 is recommended; core does not pin a signature library.
3

Send hello with the device block


How It Works

The shape and fingerprint checks live in the core frame codec; challenge issuance and verify are the wrapper seam that has not shipped yet.

Wire Contract

DeviceAuth

Signing payload

Clients in any language must render exactly these UTF-8 bytes, joined by \n with no trailing newline:
Self-check against the pinned vectors from the SDK test suite:

Rejection matrix


DeviceIdentityProtocol seam

Core defines the seam; the wrapper gateway (praisonai-bot) implements it. It is runtime_checkable, so any object with these four methods counts — handy for tests and custom stores.
Implementations must approve only on an exact device-key match — never on network reachability alone.

Why this exists

  • A shared auth_token, magic link or signed cookie leaks the whole gateway at once; a per-device key lets you revoke one lost phone.
  • device_id is a cryptographic fingerprint of the public key, not something the client picks, so a client can never claim another device’s id.
  • The signing payload binds nonce + device_id + signed_at + agent_id, so a captured proof can’t be replayed for another device or agent.

Best Practices

Unpadded, URL-safe, or whitespace-wrapped values are rejected as a shape error.
The signing payload uses str(int(signed_at)); a float or boolean renders different bytes in every client language and will not verify.
Always compute it with device_id_from_public_key(public_key) or an equivalent SHA-256 of the raw key bytes.
The core handshake treats an absent device block exactly as before.

Gateway Handshake Protocol

The hello frame that carries the device block

Operator Scopes

Pairing / approvals scope

Bot Pairing

Human-readable pairing codes — the complement to a device key

Error Handling

Structured connect errors