# OpenHuman Memory Engine Architecture: Understanding tinymemory-api, tinymemory, tinymemory-core, and tinycortex

> Explore the OpenHuman memory engine's architecture: tinymemory-api, tinymemory, tinymemory-core, and tinycortex. Understand this type-safe, persistent knowledge store.

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

---

**The OpenHuman memory engine comprises four layered Rust crates—tinymemory-api for the wire contract, tinymemory for the host façade, tinymemory-core for the storage engine, and tinycortex for graph-centric operations—that together provide a type-safe, persistent knowledge store.**

The OpenHuman repository implements a **contract-first** memory subsystem designed for extensibility and runtime flexibility. At the heart of this system are four specialized crates that separate interface definitions from implementation details. This architecture enables the core application to swap storage backends while maintaining type-level compatibility across native and dynamic module boundaries.

## The Four Core Components

The memory stack organizes functionality into distinct layers, each with specific responsibilities and locations within the codebase.

### tinymemory-api: The Wire Contract

**tinymemory-api** serves as the canonical source of truth for all types, errors, and RPC surfaces exchanged between the core process and memory modules. Located in [`src/openhuman/memory/api.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api.rs) and vendored at `vendor/tinymemory/`, this crate ensures that no other component redefines shared structures.

The contract defines fundamental types including `Chunk`, `Capabilities`, `MemoryError`, and `Provider`. It enforces version negotiation through the `CONTRACT_VERSION` constant, allowing the runtime to detect incompatible modules before executing operations. The core crate uses `pub use tinymemory_api::*` to import these definitions, guaranteeing that the host and any loaded modules speak the same language at the type level.

### tinymemory: The Host-Side Façade

**tinymemory** acts as the host-side implementation that exposes the contract to the rest of the application. The implementation resides in [`src/openhuman/memory/host_impls.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host_impls.rs) and the vendored submodule `vendor/tinymemory`, where it instantiates the concrete engine and handles host-specific concerns like configuration parsing and key-ring access.

This crate provides the `MemoryProvider` trait implementation that the OpenHuman runtime calls. When the system initializes, [`src/openhuman/memory/host.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs) constructs the provider using `MemoryEngine::new`, bridging the high-level contract to the low-level core. The façade also supplies a default "null" provider when no memory module is loaded, ensuring the application starts gracefully even without persistent storage.

### tinymemory-core: The Storage Engine

**tinymemory-core** contains the actual engine responsible for persisting, indexing, and serving chunks, goals, documents, and other artifacts. Deliberately dependency-free except for `serde` and `tokio`, this crate lives in `vendor/tinymemory/crates/tinymemory-core` and can be compiled into both the core binary and a dynamic module (`tinymemory-module`).

The engine implements `ChunkStore` for persistence and `MemoryGraph` for queries. It exposes low-level APIs including `read_chunk`, `write_chunk`, and `list_chunks` that the contract layers invoke. Direct usage appears in the test file [`src/openhuman/memory/direct_engine_refs_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/direct_engine_refs_tests.rs), which demonstrates instantiating `MemoryEngine` and performing raw chunk operations without the RPC layer.

### tinycortex: The Graph-Centric Wrapper

**tinycortex** provides a high-level, hierarchical view of memory as a directed acyclic graph. Shipped as a separate vendored crate at `vendor/tinycortex`, it builds on top of `tinymemory-core` to offer semantic enrichment and traversal capabilities. The goals domain in [`src/openhuman/memory/goals/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/goals/mod.rs) imports this crate to implement goal-oriented memory features.

This component represents stored knowledge as a DAG and supplies utilities like `add_goal` and `enrich_goal` for building hierarchical structures. It performs fast similarity searches and graph traversals that sit atop the raw chunk storage, allowing higher-level domains to reason about relationships rather than individual bytes.

## How the Components Interact

The architecture follows a strict layering principle that guarantees type-level compatibility and runtime flexibility.

1. **Contract Layer**: All RPC calls from the UI or external agents travel through JSON-RPC payloads defined by `tinymemory-api`, such as the `ReadChunkInput` struct.

2. **Host Façade**: [`src/openhuman/memory/host.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs) and [`host_impls.rs`](https://github.com/tinyhumansai/openhuman/blob/main/host_impls.rs) expose a `MemoryProvider` implementation that satisfies the contract. This provider validates incoming requests against the `CONTRACT_VERSION` before forwarding them.

3. **Engine Execution**: The provider delegates storage operations to `tinymemory-core`, which manages on-disk data structures. Because the core is pure Rust, the system can also load it as a dynamic `tinymemory-module` through the plugin system.

4. **Graph Operations**: Higher-level domains import `tinycortex` to obtain a graph view of stored chunks. These domains call back into the provider for raw chunk operations while maintaining their own semantic indices.

## Practical Implementation Examples

### Creating a Memory Provider at Startup

To initialize the memory subsystem, the application loads configuration and constructs the provider through the host façade:

```rust
use openhuman::memory::{host::MemoryHost, MemoryProvider};
use openhuman::memory::api::ProviderConfig;

// Load configuration from the OpenHuman TOML file
let cfg = ProviderConfig::load_or_init_with_env_lookup()?;

// Build the in-process provider – this uses the tinymemory façade
let provider: Box<dyn MemoryProvider> = MemoryHost::new(cfg)?.into_provider();

```

*Source*: [`src/openhuman/memory/host.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs)

### Writing a Chunk via the Contract API

The following example demonstrates creating and storing a chunk through the contract layer:

```rust
use openhuman::memory::api::{WriteChunkInput, Chunk};
use openhuman::memory::ops::provider::write_chunk;

// Create a chunk (the raw data the engine stores)
let chunk = Chunk {
    id: "doc-123".into(),
    content: b"Hello, world!".to_vec(),
    metadata: Default::default(),
    ..Default::default()
};

let input = WriteChunkInput {
    chunk,
    ..Default::default()
};

let result = write_chunk(&provider, input).await?;
println!("Stored chunk with version {}", result.version);

```

*Source*: [`src/openhuman/memory/ops/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/ops/provider.rs)

### Direct Engine Access for Low-Level Operations

For scenarios requiring bypass of the RPC layer, you can interact directly with `tinymemory-core`:

```rust
use tinymemory_core::engine::MemoryEngine;
use tinymemory_core::chunk::ChunkId;

// Assume we have a `MemoryEngine` already constructed (e.g. from tests)
let engine = MemoryEngine::open("/tmp/openhuman_memory")?;
let id = ChunkId::new("doc-123");

// Direct engine call – bypasses the contract layer
let chunk = engine.read_chunk(&id).await?;
println!("Chunk payload: {}", String::from_utf8_lossy(&chunk.content));

```

*Source*: [`src/openhuman/memory/direct_engine_refs_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/direct_engine_refs_tests.rs)

### Adding Goals with TinyCortex

Working with hierarchical goals requires the graph-oriented API provided by TinyCortex:

```rust
use tinycortex::graph::Graph;
use openhuman::memory::goals::ops::enrich::enrich_goal;

// Build a TinyCortex graph backed by the same storage directory
let graph = Graph::open("/tmp/openhuman_memory")?;

// Create a new goal node
let goal_id = graph.add_node("plan-trip", None)?;

// Run the enrichment tool which may add related documents, locations, etc.
enrich_goal(&graph, goal_id).await?;

```

*Source*: [`src/openhuman/memory/goals/enrich.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/goals/enrich.rs)

## Summary

- **tinymemory-api** establishes the contract layer in [`src/openhuman/memory/api.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api.rs), defining shared types like `Chunk` and `MemoryError` to prevent drift between host and module implementations.
- **tinymemory** provides the host-side façade through [`src/openhuman/memory/host_impls.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host_impls.rs), connecting the contract to the concrete engine while handling configuration and lifecycle management.
- **tinymemory-core** delivers the dependency-free storage engine at `vendor/tinymemory/crates/tinymemory-core`, implementing raw persistence and retrieval operations via `ChunkStore` and `MemoryGraph`.
- **tinycortex** offers graph-centric abstractions over the core engine, enabling hierarchical goal management and semantic traversals in higher-level domains like `src/openhuman/memory/goals/`.

## Frequently Asked Questions

### What is the purpose of separating tinymemory-api from the implementation crates?

The separation ensures **type-level compatibility** across the entire memory stack. By defining all structs, errors, and RPC signatures in `tinymemory-api`, both the host process and any dynamically loaded modules import identical definitions from [`src/openhuman/memory/api.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api.rs). This prevents versioning conflicts that would occur if the host and module defined `Chunk` or `MemoryError` independently.

### Can tinymemory-core run independently of the OpenHuman host process?

Yes, `tinymemory-core` is deliberately designed with minimal dependencies—only `serde` and `tokio`—allowing it to compile as a standalone dynamic module (`tinymemory-module`) or run embedded in the host. The test file [`src/openhuman/memory/direct_engine_refs_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/direct_engine_refs_tests.rs) demonstrates direct instantiation of `MemoryEngine` without the surrounding OpenHuman runtime, proving the core crate operates independently.

### How does tinycortex differ from the raw storage provided by tinymemory-core?

While `tinymemory-core` handles byte-level persistence through `read_chunk` and `write_chunk`, **tinycortex** adds a semantic layer that treats memory as a directed acyclic graph. Located in `vendor/tinycortex`, it provides goal-oriented APIs like `add_goal` and `enrich_goal` that [`src/openhuman/memory/goals/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/goals/mod.rs) uses to build hierarchical knowledge structures atop the raw chunk storage.

### Where is the version compatibility check implemented between the host and memory modules?

The `CONTRACT_VERSION` constant defined in `tinymemory-api` enables runtime version negotiation. When [`src/openhuman/memory/host.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs) initializes a provider via `MemoryHost::new`, it validates that any loaded module adheres to the contract version exposed through [`src/openhuman/memory/api.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api.rs), ensuring API compatibility before accepting RPC calls.