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:

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:

  1. Add the feature flag definition to src/Cargo.toml
  2. Update the DomainGroup enum in src/core/all.rs to include the new family variant
  3. 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 families
  • DomainSet::harness(): Minimal set for testing environments
  • DomainSet::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::ALL remains 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:

  1. Directory Structure: Create src/openhuman/analytics/ implementing the facade-stub pattern
  2. Domain Registration: Add a DomainGroup::Analytics variant in src/core/all.rs
  3. Cargo Feature: Define the feature in Cargo.toml and wrap implementation files with #[cfg(feature = "analytics")]
  4. DomainSet Updates: Modify presets in src/core/runtime/builder.rs to include the new group where appropriate
  5. Tool Registration: Define tool packs in src/openhuman/tools/toolpacks/registry.rs if the family exposes agent capabilities
  6. Test Coverage: Add assertions in src/core/all_tests.rs for both enabled and disabled states
  7. 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.toml control compile-time inclusion using the facade-stub pattern, ensuring API consistency regardless of build configuration
  • DomainSet in src/core/runtime/builder.rs manages runtime activation via the DomainGroup enum, determining which RPC controllers and tools are available for a given Core instance
  • ToolGroups in src/openhuman/tools/toolpacks/registry.rs offer granular control over tool visibility through Advertised, Withheld, and Off states
  • Central registration in src/core/all.rs and comprehensive validation in src/core/all_tests.rs ensure 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →