# OpenHuman Memory Management: Understanding Memory Tree, Obsidian Sync, and TinyMemory

> Explore OpenHuman memory management with Memory Tree, Obsidian Sync, and TinyMemory. Unify AI content into a virtual Memory Tree backed by TinyMemory, sync to Obsidian via RPC.

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

---

**OpenHuman memory management unifies AI-generated content into a virtual Memory Tree backed by the TinyMemory engine, with optional two-way synchronization to Obsidian vaults via background RPC pipelines.**

OpenHuman memory management serves as the persistent backbone for the `tinyhumansai/openhuman` project, storing every AI interaction in a hierarchical structure that bridges local storage and external knowledge bases. The architecture combines a virtual **Memory Tree** with the **TinyMemory** versioned key-value engine, while providing seamless **Obsidian sync** capabilities for users who prefer markdown-based knowledge management.

## Memory Tree Architecture

The Memory Tree presents a unified "file-system-like" namespace that aggregates multiple specialized storage domains. Rather than storing files directly, it maintains a virtual hierarchy over documents, chunks, goals, and people data.

### Virtual Hierarchy and Domain Stores

Each data type registers with the central `DomainSet` in [`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs), allowing the tree to materialize paths on demand. Domain-specific stores handle concrete persistence for their respective data types:

- **Documents** → `store::documents`
- **Chunks** → `store::chunks`
- **Goals** and **People** → dedicated schema stores

The public façade in [`src/openhuman/memory/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/mod.rs) routes queries to appropriate sub-modules without requiring core-wide refactoring when adding new domains.

### TinyMemory Engine

All domains ultimately persist through the **TinyMemory** engine, a versioned key-value store vendored at `vendor/tinymemory/crates/tinymemory-core`. This engine provides atomic writes and transactional batch updates while maintaining a minimal footprint.

The contract crate `tinymemory-api` defines the wire protocol including `MemoryProvider`, `Chunk`, and `Error` types. [`src/openhuman/memory/api.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api.rs) re-exports these definitions to guarantee type consistency between the core and dynamically loaded modules:

```rust
// src/openhuman/memory/api.rs
pub use tinymemory_api::*;

```

### Tree Runtime Operations

The **Tree Runtime** in [`src/openhuman/memory/tree/tree_runtime/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/tree/tree_runtime/ops.rs) implements operations such as `list`, `read`, and `sync`. These operations resolve virtual paths to physical storage locations and expose an RPC interface for tooling integration.

## Obsidian Vault Integration

OpenHuman can treat the Memory Tree as an **Obsidian vault**, enabling users to browse AI-generated content in Obsidian while the system maintains bidirectional synchronization.

### Vault Detection Logic

Detection begins in [`src/openhuman/memory/obsidian_registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/obsidian_registry.rs), which walks the filesystem searching for [`obsidian.json`](https://github.com/tinyhumansai/openhuman/blob/main/obsidian.json) files. The system checks whether the content root (defaulting to `~/OpenHuman/projects`) or any ancestor directory appears in the Obsidian registry:

```rust
// src/openhuman/memory/obsidian_registry.rs
pub fn is_registered_vault(
    content_root: &Path, 
    extra_config_dir: Option<&Path>
) -> Result<bool, std::io::Error> {
    // …search for obsidian.json, parse, compare paths…
}

```

Users may specify an override via the `extra_config_dir` parameter to support non-standard Obsidian installations.

### RPC Endpoints and UI Integration

The `obsidian_vault_status` endpoint in [`src/openhuman/memory/read_rpc/vault.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/read_rpc/vault.rs) returns structured status information enabling the React UI to render "Open in Obsidian" buttons:

```rust
// src/openhuman/memory/read_rpc/vault.rs
pub async fn obsidian_vault_status(
    ctx: &mut RpcContext,
) -> Result<RpcOutcome<ObsidianVaultStatusResponse>, String> {
    // …spawn blocking task that calls is_registered_vault…
}

```

When a vault is detected, the UI generates deep-links using the `obsidian://open?path=` protocol with the absolute vault path returned by the registry.

### Auto-Sync Pipeline

Background synchronization is controlled by the `memory_tree_auto_sync` platform setting. When enabled, the **Memory Sync** service ([`src/openhuman/memory/sync/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/sync/mod.rs)) periodically executes the `memory_tree_sync_status` RPC defined in [`src/openhuman/memory/sync/sync_status/rpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/sync/sync_status/rpc.rs). This aggregates health information from all sub-domains—including paused states, error flags, and job counters—into a compact payload for UI consumption.

## TinyMemory Storage Implementation

The **TinyMemory** engine provides the foundational persistence layer for all memory operations. It stores versioned chunks optimized for append-heavy AI conversation patterns.

### Contract and Type Safety

Type safety across module boundaries is enforced through the `tinymemory-api` contract crate. By re-exporting these types in [`src/openhuman/memory/api.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api.rs), the system ensures that modules compiled against the contract can load at runtime without type mismatches, preventing serialization errors between the core and extensions.

### MemoryHost Wrapper

The `MemoryHost` struct in [`src/openhuman/memory/host.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/host.rs) provides high-level helpers for the core:

- `write_chunk`: Atomic single-record writes
- `read_chunk`: Version-aware retrieval
- Transaction-style batch updates for multi-domain consistency

## End-to-End Sync Pipeline

The complete data flow from external sources to Obsidian follows four stages:

1. **Source Ingestion**: Connectors (Composio, ClickUp, Slack) push data via RPC controllers in `src/openhuman/memory/sync/composio/*`
2. **Tree Updates**: The event bus notifies the Tree Runtime of store-level changes, updating the virtual hierarchy
3. **Health Aggregation**: The sync status RPC collates per-domain health flags
4. **Deep Link Generation**: If a vault is registered, the UI constructs `obsidian://` URLs for instant navigation

All operations are asynchronous and governed by the **agent-policy** system, ensuring background sync never blocks user-initiated turns.

## Practical Code Examples

The following examples demonstrate interacting with the memory system via the Rust API (see [`examples/run_turn.rs`](https://github.com/tinyhumansai/openhuman/blob/main/examples/run_turn.rs) for complete context):

```rust
use openhuman_core::{Harness, Provider, Workspace, Access};

// Initialize core with ephemeral workspace
let harness = Harness::builder()
    .provider(Provider::openai_compatible(
        "https://api.openai.com".into(), 
        "sk-…".into()
    ))
    .workspace(Workspace::Ephemeral)
    .access(Access::full())
    .build()
    .await
    .expect("failed to build core");

// List Memory Tree root entries
let tree = harness
    .rpc()
    .call::<_, Vec<String>>("memory_tree_list", ())
    .await
    .expect("list failed");
println!("Memory Tree root entries: {:?}", tree);

```

Querying Obsidian vault status:

```rust
let vault_status = harness
    .rpc()
    .call::<_, openhuman::memory::read_rpc::ObsidianVaultStatusResponse>(
        "obsidian_vault_status",
        (),
    )
    .await
    .expect("vault query failed");

if vault_status.is_registered {
    println!("Vault path: {}", vault_status.absolute_path);
}

```

Enabling automatic synchronization for external connections:

```rust
harness
    .rpc()
    .call::<_, ()>("memory_tree_auto_sync_set", ("clickup", true))
    .await
    .expect("failed to enable sync");

```

## Summary

- **Memory Tree** provides a virtual hierarchy unifying documents, chunks, goals, and people data under a single namespace rooted at `~/OpenHuman/projects`
- **TinyMemory** serves as the versioned key-value engine backing all domains, with type safety enforced through the `tinymemory-api` contract
- **Obsidian sync** enables bidirectional workflows through automatic vault detection via [`obsidian.json`](https://github.com/tinyhumansai/openhuman/blob/main/obsidian.json) and deep-link generation
- The **Tree Runtime** in [`tree/tree_runtime/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/tree/tree_runtime/ops.rs) materializes virtual paths on demand while the **Sync Service** manages background data flows
- All operations are accessible via RPC endpoints, allowing external tools and UI components to interact with the memory layer without direct file system access

## Frequently Asked Questions

### How does the Memory Tree differ from a regular file system?

The Memory Tree is a virtual hierarchy that aggregates multiple specialized stores rather than storing files directly. According to the `tinyhumansai/openhuman` source code, it maps paths to domain-specific stores (documents, chunks, goals) registered in the `DomainSet`, with actual persistence handled by the TinyMemory engine. This allows the system to present a unified namespace while optimizing storage for each data type.

### What triggers Obsidian vault detection in OpenHuman?

Detection occurs when the `obsidian_vault_status` RPC endpoint calls `is_registered_vault` in [`src/openhuman/memory/obsidian_registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/obsidian_registry.rs). The function walks the filesystem looking for [`obsidian.json`](https://github.com/tinyhumansai/openhuman/blob/main/obsidian.json) files and checks whether the content root (or any ancestor directory) matches a registered vault path. Users can override the search path via the `extra_config_dir` parameter.

### Can I disable automatic synchronization with external services?

Yes. The `memory_tree_auto_sync` platform setting controls background synchronization. You can disable specific connectors by calling the `memory_tree_auto_sync_set` RPC with `false`, or prevent the sync service from scheduling jobs entirely. The agent-policy system ensures that even when enabled, background sync yields to user-initiated operations.

### How does TinyMemory ensure data consistency across modules?

TinyMemory enforces a single source of truth through the contract crate pattern. The `tinymemory-api` crate defines all types and protocols, which [`src/openhuman/memory/api.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/memory/api.rs) re-exports to both the core and loaded modules. This guarantees that modules compiled against the contract use identical type definitions, preventing runtime serialization mismatches when chunks are written by one component and read by another.