# How OpenHuman Implements Signal Protocol for E2E Agent-to-Agent Communication in tiny.place

> Discover how OpenHuman implements Signal protocol for E2E agent-to-agent communication in tiny.place. Learn about its Rust session store and double-ratchet encryption.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: internals
- Published: 2026-08-27

---

**OpenHuman wires the Signal protocol for E2E agent-to-agent communication in tiny.place by combining a durable Rust session store with RPC handlers that execute double-ratchet encryption and decryption.**

The `tinyhumansai/openhuman` repository implements **Signal protocol E2E agent-to-agent communication** using the double-ratchet algorithm in the tiny.place domain. This architecture isolates cryptographic state in dedicated storage while exposing a thin `SignalSession` API for seamless integration with the OpenHuman backend.

## Core Components of the Signal Integration

### Persistent Session Storage in [`signal_store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/signal_store.rs)

The foundation of OpenHuman's Signal protocol implementation resides in [`src/openhuman/tinyplace/signal_store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tinyplace/signal_store.rs), which provides the `FileSessionStore` struct. This durable, file-backed store maintains each agent's long-term identity key pair, pre-keys, and per-session state in a format consumable by the Signal double-ratchet.

The `FileSessionStore::new` constructor initializes the storage directory and warms the cache for fast lookups. For global access across the process, the module exposes `global_signal_store` helpers that provide a singleton pattern for the session store.

### The SignalSession Wrapper

OpenHuman utilizes the `SignalSession` type from the `tinyplace::signal::session` module (provided by the tinyplace crate) as the high-level cryptographic interface. Each session is instantiated with an identity key—typically an X25519 public key—and a reference to the `FileSessionStore`.

The session object exposes `encrypt` and `decrypt` methods that execute the double-ratchet forward-secure operations. When creating a new session, the code uses `SignalSession::new(my_identity_key, Arc::new(store))` to bind the cryptographic state to the durable storage backend.

## Message Flow and RPC Handlers in [`manifest.rs`](https://github.com/tinyhumansai/openhuman/blob/main/manifest.rs)

The integration point between the Signal protocol and OpenHuman's RPC system lives in [`src/openhuman/tinyplace/manifest.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tinyplace/manifest.rs). This file contains the handlers that expose Signal messaging to the rest of the system through JSON-RPC endpoints defined in [`src/openhuman/tinyplace/schemas.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tinyplace/schemas.rs).

### Sending Encrypted Messages

When an agent initiates a "send Signal DM" RPC call, the handler executes the following sequence:

1. Loads the peer's pre-key bundle via the tiny.place key management RPCs
2. Constructs a `SignalSession` using the shared `FileSessionStore` and the local identity key obtained via `decode_identity_key`
3. Invokes `session.encrypt(&peer_prekey_bundle, plaintext)` to generate the ciphertext envelope
4. Hands the encrypted payload to the OpenHuman backend for delivery

### Receiving and Decrypting Messages

Inbound Signal envelopes are processed by the "decrypt Signal DM" RPC handler. This handler:

1. Retrieves the stored session state from the `FileSessionStore`
2. Reconstructs the `SignalSession` using the cached identity key
3. Calls `session.decrypt(&inbound)` to advance the ratchet and recover the plaintext
4. Returns the decrypted payload to the calling agent

## End-to-End Verification

### Testing the Double-Ratchet Implementation

The correctness of the Signal protocol integration is validated in [`src/openhuman/tinyplace/signal_e2e_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tinyplace/signal_e2e_tests.rs). This test suite creates two independent `SignalSession` instances—Alice and Bob—backed by the same `FileSessionStore` to simulate a full local round-trip.

The tests verify that messages encrypted by one side decrypt correctly on the other and confirm that the low-level Signal API interoperates properly with the high-level session wrapper. This ensures that session store persistence, key handling, and double-ratchet state management remain synchronized across encryption and decryption operations.

## Implementation Example

The following Rust code demonstrates the complete workflow for initializing the Signal protocol infrastructure and executing agent-to-agent encryption:

```rust
// 1️⃣ Initialise the durable session store (once per process)
let store = FileSessionStore::new(
    std::path::PathBuf::from("/home/user/.openhuman/tinyplace/signal_store")
).await?;

// 2️⃣ Build a Signal session for the local agent
let my_id_key = my_keypair.public_key; // X25519 public key bytes
let session = SignalSession::new(my_id_key, Arc::new(store));

// 3️⃣ Encrypt a message for a remote agent
let peer_prekey_bundle = fetch_peer_prekey_bundle(peer_crypto_id).await?;
let ciphertext = session.encrypt(&peer_prekey_bundle, b"Hello from Alice!")?;

// 4️⃣ Decrypt an incoming envelope
let inbound = receive_signal_envelope().await?;
let plaintext = session.decrypt(&inbound)?;
assert_eq!(plaintext, b"Hello from Alice!");

```

## Summary

- **OpenHuman** implements **Signal protocol E2E agent-to-agent communication** in tiny.place through a dedicated Rust module combining durable storage and RPC handlers.
- The `FileSessionStore` in [`signal_store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/signal_store.rs) persists identity keys, pre-keys, and session state using a file-backed architecture with singleton access via `global_signal_store`.
- **SignalSession** from the tinyplace crate provides the double-ratchet encryption interface, wrapping the cryptographic operations in `encrypt` and `decrypt` methods.
- RPC handlers in [`manifest.rs`](https://github.com/tinyhumansai/openhuman/blob/main/manifest.rs) orchestrate the message flow, fetching pre-key bundles and managing session lifecycles during send and receive operations.
- The [`signal_e2e_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/signal_e2e_tests.rs) suite validates end-to-end correctness by simulating bidirectional communication between independent session instances.

## Frequently Asked Questions

### How does the FileSessionStore handle key persistence?

The `FileSessionStore` serializes each agent's long-term identity key pair, pre-keys, and per-session state to disk in a format compatible with the Signal double-ratchet. The `FileSessionStore::new` constructor creates the storage directory structure and initializes an in-memory cache for fast lookups, ensuring cryptographic material persists across process restarts while remaining accessible for rapid session reconstruction.

### What encryption algorithm does OpenHuman use for agent messaging?

OpenHuman uses the **Signal double-ratchet protocol** for end-to-end encryption, specifically employing **X25519** elliptic curve keys for identity establishment. The implementation leverages the `tinyplace::signal::session` module to perform forward-secure encryption and decryption operations that automatically advance the ratchet with each message exchange.

### Where are the RPC handlers for Signal messaging defined?

The RPC handlers that manage Signal encryption and decryption are defined in [`src/openhuman/tinyplace/manifest.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tinyplace/manifest.rs). This file implements the "send Signal DM" and "decrypt Signal DM" endpoints, which utilize `decode_identity_key` to extract public keys and coordinate session creation via `SignalSession::new` before calling the cryptographic methods.

### How does OpenHuman verify the Signal protocol implementation?

Verification occurs in [`src/openhuman/tinyplace/signal_e2e_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tinyplace/signal_e2e_tests.rs), where the test suite creates independent `SignalSession` instances representing different agents. These tests confirm that the double-ratchet algorithm correctly encrypts and decrypts messages across distinct sessions while maintaining synchronization with the underlying `FileSessionStore`, ensuring the production implementation matches the Signal protocol specification.