How the Obsidian Vault Synchronizes with the OpenHuman Memory Tree Canonicalization Process
OpenHuman maintains bidirectional synchronization between its SQLite memory-tree and an Obsidian-compatible markdown vault by writing canonicalized chunks and summaries to <workspace>/wiki/ during the canonicalization pipeline, then re-ingesting user edits on subsequent runs to keep both stores aligned.
The OpenHuman platform employs a dual-storage architecture that bridges machine-readable databases with human-readable knowledge bases. When the system performs memory tree canonicalization—the process of scoring, summarizing, and hierarchically organizing extracted knowledge—it simultaneously updates an Obsidian vault that serves as a browsable mirror of the agent's memory. This synchronization ensures that every canonical chunk and summary node exists both in the authoritative SQLite store and in a local markdown vault accessible through Obsidian's graph view.
Ingestion Pipeline: From Raw Sources to Canonical Chunks
The synchronization process begins during the ingestion phase, where OpenHuman parses external sources such as Gmail, Slack, and WhatsApp into standardized memory chunks. Provider-specific modules like gmail::ingest.rs and slack::ingest.rs handle the initial parsing, converting raw messages into canonical chunks of ≤ 3 k tokens formatted as Markdown.
These chunks are stored in the SQLite chunks table while simultaneously being written to the Obsidian vault. The job orchestration in src/openhuman/memory/tree/jobs/handlers/mod.rs coordinates this dual-write operation:
src/openhuman/composio/providers/gmail/ingest.rs(line 404) writes markdown files for Obsidian compatibilitysrc/openhuman/composio/providers/slack/ingest.rs(line 227) performs similar vault writes for Slack messages
Tag Generation and YAML Header Updates
After chunk creation, OpenHuman generates Obsidian-style hierarchical tags using the kind/Value format to enable graph navigation and filtering. The tag logic resides in src/openhuman/memory/tree/content_store/tags.rs, where two key functions operate:
entity_tagconstructs the hierarchicalkind/Valuestringupdate_chunk_tagsatomically rewrites thetags:block in the markdown file's YAML front-matter while preserving the body content's SHA hash
As documented in src/openhuman/memory/tree/content_store/README.md, this process ensures that metadata updates don't corrupt the underlying content while maintaining compatibility with Obsidian's tag explorer and graph view.
Canonical Summary Trees and Wikilink Construction
During canonicalization, the system folds multiple chunks into higher-level summary nodes, creating a hierarchical memory tree. This process generates summary markdown files that serve as parent nodes in the Obsidian vault, containing:
- YAML front-matter with child wikilinks (
[[<basename>]]) referencing descendant chunks - Obsidian-compatible
tags:sections for hierarchical filtering
The markdown composition logic in src/openhuman/memory/tree/content_store/compose.rs handles this construction:
- Line 49 builds the canonical source tag for summaries
- Line 388 adds child wikilinks to the front-matter
- Filename safety is ensured via
memoryTree.ts(line 447) in the UI layer, which sanitizes basenames for filesystem compatibility
Vault Layout and File System Operations
All markdown files reside under a single content root defined in src/openhuman/memory/tree/content_store/paths.rs. The vault uses a flat directory structure at <workspace>/wiki/ with subfolders for each logical source (source/<slug>/), avoiding deep hierarchies that would clutter the Obsidian sidebar (see paths.rs line 46).
The actual filesystem operations are coordinated by src/openhuman/memory/tree/content_store/mod.rs, which ensures exactly one copy of each chunk exists in the vault. The dedicated Obsidian writer in src/openhuman/memory/tree/content_store/obsidian.rs serves as the primary entry point for vault writes, abstracting the specifics of markdown formatting and file placement. The abstraction for source-file handling, including Obsidian ".base" file representations, is provided by src/openhuman/memory/tree/tree_source/source_file.rs.
UI Deep-Link Integration
The React frontend provides seamless navigation between the OpenHuman interface and Obsidian through deep-link integration. The RPC read path in src/openhuman/memory/tree/read_rpc.rs exposes the vault's content location to the frontend, enabling the construction of valid filesystem paths.
When users click "View vault in Obsidian," the application constructs an obsidian://open?path=… URL that the operating system resolves to the local Obsidian installation.
Implementation details appear in two key UI components:
app/src/components/intelligence/MemoryWorkspace.tsxcontains theopenVaultInObsidianfunction (lines 70‑75) that opens the entire vaultapp/src/components/intelligence/MemoryGraph.tsximplementsopenSummaryInObsidianfor individual node navigationapp/src/utils/tauriCommands/memoryTree.tsprovides filesystem-safe basename generation for URLs
The following TypeScript implementation demonstrates the vault opening mechanism:
async function openVaultInObsidian(contentRootAbs: string): Promise<void> {
const url = `obsidian://open?path=${encodeURIComponent(contentRootAbs)}`;
console.debug('[ui-flow][memory-workspace] open vault in Obsidian url=%s', url);
await window.__TAURI__.invoke('open', { path: url });
}
Both functions log deep-link URLs using prefixed debug markers ([ui-flow][memory-workspace] and [memory-graph]) for troubleshooting synchronization issues.
Bidirectional Synchronization Cycle
The synchronization operates as a one-way write, round-trip read system where SQLite remains the single source of truth. When users edit markdown files directly in Obsidian, changes are not immediately written back to the database. Instead, the next canonicalization run detects modifications through filesystem timestamp comparisons.
The re-ingestion process follows this sequence:
- The scanner identifies modified files by comparing timestamps against the last canonicalization run
- The markdown parser re-extracts entities and content from the edited file
- The corresponding chunk row in SQLite updates to reflect the changes
- The system regenerates tags and summary links, ensuring the vault and memory-tree converge to a consistent state
This design guarantees that the SQLite memory-tree maintains authoritative status while the Obsidian vault serves as a reproducible, human-editable view that automatically reconciles with the canonical state.
Summary
- Dual storage architecture: OpenHuman maintains both an SQLite memory-tree and an Obsidian-compatible markdown vault at
<workspace>/wiki/ - Canonicalization writes: The pipeline in
src/openhuman/memory/tree/content_store/handles markdown generation, tag creation, and summary tree construction during the canonicalization process - Hierarchical tags: The system generates
kind/Valuetags viasrc/openhuman/memory/tree/content_store/tags.rsfor Obsidian graph navigation - Deep-link support: UI components in
app/src/components/intelligence/enable one-click vault opening viaobsidian://URLs - Bidirectional sync: User edits in Obsidian are detected via filesystem timestamps and re-ingested on subsequent canonicalization runs, with SQLite serving as the single source of truth
Frequently Asked Questions
How does OpenHuman handle filename collisions in the Obsidian vault?
The system prevents collisions through app/src/utils/tauriCommands/memoryTree.ts (line 447), which sanitizes basenames to ensure filesystem safety. Additionally, src/openhuman/memory/tree/content_store/paths.rs organizes files into source-specific subdirectories (source/<slug>/), reducing the likelihood of naming conflicts between different data providers.
Can I edit files in the Obsidian vault without breaking the synchronization?
Yes. The vault is designed for human editing, and any modifications made in Obsidian are detected during the next canonicalization cycle via filesystem timestamp checks. The re-ingestion process in src/openhuman/memory/tree/content_store/mod.rs parses your edits and updates the corresponding SQLite chunks, preserving the bidirectional flow without requiring manual intervention.
What happens if the Obsidian vault directory is moved or deleted?
The vault is a derived view of the SQLite memory-tree, not the primary data store. If deleted, OpenHuman regenerates the entire vault from the canonical memory-tree during the next canonicalization run. However, any un-ingested edits made in Obsidian would be lost, as the system cannot recover changes that never completed a synchronization cycle back to SQLite.
Which component generates the hierarchical tags visible in Obsidian's graph view?
Tag generation occurs in src/openhuman/memory/tree/content_store/tags.rs, specifically through the entity_tag and update_chunk_tags functions. These create the kind/Value hierarchical format that Obsidian recognizes for graph visualization and tag filtering, automatically updating the YAML front-matter of vault files without altering the body content.
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 →