# How Gated Families Are Managed in OpenHuman's Rust Core: The Three-Axis Architecture

> Discover how OpenHuman's Rust core manages gated families using a three-axis architecture for compile-time, runtime, and tool visibility control. Learn more!

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

---

**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`](https://github.com/tinyhumansai/openhuman/blob/main/src/Cargo.toml)
- **DomainSet**: Manages runtime activation of domain families via [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs)
- **ToolGroups**: Regulates tool schema visibility and invocability through [`src/openhuman/tools/toolpacks/registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/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:

```rust
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`](https://github.com/tinyhumansai/openhuman/blob/main/src/Cargo.toml)
2. Update the `DomainGroup` enum in [`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs). Each variant maps one-to-one to a top-level directory under `src/openhuman/`:

```rust
// 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:

```rust
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:

```rust
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`](https://github.com/tinyhumansai/openhuman/blob/main/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:

```rust
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`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs)
3. **Cargo Feature**: Define the feature in [`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml) and wrap implementation files with `#[cfg(feature = "analytics")]`
4. **DomainSet Updates**: Modify presets in [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/toolpacks/registry.rs) if the family exposes agent capabilities
6. **Test Coverage**: Add assertions in [`src/core/all_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs) and comprehensive validation in [`src/core/all_tests.rs`](https://github.com/tinyhumansai/openhuman/blob/main/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`](https://github.com/tinyhumansai/openhuman/blob/main/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.