How Gated Families Are Managed in OpenHuman's Rust Core: The Three-Axis Architecture
OpenHuman manages gated families through a coordinated three-axis system that controls compile-time inclusion via Cargo features, runtime activation via DomainSet, and tool visibility via ToolGroups.
OpenHuman's Rust core implements a modular architecture where entire domain families—such as voice, web3, and documents—can be selectively compiled, activated, and exposed to AI agents. The system's gating mechanism operates across three distinct layers, ensuring that unused code is excluded from binaries, inactive domains consume no runtime resources, and tools are only exposed to models when appropriate.
The Three-Axis Gating Architecture
The gating system operates across three distinct layers that span the entire lifecycle of a domain family:
- Feature Gates: Control compile-time inclusion of family code in
src/Cargo.toml - DomainSet: Manages runtime activation of domain families via
src/core/runtime/builder.rs - ToolGroups: Regulates tool schema visibility and invocability through
src/openhuman/tools/toolpacks/registry.rs
Each axis addresses a specific concern, from binary size optimization to runtime security and model capability management.
Compile-Time Gating with Cargo Features
At the compilation layer, OpenHuman uses Cargo feature flags to determine which family implementations are included in the final binary. This system is defined in src/Cargo.toml and enforced throughout the codebase using the #[cfg(feature = "...")] attribute.
The Facade-Stub Pattern
Every gated family follows a facade+stub pattern that maintains API stability regardless of feature state. The top-level module is always compiled, but its implementation is conditionally included:
pub mod voice; // always compiled
#[cfg(feature = "voice")]
mod real; // real implementation
#[cfg(not(feature = "voice"))]
mod stub; // returns disabled-error
pub use real::*; // or stub::* depending on the feature
When the voice feature is disabled, the stub implementation provides identical public symbols but returns "feature disabled" errors. This pattern ensures that dependent code requires no additional #[cfg] checks—the API surface remains consistent across build configurations.
Integration Requirements
New families require three modifications to the build system:
- Add the feature flag definition to
src/Cargo.toml - Update the
DomainGroupenum insrc/core/all.rsto include the new family variant - Ensure the desktop shell forwards the flag, verified by
scripts/ci/check-feature-forwarding.mjs
Runtime Gating with DomainSet
Once compiled, families are controlled at runtime through the DomainSet struct defined in src/core/runtime/builder.rs. This system determines which domain families are active for a specific Core instance.
The DomainGroup Enum
All domain families are represented by the DomainGroup enum in src/core/all.rs. Each variant maps one-to-one to a top-level directory under src/openhuman/:
// Conceptual representation based on src/core/all.rs
pub enum DomainGroup {
Voice,
Web3,
Documents,
// ... additional families
}
The enum provides compile-time constants such as DomainGroup::ALL and DomainGroup::COUNT that enforce complete registration of all families across the system.
DomainSet Presets and Configuration
The DomainSet struct holds the active set of domains for a Core instance. The Harness::builder() API accepts this configuration to determine runtime behavior:
use openhuman_core::Harness;
use openhuman_core::runtime::DomainSet;
let harness = Harness::builder()
.domain_set(DomainSet::full()) // all families on
.build()
.await?;
Available presets include:
DomainSet::full(): Activates all compiled familiesDomainSet::harness(): Minimal set for testing environmentsDomainSet::none(): No families active
Runtime Behavior of Disabled Domains
When a domain is absent from the DomainSet:
- RPC Controllers are not registered, resulting in "unknown method" errors for requests targeting that family
- Agent Tools lists are empty—the domain's capabilities do not appear in the model's tool catalog
- Stores and Event Subscribers are not instantiated, conserving memory and CPU resources
Selective disabling works via standard set operations:
use openhuman_core::runtime::{DomainSet, DomainGroup};
let mut domains = DomainSet::full();
domains.remove(DomainGroup::Voice); // turn off voice at runtime
let harness = Harness::builder()
.domain_set(domains)
.build()
.await?;
Tool-Level Gating with ToolGroups
Even when a domain is active, individual tool packs can be controlled via ToolGroups defined in src/openhuman/tools/toolpacks/registry.rs. This three-state system manages tool visibility separately from domain availability:
| State | Schema on Wire | Callable by Core |
|---|---|---|
| Advertised | Yes | Yes |
| Withheld | No | Yes (via load_skill/use_skill) |
| Off | No | No |
Configuring Tool Visibility
The Harness::builder() API exposes .tool_groups() for fine-grained configuration:
use openhuman_core::tools::{ToolGroups, GroupMode};
let mut groups = ToolGroups::packed();
groups.with("media", GroupMode::Off); // hide all media tools
let harness = Harness::builder()
.tool_groups(groups)
.build()
.await?;
The Off state is particularly useful for embedded deployments that need to hide capabilities entirely, while Withheld supports lazy-loading patterns where tools remain callable but are not advertised in the initial schema sent to the model.
Wiring and Validation
All registration logic flows through src/core/all.rs, which contains #[cfg(feature = "...")] guarded push calls for controllers, stores, and tool packs. This centralizes the actual instantiation of family components and ensures that compile-time flags align with runtime registration.
Automated Testing
The test suite in src/core/all_tests.rs validates gating correctness across configurations:
- Confirms controllers appear when features are enabled
- Verifies controllers disappear when features are disabled
- Ensures
DomainGroup::ALLremains synchronized with registration logic
CI Feature Forwarding
The scripts/ci/check-feature-forwarding.mjs script prevents silent regressions by verifying that the desktop Tauri shell forwards every product feature to the core. This check caught historical issues such as the accidental loss of the voice family in certain desktop builds.
Adding a New Gated Family
To implement a new gated family (e.g., analytics), follow this integration checklist based on the existing patterns in tinyhumansai/openhuman:
- Directory Structure: Create
src/openhuman/analytics/implementing the facade-stub pattern - Domain Registration: Add a
DomainGroup::Analyticsvariant insrc/core/all.rs - Cargo Feature: Define the feature in
Cargo.tomland wrap implementation files with#[cfg(feature = "analytics")] - DomainSet Updates: Modify presets in
src/core/runtime/builder.rsto include the new group where appropriate - Tool Registration: Define tool packs in
src/openhuman/tools/toolpacks/registry.rsif the family exposes agent capabilities - Test Coverage: Add assertions in
src/core/all_tests.rsfor both enabled and disabled states - CI Verification: Run the feature-forwarding check to ensure desktop shell integration
This procedure ensures the new family behaves correctly across all three gating axes.
Summary
OpenHuman's gated family architecture provides precise control over code inclusion and runtime behavior:
- Cargo features in
src/Cargo.tomlcontrol compile-time inclusion using the facade-stub pattern, ensuring API consistency regardless of build configuration - DomainSet in
src/core/runtime/builder.rsmanages runtime activation via theDomainGroupenum, determining which RPC controllers and tools are available for a given Core instance - ToolGroups in
src/openhuman/tools/toolpacks/registry.rsoffer granular control over tool visibility throughAdvertised,Withheld, andOffstates - Central registration in
src/core/all.rsand comprehensive validation insrc/core/all_tests.rsensure system integrity across feature combinations - The CI feature-forwarding check prevents configuration drift between core and desktop shells
Frequently Asked Questions
How do I disable a specific family at runtime without recompiling?
Use the DomainSet API to remove the specific DomainGroup variant before building the Harness instance. Since DomainSet operates at runtime, you can toggle families via configuration without modifying Cargo features or rebuilding the binary.
What happens if I try to use a tool from a family that is compiled but not in the DomainSet?
The Core returns an "unknown method" error for RPC calls, and the tool does not appear in the agent's tool catalog. The family remains in the binary (compile-time inclusion) but is logically disconnected (runtime gating), providing both security and resource efficiency.
Can a tool be executable by the core but hidden from the AI model's schema?
Yes, set the tool pack's GroupMode to Withheld. In this state, the tool remains callable via explicit load_skill or use_skill requests but is excluded from the initial schema sent to the model. This supports capability discovery patterns and staged tool exposure.
Where is the single source of truth for which families exist in the system?
The DomainGroup enum in src/core/all.rs serves as the canonical registry. It must contain a variant for every family, and the DomainGroup::ALL constant enforces that all variants are accounted for in registration logic and tests.
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 →