How OpenHuman's Memory Subsystem Interacts with TinyCortex and the Module Seam
OpenHuman's memory subsystem delegates all storage and retrieval operations to TinyCortex through a contract-first architecture defined by the tinymemory-api crate, using TinyBus for in-process communication across the module seam while keeping the core binary free of heavy native dependencies.
The tinyhumansai/openhuman repository implements a modular memory architecture that separates the core engine from storage implementations. This design enables the OpenHuman memory subsystem to communicate with TinyCortex exclusively through a well-defined contract, reducing binary size and improving system resilience. By routing all memory operations through the module seam, the system maintains high performance without embedding the full TinyCortex engine in the product binary.
Contract-First Architecture with tinymemory-api
The foundation of the memory subsystem relies on tinymemory-api, a standalone contract crate that defines the wire-format types crossing the module boundary. Located in src/openhuman/memory/api.rs, this crate re-exports critical types including Chunk, MemoryError, and Capabilities that both the core process and native modules use to communicate.
Because the core does not embed the TinyCortex engine directly, it instead hosts a lightweight module host that serializes memory calls into TinyBus protocol requests. Every operation—whether list_chunks, retrieve, or store—becomes a bus::call annotated with the contract version. This separation ensures the core and memory modules compile independently; type mismatches surface at compile time rather than runtime.
The Module Seam and ModuleMemoryProvider
When OpenHuman requires memory backend functionality, it instantiates a ModuleMemoryProvider defined in src/openhuman/modules/memory.rs. This provider manages the complete lifecycle of the memory module interaction.
Module Loading and Verification
The loading process begins in src/openhuman/modules/registry.rs, where the registry selects a release-verified native library (.so or .dylib) implementing the tinymemory contract. Each release pins a specific SHA-256 digest to prevent tampering or version drift.
Handshake and Bus Initialization
Upon loading, the module advertises its contract version through a handshake protocol. The core validates this against tinymemory-api::CONTRACT_VERSION before establishing communication. A TinyBus broker initializes per process via OnceBus::init_in_process(), providing the provider with a BusHandle for serving calls.
Call Routing and Fault Isolation
All memory requests route through bus::call("tinymemory", …), invoking handlers like list_chunks, store_chunk, or retrieve within the module. Because the module runs in-process, latency remains minimal while the bus architecture isolates failures. Panics inside the module convert to MemoryError::ModuleFailed, allowing the core to continue operating. If loading fails entirely, the system falls back to a null provider that returns empty results rather than crashing.
TinyCortex Migration and Current Relationship
Historically, TinyCortex functioned as tinymemory-core, embedded directly within the binary. The 2026-08-31 migration documented in docs/tinycortex-migration-spec.md extracted this engine into a native module, transforming it into a dev-dependency used only for testing.
Architectural Rationale
The migration removed approximately 1MiB of native dependencies including SQLite and cryptographic libraries from the product binary. Users who require full memory capabilities enable the memory feature, which loads the TinyCortex module at runtime; otherwise, the null provider maintains system operation.
Parity Verification
To ensure the module matches original engine capabilities, the repository maintains docs/tinycortex-parity-checklist.md. This CI-driven checklist verifies contract-exposed APIs support identical functionality—including chunk pagination and embedding retrieval—guaranteeing the module seam serves as a drop-in replacement.
Practical Implementation Examples
The following examples demonstrate interacting with the memory subsystem through its public API.
Retrieving recent chunks routes through the provider to TinyCortex:
use openhuman::memory::api::{Chunk, MemoryError};
use openhuman::memory::ops::list_chunks;
async fn recent_chunks() -> Result<Vec<Chunk>, MemoryError> {
// Routes through ModuleMemoryProvider to TinyBus
list_chunks().await
}
Storing document content follows the same contract path:
use openhuman::memory::ops::store_chunk;
use openhuman::memory::api::{Chunk, StoreChunkRequest};
async fn ingest_document(text: &str) -> Result<Chunk, MemoryError> {
let request = StoreChunkRequest {
content: text.into(),
..Default::default()
};
// Invokes the module's store_chunk handler via bus::call
store_chunk(request).await
}
Summary
- OpenHuman's memory subsystem operates exclusively through the
tinymemory-apicontract crate, ensuring type safety across the core-module boundary. - The
ModuleMemoryProviderinsrc/openhuman/modules/memory.rsmanages TinyCortex integration via TinyBus, loading verified native modules fromsrc/openhuman/modules/registry.rs. - TinyCortex migrated from embedded engine to optional native module in August 2026, reducing core binary size by approximately 1MiB while maintaining functionality through the module seam.
- Fault isolation via TinyBus converts module panics to
MemoryError::ModuleFailed, with automatic fallback to a null provider if the module fails to load. - The architecture supports independent versioning, allowing TinyCortex updates without core recompilation beyond updating the pinned SHA-256 digest.
Frequently Asked Questions
What is the module seam in OpenHuman?
The module seam is the architectural boundary separating the OpenHuman core from native module implementations. It consists of the contract definitions in tinymemory-api, the TinyBus communication protocol, and the ModuleMemoryProvider that routes calls to loaded native libraries. This seam allows heavy dependencies like TinyCortex to reside outside the product binary while maintaining in-process performance characteristics.
How does TinyBus isolate memory module failures?
TinyBus creates a broker per process using OnceBus::init_in_process() that wraps module calls in isolation boundaries. When the TinyCortex module panics during operations like retrieve or store_chunk, the broker catches the panic and translates it into a MemoryError::ModuleFailed response. This mechanism prevents memory engine crashes from terminating the OpenHuman core process.
Why was TinyCortex removed from the core binary?
The TinyCortex engine was extracted from the core binary during the August 2026 migration to eliminate approximately 1MiB of native dependencies including SQLite and cryptographic libraries. Moving TinyCortex to a loadable module reduces the base binary size and allows users to optionally enable memory functionality through the memory feature flag, while the core can operate with a lightweight null provider when memory features are disabled.
Can third-party modules implement the memory contract?
Yes, any native module implementing the tinymemory-api contract types and responding to standard TinyBus calls like list_chunks and store_chunk can serve as the memory backend. The src/openhuman/modules/registry.rs component loads modules based on SHA-256 verification, meaning third-party implementations must be registered and pinned in the registry to be recognized by the ModuleMemoryProvider.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →