# How Cargo Feature Gates Compose with Runtime DomainSet in OpenHuman

> Discover how OpenHuman's Cargo feature gates compose with runtime DomainSet, enabling a powerful two-layer system for code inclusion and runtime activation.

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

---

**Cargo feature gates control compile-time code inclusion while DomainSet filters runtime domain activation, creating a two-layer system where features must be compiled in before they can be toggled at runtime.**

OpenHuman employs a sophisticated two-axis configuration model that separates compile-time optimization from runtime flexibility. This architecture ensures minimal binary size through Cargo feature gates while maintaining operational versatility via the DomainSet axis. Understanding how these mechanisms compose allows developers to customize OpenHuman deployments across desktop, headless, and embedded environments without unnecessary recompilation.

## The Two-Axis Configuration Model

OpenHuman's configuration system operates on distinct compile-time and runtime layers. Each layer controls different aspects of the system's behavior and resource utilization.

### Compile-Time Feature Gates in Cargo.toml

Compile-time configuration is driven by Cargo feature gates defined in the root **[`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml)** under the `[features]` table and enumerated in **[`scripts/ci/product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/product-features.txt)** for production builds. These gates determine which code families and their transitive dependencies are included in the final binary.

When a feature such as `web3`, `voice`, or `documents` is disabled, the corresponding module is excluded from compilation entirely. This elimination extends to native dependencies like `bitcoin`, `libgit2-sys`, or `cpal`, ensuring zero binary-size cost for unused capabilities. According to the architecture documentation in **[`AGENTS.md`](https://github.com/tinyhumansai/openhuman/blob/main/AGENTS.md)**, this approach defines both a minimal *kernel profile* and a full *product profile* based on which gates are active during the build process.

### Runtime DomainSet in the Core Builder

Runtime configuration is managed by the **`DomainSet`** type implemented in **[`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs)**. This axis determines which domain families are active during process execution, controlled through the `CoreBuilder::domains()` method.

The `DomainSet` filters which controllers appear in the JSON-RPC dispatcher, which tools are advertised to agents, and which stores and event-subscribers are instantiated. Even when a domain's code is compiled into the binary, the runtime set can hide it from the RPC surface or disable its background services. The mapping of `DomainGroup` variants to runtime flags lives in **[`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs)**, where each variant corresponds to a specific functional domain like `Web3` or `Voice`.

## Composition Rules: How the Axes Interact

The relationship between compile-time feature gates and runtime DomainSet follows strict dependency rules. Feature gates act as the primary filter, while DomainSet provides secondary runtime filtering.

**Feature gates are the mandatory first layer.** If a Cargo feature is disabled at compile-time, the corresponding `DomainGroup` variant cannot be instantiated at runtime because the underlying code does not exist in the binary. This hard dependency guarantees that no binary-size or native-dependency cost is incurred for disabled features.

**DomainSet is the optional second layer.** When a feature is enabled at compile-time, the domain's code is present, but `DomainSet` can still disable it for a specific process. In this state, the binary retains the code but behaves as if the domain never existed. This allows a single compiled binary to run in different modes—such as a full desktop application versus a minimal headless harness—without recompilation.

**The axes are orthogonal but inter-dependent.** If a feature is off at compile-time, the runtime `DomainSet` flag is irrelevant. Conversely, if a feature is on but the runtime set disables the domain, the code remains dormant in the binary.

## Implementation Details from the OpenHuman Source Code

The composition logic is implemented through guarded code patterns in the core runtime builder. In **[`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs)**, the `CoreBuilder` accepts a `DomainSet` that is applied during construction:

```rust
// In src/core/runtime/builder.rs
pub fn domains(mut self, set: DomainSet) -> Self {
    self.context.domains = set;
    self
}

// Runtime check during domain registration
if self.context.domains.contains(DomainGroup::Web3) {
    // register web3 controllers, tools, stores…
}

```

The `DomainGroup` enum variants are declared in **[`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs)**, where each variant is matched in the domain registration block. This file serves as the central registry that connects compile-time features to runtime domain groups.

## Practical Configuration Examples

### Building a Minimal Binary

To create a lightweight binary with only specific domains, disable default features and select onlyrequired capabilities at compile-time:

```toml

# Cargo.toml snippet – disabling heavy features at compile-time

[features]
default = ["voice", "web3", "documents"]   # product profile

# To build a minimal binary:

#   cargo build --no-default-features --features "flows"

```

### Runtime Domain Selection

Once compiled, the same binary can operate in different modes by specifying the DomainSet at launch:

```rust
use openhuman_core::embed::CoreBuilder;
use openhuman_core::core::runtime::{DomainSet, ServiceSet};

// Full desktop mode: activate all compiled-in domains
let core = CoreBuilder::new()
    .domains(DomainSet::full())          // runtime: enable every compiled domain
    .services(ServiceSet::desktop())     // start HTTP RPC, socket.io, etc.
    .build()
    .await?;

// Headless harness mode: only core kernel domains
let core = CoreBuilder::new()
    .domains(DomainSet::harness())       // only Agent, Memory, Threads, Config, Security
    .services(ServiceSet::none())        // no background services
    .build()
    .await?;

```

### Environment-Based Runtime Override

The binary can read domain configuration from environment variables or CLI arguments:

```bash

# Launching with a runtime domain set override

OPENHUMAN_DOMAIN_SET=harness ./target/release/openhuman-core

```

## Why OpenHuman Separates Compile-Time and Runtime Configuration

This dual-axis design serves two critical engineering requirements. **Binary size control** is achieved through feature gates that eliminate heavy native dependencies entirely when not needed. **Operational flexibility** is provided by DomainSet, allowing the same artifact to function as a full desktop application, a headless CLI harness, or a minimal test fixture through runtime flags alone.

The separation ensures that CI/CD pipelines can build a single *product* binary defined in **[`scripts/ci/product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/product-features.txt)** while deployment scripts can fine-tune behavior per-environment using `DomainSet::full()`, `DomainSet::harness()`, or `DomainSet::none()` presets.

## Summary

- **Compile-time gates** in [`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml) determine code inclusion and native dependency linking; disabled features remove their corresponding `DomainGroup` variants entirely from the runtime registry.
- **Runtime DomainSet** in [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs) filters domain activation after compilation, controlling RPC visibility and tool availability without binary modification.
- **Composition order** is strict: features must be enabled at compile-time before DomainSet can toggle them at runtime.
- **Practical benefit** is the ability to ship one optimized binary that adapts to desktop, server, or test environments through configuration rather than recompilation.

## Frequently Asked Questions

### What happens if I enable a domain in DomainSet but disabled its feature at compile-time?

The domain will not be available. If the Cargo feature is disabled, the corresponding code is not compiled into the binary, making the `DomainGroup` variant unavailable for runtime instantiation. The `DomainSet` check will silently skip registration because the underlying modules do not exist in the artifact.

### Where are the product feature sets defined for OpenHuman releases?

Production feature configurations are defined in **[`scripts/ci/product-features.txt`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/ci/product-features.txt)** and the `[features]` table of the root **[`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml)**. These files specify the default feature set shipped with the desktop application, while the `DomainSet` presets like `DomainSet::full()` and `DomainSet::harness()` are implemented in **[`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs)**.

### Can I change the active domains without recompiling OpenHuman?

Yes. As long as the features were enabled at compile-time, you can switch between `DomainSet::full()`, `DomainSet::harness()`, or custom domain combinations at runtime by passing different values to `CoreBuilder::domains()` or setting the appropriate environment variables before launching the binary.

### How does DomainSet affect JSON-RPC controller registration?

When a domain is excluded from the `DomainSet`, its controllers are omitted from the JSON-RPC dispatcher in **[`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs)**. This results in unknown-method errors for RPC calls targeting that domain, effectively hiding the functionality from API consumers while keeping the underlying code present in the binary for potential future activation.