# How the OpenHuman Memory Module Interacts with tinymemory-api: Architecture and Implementation Guide

> Discover how the OpenHuman memory module interacts with tinymemory-api for persistent storage and vector operations. Explore architecture and implementation details.

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

---

**The OpenHuman memory module delegates all persistent storage and vector operations to the TinyMemory runtime via the `tinymemory-api` contract, using a host-provider shim and runtime provider selection to bridge the core application with dynamically loaded modules.**

The OpenHuman project ([tinyhumansai/openhuman](https://github.com/tinyhumansai/openhuman)) separates long-term data concerns from core orchestration logic by implementing a strict **contract-first** architecture. Rather than embedding storage engines directly, the **memory module** communicates with an external TinyMemory runtime through shared types defined in **tinymemory-api**, ensuring compile-time safety across process boundaries while supporting graceful degradation when modules are unavailable.

## The Contract-First Architecture

At the foundation of this interaction lies the `tinymemory-api` crate, which acts as the single source of truth for all data structures and traits shared between the host application and the TinyMemory module.

### Defining the tinymemory-api Contract

The vendored crate at [[`vendor/tinymemory/crates/tinymemory-api/src/lib.rs`](https://github.com/tinyhumansai/openhuman/blob/main/vendor/tinymemory/crates/tinymemory-api/src/lib.rs)](https://github.com/tinyhumansai/openhuman/blob/main/vendor/tinymemory/crates/tinymemory-api/src/lib.rs) defines the wire protocol for memory operations. This includes core types such as `Chunk`, `Metadata`, `SourceKind`, and the `MemoryProvider` trait that both sides must implement. By centralizing these definitions in a dedicated crate, the system guarantees that the host and any loaded module agree on struct layouts, enum variants, and serialization formats.

[[`src/openhuman/memory/api/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api/mod.rs)](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api/mod.rs) re-exports these types under the `openhuman::memory::api` namespace. This indirection prevents the core codebase from depending directly on vendored paths while ensuring that all memory-related components consume identical type definitions.

## Host-to-Module Communication Bridge

The transition from the OpenHuman core to the TinyMemory runtime occurs through a thin shim that implements the contract on the host side and forwards operations over the **TinyBus** interface.

### The ModuleMemoryProvider Shim

[[`src/openhuman/memory/host.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs)](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs) contains the `ModuleMemoryProvider` implementation, which satisfies the `MemoryProvider` trait from `tinymemory-api` on behalf of the core. When the core invokes storage operations—such as `upsert_chunk` or `search`—this shim serializes the requests and forwards them to the dynamically loaded TinyMemory module over the bus. The shim also provides host-side fallback implementations, including **NoopEmbedding**, which ensures the core remains functional even when the module is absent.

### Runtime Provider Selection

[[`src/openhuman/memory/ops/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/ops/provider.rs)](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/ops/provider.rs) handles the selection of the active provider at startup. If the `modules` feature is enabled and the TinyMemory CDylib loads successfully, the system instantiates the module-backed provider; otherwise, it falls back to `NoopMemoryProvider`. This logic ensures that `memory::query` calls resolve to a valid implementation regardless of the runtime configuration.

## Module Registration and Loading

Before any communication can occur, the TinyMemory module must be registered and loaded into the process. [[`src/openhuman/modules/registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/registry.rs)](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/registry.rs) manages the lifecycle of loadable modules, verifying checksums and resolving artifacts for the TinyMemory runtime. Once loaded, the module exposes a bus interface implementing the same `tinymemory-api` traits, allowing the `ModuleMemoryProvider` to call it transparently without knowing implementation details.

## Working with Memory Operations

All high-level memory interactions—whether querying chat history or upserting documents—flow through the public API in [[`src/openhuman/memory/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/mod.rs)](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/mod.rs), which internally delegates to the selected provider using `tinymemory-api` types.

The following example demonstrates performing a vector search using the public query interface:

```rust
use openhuman::memory::api::{Chunk, Metadata, SourceKind};

// Search for entities across specific source types
let results = openhuman::memory::query::search_entities(
    "project requirements",
    10, // limit
    vec![SourceKind::Chat, SourceKind::Document],
).await?;

// Inspect returned chunks using the shared contract types
for chunk in results {
    println!("Found chunk {} with {} bytes", chunk.id, chunk.content.len());
}

```

For scenarios requiring direct provider access, you can interact with the underlying implementation:

```rust
use openhuman::memory::ops::provider::get_provider;
use openhuman::memory::api::{Chunk, Metadata, SourceKind};

// Obtain the active provider (module-backed or fallback)
let provider = get_provider();

// Construct a new chunk using contract types
let chunk = Chunk {
    id: "chunk-001".into(),
    content: b"Meeting notes...".to_vec(),
    metadata: Metadata {
        source_kind: SourceKind::Chat,
        ..Default::default()
    },
    ..Default::default()
};

// Persist through the provider interface
provider.upsert_chunk(chunk)?;

```

These operations compile against the same `Chunk` and `Metadata` definitions used by the TinyMemory module, ensuring that data serialized by the host deserializes correctly on the module side.

## Summary

- The **tinymemory-api** crate defines the contract types (e.g., `Chunk`, `SourceKind`, `MemoryProvider`) shared between OpenHuman and the TinyMemory runtime.
- **[`src/openhuman/memory/api/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api/mod.rs)** re-exports these types to create a unified import surface for the memory domain.
- **[`src/openhuman/memory/host.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs)** implements `ModuleMemoryProvider`, forwarding host calls to the loaded module over the TinyBus while providing no-op fallbacks.
- **[`src/openhuman/memory/ops/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/ops/provider.rs)** selects the concrete provider at runtime, choosing between the module implementation and a fallback based on availability.
- **[`src/openhuman/modules/registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/modules/registry.rs)** handles the loading and verification of the TinyMemory CDylib, registering it for host communication.
- All public memory APIs in **[`src/openhuman/memory/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/mod.rs)** operate on `tinymemory-api` types, ensuring type safety across the host-module boundary.

## Frequently Asked Questions

### What is tinymemory-api in the OpenHuman architecture?

**tinymemory-api** is the vendored Rust crate that defines the public wire protocol and data structures (such as `Chunk`, `Metadata`, and `MemoryProvider`) shared between the OpenHuman core and the TinyMemory runtime. It serves as the compile-time contract that ensures both sides agree on serialization formats and trait implementations, preventing runtime errors due to mismatched data layouts.

### How does the OpenHuman core communicate with the TinyMemory module?

The core communicates through the **ModuleMemoryProvider** shim located in [`src/openhuman/memory/host.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs). This structure implements the `MemoryProvider` trait from `tinymemory-api` on the host side and forwards method calls—such as `get_chunks` or `upsert_chunk`—to the dynamically loaded TinyMemory module via the TinyBus RPC interface. This abstraction allows the core to treat remote module calls as local trait method invocations.

### What happens if the TinyMemory module fails to load or is unavailable?

If the module fails checksum verification, cannot be loaded, or when the `modules` feature is disabled, **[`src/openhuman/memory/ops/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/ops/provider.rs)** falls back to `NoopMemoryProvider`. This fallback implements the `MemoryProvider` trait with no-op or empty-return implementations, ensuring the core application continues to function without crashing, albeit without persistent memory capabilities.

### Why does the memory module re-export types from tinymemory-api instead of using them directly?

**[`src/openhuman/memory/api/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api/mod.rs)** re-exports `tinymemory-api` types to create a stable, semantic namespace (`openhuman::memory::api`) that is decoupled from the physical vendored path. This pattern allows the core to depend on a logical interface rather than the specific crate location, simplifying future refactors and ensuring that all memory-related components consume identical type definitions from a single authority.