# Configuring DomainSet and ServiceSet for Custom OpenHuman Runtimes: A Complete Guide

> Configure DomainSet and ServiceSet for custom OpenHuman runtimes. Tailor your tinyhumansai/openhuman runtime from desktop apps to headless APIs using CoreBuilder.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: how-to-guide
- Published: 2026-08-29

---

**Use `CoreBuilder` with `ServiceSet` to select transport layers and `DomainSet` to enable specific domain families, allowing you to tailor the tinyhumansai/openhuman runtime from full desktop applications to headless APIs or embedded libraries.**

OpenHuman provides a flexible, two-axis configuration system that lets you customize exactly which services start and which business logic domains are active. By combining `ServiceSet` and `DomainSet` through the `CoreBuilder` API, you can construct runtimes ranging from feature-rich desktop shells to minimal headless workers or pure library embedders.

## Understanding the Two-Axis Configuration Model

OpenHuman’s runtime is configured along two independent axes that control orthogonal aspects of the system.

### ServiceSet: Transport and Background Services

The **ServiceSet** axis determines which transport protocols and background services initialize at runtime. This controls how your runtime communicates with the outside world and manages internal scheduling.

Available presets include:

- **`ServiceSet::desktop()`** – Activates all transports and services, including the full HTTP RPC server, Socket.IO, cron schedulers, and channel listeners. This is the configuration used by the desktop Tauri shell.
- **`ServiceSet::headless_api()`** – Starts only the HTTP JSON-RPC server, ideal for cloud deployments and server environments that need API access without UI components.
- **`ServiceSet::none()`** – Disables all transports, creating a pure library mode with no external network services.
- **`ServiceSet::embedded()`** – Configures a long-lived embedder that runs background work and internal processing but exposes no external transport layer.

Pass your chosen preset to `CoreBuilder::services(..)` when constructing the runtime.

### DomainSet: Domain Families and Controllers

The **DomainSet** axis selects which domain families (controllers, tools, stores, and subscribers) are live at runtime. Each flag corresponds to a `DomainGroup` that represents a functional area of the system.

Domain families include: `agent`, `memory`, `threads`, `config`, `security`, `flows`, `skills`, `mcp`, `channels`, `web3`, `voice`, and `media`.

Available presets include:

- **`DomainSet::full()`** – Enables every domain family, matching the default behavior of the desktop application.
- **`DomainSet::harness()`** – Activates only core kernel families required for an embeddable agent harness (`agent`, `memory`, `threads`, `config`, and `security`).
- **`DomainSet::none()`** – Disables every domain family, leaving only always-on core infrastructure.

Provide the set to `CoreBuilder::domains(..)` to tailor the feature surface. You can also construct custom sets manually by setting individual boolean flags.

## CoreBuilder API and Configuration Methods

The runtime composition happens through `CoreBuilder`, defined in [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs). This builder exposes methods to independently set both axes before calling `build().await` to instantiate the core.

According to the source code in [`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs), the high-level facade exposes these methods for embedders:

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

let core = CoreBuilder::new()
    // Enable only HTTP JSON-RPC and the cron scheduler
    .services(ServiceSet::headless_api())
    // Run only the kernel families required for an embedded agent
    .domains(DomainSet::harness())
    .build()
    .await?;

```

The chosen sets are stored in the runtime context ([`src/core/runtime/context.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/context.rs)), making them available throughout the application lifecycle.

## Practical Configuration Examples

### Full Desktop Runtime

Use this configuration when building a complete desktop application with all features enabled:

```rust
let core = CoreBuilder::new()
    .services(ServiceSet::desktop())   // All transports + services
    .domains(DomainSet::full())        // Every domain family enabled
    .build()
    .await?;

```

### Headless Cloud Worker

Deploy a lightweight server that exposes only HTTP JSON-RPC while maintaining full business logic capabilities:

```rust
let core = CoreBuilder::new()
    .services(ServiceSet::headless_api())
    .domains(DomainSet::full())   // Keep all domain families
    .build()
    .await?;

```

### Pure Library and Harness Mode

Create a minimal embeddable runtime with no network exposure and only essential kernel domains:

```rust
let core = CoreBuilder::new()
    .services(ServiceSet::none())
    .domains(DomainSet::harness())
    .build()
    .await?;

```

### Custom Domain Selection

Selectively disable specific domains like voice and web3 while keeping other features:

```rust
let custom_domains = DomainSet {
    agent: true,
    memory: true,
    threads: true,
    config: true,
    security: true,
    flows: true,
    skills: true,
    mcp: true,
    channels: true,
    web3: false,   // Disabled
    voice: false,  // Disabled
    media: false,
};

let core = CoreBuilder::new()
    .services(ServiceSet::desktop())
    .domains(custom_domains)
    .build()
    .await?;

```

### Embedded Host with Background Work

Run background tasks and internal processing without exposing external RPC endpoints:

```rust
let core = CoreBuilder::new()
    .services(ServiceSet::embedded())
    .domains(DomainSet::harness())
    .build()
    .await?;

```

## Key Source Files and Implementation Details

Understanding where these configurations are defined helps when extending or debugging the runtime:

- **[`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs)** – Contains the struct definitions for `ServiceSet` and `DomainSet`, including their preset methods and documentation (lines 32-100).
- **[`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs)** – Exposes the high-level `CoreBuilder` API used by embedders and application runners (lines 4-34).
- **[`src/tui/runner.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/tui/runner.rs)** – Demonstrates constructing a core with `DomainSet::full()` and `ServiceSet::none()` for the terminal UI runner (lines 122-127).
- **[`src/core/runtime/context.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/context.rs)** – Holds the runtime context that carries the chosen `DomainSet` and `ServiceSet` throughout execution.
- **[`src/lib.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/lib.rs)** – Re-exports `CoreBuilder`, `DomainSet`, `ServiceSet`, and related types for library consumers.

## Summary

- **ServiceSet** controls transport layers (HTTP RPC, Socket.IO) and background services, with presets for desktop, headless API, embedded, and disabled modes.
- **DomainSet** controls which business logic families are active, with presets for full features, minimal harness, or completely disabled.
- **`CoreBuilder`** composes these axes independently via `services()` and `domains()` methods before `build().await`.
- Configuration definitions live in [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs), while practical examples appear in [`src/tui/runner.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/tui/runner.rs) and the harness builder.
- You can construct manual `DomainSet` instances with individual boolean flags to create precisely tailored runtimes.

## Frequently Asked Questions

### What is the difference between ServiceSet and DomainSet in OpenHuman?

**ServiceSet** controls infrastructure concerns—transports like HTTP JSON-RPC, Socket.IO, and background schedulers—while **DomainSet** controls application logic by enabling or disabling specific domain families like `agent`, `memory`, or `web3`. They are independent axes, meaning you can run a headless HTTP API with only harness domains, or a desktop app with no transport (as shown in [`src/tui/runner.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/tui/runner.rs)).

### How do I create a headless OpenHuman server?

Pass `ServiceSet::headless_api()` to `CoreBuilder::services()` to start only the HTTP JSON-RPC server without Socket.IO or other desktop-specific services. You typically pair this with `DomainSet::full()` to keep all business logic available via the API, or use `DomainSet::harness()` for a minimal agent server.

### Can I enable specific domains while disabling others in OpenHuman?

Yes. Instead of using presets like `DomainSet::full()`, instantiate `DomainSet` directly with struct literal syntax, setting boolean flags for each domain family (`agent`, `memory`, `threads`, `config`, `security`, `flows`, `skills`, `mcp`, `channels`, `web3`, `voice`, `media`). Pass this custom instance to `CoreBuilder::domains()`.

### Where are ServiceSet and DomainSet defined in the OpenHuman source code?

Both structs are defined in **[`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs)** (lines 32-100) according to the tinyhumansai/openhuman repository. The `CoreBuilder` API that consumes these types is exposed through **[`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs)**, and the runtime context holding these values is managed in **[`src/core/runtime/context.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/context.rs)**.