OpenHuman Native Modules: Complete Guide to tinydocs, tinyruntime, tinyvoice, and More
OpenHuman ships with seven dynamically loadable native modules—tinydocs, tinyruntime, tinyvoice, tinyjuice, tinywallet, memory, and platform—that extend the AI assistant's capabilities via cdylib plugins while maintaining a lightweight core binary.
OpenHuman's modular architecture separates heavy dependencies from the core runtime through native modules located in src/openhuman/modules/. These modules follow the TinyBus contract-first pattern, exposing RPC interfaces that the core invokes without bloating the main binary with unnecessary crates.
What Are OpenHuman Native Modules?
OpenHuman native modules are runtime-loadable cdylib plugins that implement specific feature contracts via the TinyBus system. According to the tinyhumansai/openhuman source code, each module resides in src/openhuman/modules/ as a Rust source file that compiles to a separate dynamic library.
The core binary interacts with these modules through RPC interfaces defined in the module contracts. This design allows the core to shed heavy dependencies—such as the 39 document-related crates used by tinydocs—by offloading functionality to dynamically loaded libraries.
Module Registry and Discovery
The static registry at src/openhuman/modules/registry.rs maintains a catalog of known module releases. Each entry includes:
- SHA-256 digest for verification
- Target triples specifying compatible platforms
- Version metadata for dependency resolution
At startup, the core checks the OPENHUMAN_MODULE_PATH environment variable or downloads verified artifacts from the registry. The loading process validates checksums, selects the appropriate artifact for the host's glibc/OS version, and invokes dlopen to load the cdylib.
Available Native Modules in OpenHuman
tinydocs (Document Processing)
Located in src/openhuman/modules/documents.rs, the tinydocs module handles Office document generation and PDF text extraction. It exports two primary RPC endpoints:
openhuman.documents_generate– Accepts aDocumentSpecand returns aDocumentResultcontaining.docxor.pptxfilesopenhuman.documents_extract– Parses PDFs and extracts text content
By isolating these codecs in a native module, the core binary eliminates 39 document-related crates from its dependency tree.
tinyruntime (JavaScript Execution)
The tinyruntime module in src/openhuman/modules/runtime.rs provides a sandboxed JavaScript/Node.js execution environment for user-supplied skills defined in SKILL.md workflows. It implements the runtime contract with these RPC endpoints:
openhuman.runtime_node_exec– Executes Node.js scripts in an isolated processopenhuman.runtime_npm_exec– Handles npm tool invocations and returns output streams
This module enables dynamic skill execution without embedding a JavaScript engine in the core binary.
tinyvoice (Speech Services)
Found in src/openhuman/modules/voice.rs, tinyvoice acts as a facade for Speech-to-Text (STT) and Text-to-Speech (TTS) services. Rather than linking heavy audio stacks like cpal or hound, the module forwards requests to hosted backends (OpenAI, ElevenLabs):
openhuman.voice_transcribe– Accepts audio blobs and returns transcribed textopenhuman.voice_synthesize– Converts text to speech via configured providers
tinyjuice (Token Processing)
The tinyjuice module, implemented in src/openhuman/modules/tokenjuice_host.rs, handles token-level inference for TinyJuice—the AST compression tool used by the memory subsystem. It exposes:
openhuman.tokenjuice_parse– Streams tokenized text data back to the core for efficient embedding generation
This module runs the parser in a separate process, preventing memory pressure from affecting the core runtime.
tinywallet (Cryptocurrency Operations)
Located in src/openhuman/modules/wallet.rs, tinywallet implements multi-chain cryptocurrency wallet operations for Bitcoin, EVM-compatible chains, and Solana. When the web3 feature is disabled, the module is completely omitted from builds. Its RPC surface includes:
openhuman.wallet_sign– Cryptographic signing of transaction payloadsopenhuman.wallet_prepare_transfer– Constructs and broadcasts transactions to specified networks
memory (Memory Provider)
The memory module at src/openhuman/modules/memory.rs provides a module-backed implementation of the tinymemory-api contract. It interfaces with the external tinymemory crate to provide:
openhuman.memory_diff– Retrieves diff-based snapshotsopenhuman.memory_chunk_read– Accesses hierarchical chunk storage with git-backed versioning
When present, the core routes all memory operations through this native module rather than using built-in implementations.
platform (OS Abstraction)
platform in src/openhuman/modules/platform.rs supplies OS-specific helpers including path handling and environment detection. This thin facade provides internal utilities required by other modules without pulling in heavy platform dependencies.
Practical Code Examples
Generating Documents with tinydocs
use openhuman::core::Harness;
use openhuman::api::document::{GenerateDocumentInput, DocumentFormat};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let harness = Harness::builder()
.provider(openhuman::providers::openai_compatible(
"https://api.openai.com/v1",
std::env::var("OPENAI_API_KEY")?,
))
.access(openhuman::access::full())
.build()
.await?;
let input = GenerateDocumentInput {
format: DocumentFormat::Docx,
content: "Hello, OpenHuman!".into(),
..Default::default()
};
let result = harness
.rpc()
.call("openhuman.documents_generate", input)
.await?
.into_json::<openhuman::api::document::GenerateDocumentResult>()?;
println!("Document written to: {}", result.path.display());
Ok(())
}
Executing JavaScript via tinyruntime
use openhuman::core::Harness;
use openhuman::api::runtime::NodeExecRequest;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let harness = Harness::builder()
.provider(openhuman::providers::openai_compatible(
"https://api.openai.com/v1",
std::env::var("OPENAI_API_KEY")?,
))
.access(openhuman::access::full())
.build()
.await?;
let request = NodeExecRequest {
script: "console.log(Date.now());".into(),
..Default::default()
};
let response = harness
.rpc()
.call("openhuman.runtime_node_exec", request)
.await?
.into_json::<openhuman::api::runtime::NodeExecResult>()?;
println!("Node output: {}", response.stdout);
Ok(())
}
Transcribing Audio with tinyvoice
use openhuman::core::Harness;
use openhuman::api::voice::TranscribeRequest;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let harness = Harness::builder()
.provider(openhuman::providers::openai_compatible(
"https://api.openai.com/v1",
std::env::var("OPENAI_API_KEY")?,
))
.access(openhuman::access::full())
.build()
.await?;
let audio_bytes = std::fs::read("speech.wav")?;
let request = TranscribeRequest {
audio: audio_bytes,
language: Some("en".into()),
..Default::default()
};
let result = harness
.rpc()
.call("openhuman.voice_transcribe", request)
.await?
.into_json::<openhuman::api::voice::TranscribeResult>()?;
println!("Transcription: {}", result.text);
Ok(())
}
Summary
OpenHuman's native module system enables feature-rich AI capabilities without compromising binary size or compile times:
- Seven native modules handle specific domains: documents (tinydocs), JavaScript execution (tinyruntime), audio (tinyvoice), tokenization (tinyjuice), cryptocurrency (tinywallet), memory (memory), and OS abstraction (platform)
- Dynamic loading via
cdylibplugins keeps heavy dependencies out of the core binary - TinyBus RPC interfaces provide standardized communication between the core and modules
- Registry-based distribution in
src/openhuman/modules/registry.rsmanages verified releases with SHA-256 validation
Frequently Asked Questions
How does OpenHuman load native modules at runtime?
The core checks the OPENHUMAN_MODULE_PATH environment variable for local builds. If absent, it queries the static registry in src/openhuman/modules/registry.rs, downloads the verified artifact matching the host's target triple, validates the SHA-256 checksum, and invokes dlopen to load the cdylib. The module then registers its RPC interfaces with the TinyBus system.
Can I run OpenHuman without loading native modules?
Yes. The core operates independently of native modules. However, specific features like document generation (tinydocs) or JavaScript execution (tinyruntime) require their respective modules to be loaded. Without these modules, the core cannot process requests targeting those RPC endpoints.
What is the difference between tinyjuice and the memory module?
tinyjuice, located in src/openhuman/modules/tokenjuice_host.rs, specifically handles token-level parsing and AST compression for the TinyJuice tool. The memory module in src/openhuman/modules/memory.rs provides the full memory contract implementation, including diff-based snapshots and chunk storage. While tinyjuice assists the memory system with tokenization, the memory module manages the complete persistence layer.
Why are audio codecs removed from the main binary?
The tinyvoice module acts as a thin facade that forwards STT/TTS requests to remote providers like OpenAI and ElevenLabs. By removing heavy audio dependencies such as cpal and hound from the core binary and placing them in the dynamically loaded module, OpenHuman maintains a lightweight footprint while still offering comprehensive voice capabilities.
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 →