# How to Use openhuman_core::Harness for Library Embedding in OpenHuman

> Learn how to embed the OpenHuman core runtime into your Rust apps using openhuman_core::Harness. Enjoy turn-by-turn chat sessions without external processes.

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

---

**The `openhuman_core::Harness` struct provides a typed, async-friendly API for embedding the full OpenHuman core runtime into Rust applications, enabling turn-by-turn chat sessions without spawning external processes.**

OpenHuman supports both standalone Tauri-based deployment and direct library embedding for Rust developers. The `Harness` type—defined in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs)—wraps the complete Core runtime, including all background services, domain families, and tool packs, exposing a thin ergonomic layer for driving conversational agents programmatically.

## Understanding the Harness Architecture

The `Harness` struct acts as a reference-counted handle to the underlying Core runtime. Because it stores the runtime inside an `Arc<CoreHandle>`, cloning a `Harness` instance is computationally cheap and safe to share across async tasks. According to the source code comments in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs), the public API intentionally mirrors the CLI entry point but provides full type safety and async/await compatibility for library consumers.

The Harness lifecycle follows three distinct phases:

1. **Configuration** – Use `Harness::builder()` to construct a `HarnessBuilder` and specify providers, workspaces, access tiers, and runtime components.
2. **Initialization** – Call `.build().await` to load configuration, spawn the Core runtime via `CoreBuilder`, and return a ready-to-use `Harness`.
3. **Execution** – Invoke `.run(prompt).await` to execute a single conversational turn and receive a structured `TurnResult`.

## Building a Harness Instance

Construction begins with the `HarnessBuilder`, located in [`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs). The builder implements a fluent API where each configuration method consumes `self` and returns the updated builder, allowing method chaining for ergonomic setup.

```rust
use openhuman::embed::harness::{Harness, HarnessBuilder};
use openhuman::openhuman::{Provider, Workspace};
use openhuman::openhuman::access::Access;

let harness = Harness::builder()
    .provider(Provider::openai_compatible("https://api.openai.com", "sk-…"))
    .workspace(Workspace::Ephemeral)
    .access(Access::full())
    .backend_url("https://api.tinyhumans.ai")
    .build()
    .await?;

```

The `build()` method—implemented in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs)—performs the heavy initialization work. It resolves configuration sources (environment variables override configuration files), constructs the `CoreBuilder`, and wires optional components such as MCP servers, autonomy settings, and security policies. If any required runtime component fails to initialize, `build()` returns an error immediately.

Key builder configuration methods include:

- **`.provider(Provider)`** – Sets the LLM provider endpoint and credentials.
- **`.workspace(Workspace)`** – Configures persistent or ephemeral storage for the session.
- **`.access(Access)`** – Defines the permission tier (e.g., `Access::full()`).
- **`.services(ServiceSet)`** – Selects which background services (RPC, socket, cron) to spawn.
- **`.domains(DomainSet)`** – Chooses which domain families to initialize.
- **`.tools(ToolGroups)`** – Specifies available tool packs for the agent.
- **`.autonomy(AutonomySettings)`** and **`.policy(SecurityPolicy)`** – Configure runtime security constraints.

## Running Conversational Turns

Once initialized, the `Harness::run` method drives individual chat turns. The method signature accepts any type implementing `Into<String>` for the prompt and returns a `TurnResult` containing the complete interaction transcript.

```rust
let result = harness.run("Summarize the OpenHuman architecture.").await?;
println!("Agent reply: {}", result.agent_message);

```

As implemented in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs), the `run` method:

1. Creates a lightweight `Session` with a local identifier.
2. Initializes a turn context via `core.turn(session)`.
3. Sends the prompt through `turn.send_prompt()`.
4. Returns a `TurnResult` populated with `agent_message`, `tool_calls`, and `transcript` fields.

The `TurnResult` struct provides structured access to:

- **`agent_message`** – The final textual response from the language model.
- **`tool_calls`** – A vector of `ToolCall` objects recording every tool invocation, including name, arguments, and return values.
- **`transcript`** – A JSON representation of the full conversation history suitable for persistence or inspection.

## Headless Embedding and Runtime Customization

For background workers or CLI tools that require the Core logic without UI-related overhead, OpenHuman supports headless configuration via explicit `ServiceSet` and `DomainSet` selection. The example in [`examples/embed_headless.rs`](https://github.com/tinyhumansai/openhuman/blob/main/examples/embed_headless.rs) demonstrates this pattern:

```rust
use openhuman::core::runtime::builder::{ServiceSet, DomainSet, ToolGroups};

let harness = Harness::builder()
    .provider(Provider::openai_compatible("https://api.openai.com", "sk-…"))
    .workspace(Workspace::Ephemeral)
    .access(Access::full())
    .services(ServiceSet::none())      // Disables RPC, socket, and cron services
    .domains(DomainSet::harness())     // Loads only core domains required for embedding
    .tools(ToolGroups::packed())       // Includes default tool packs
    .build()
    .await?;

```

This configuration minimizes resource consumption by skipping the full service suite while retaining the conversational capabilities provided by the harness domains. Developers can mix and match `ServiceSet`, `DomainSet`, and `ToolGroups` variants to compose exact runtime requirements.

## Key Source Files and Implementation Details

Understanding the module structure helps when extending or debugging embedded deployments:

- **[`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs)** – Defines the public `Harness` struct, the `run` method, `TurnResult`, and the `HarnessBuilder::build` implementation that wires the Core runtime.
- **[`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs)** – Implements the fluent `HarnessBuilder` struct with chainable setters for provider, workspace, access tiers, and runtime components.
- **[`examples/run_turn.rs`](https://github.com/tinyhumansai/openhuman/blob/main/examples/run_turn.rs)** – Minimal demonstration of constructing a harness and executing a single conversational turn.
- **[`examples/embed_headless.rs`](https://github.com/tinyhumansai/openhuman/blob/main/examples/embed_headless.rs)** – Reference implementation for headless deployments with disabled UI services.
- **[`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs)** – Underlying `CoreBuilder` that `HarnessBuilder` delegates to for runtime initialization.

## Summary

- **`openhuman_core::Harness`** serves as the primary entry point for embedding OpenHuman as a library, wrapping the complete Core runtime in a cheap-to-clone handle.
- **Initialization** follows a builder pattern via `Harness::builder()`, supporting configuration of providers, workspaces, service sets, and security policies before calling `.build().await`.
- **Execution** uses `Harness::run(prompt).await` to drive turn-by-turn conversations, returning a `TurnResult` containing the agent message, tool calls, and JSON transcript.
- **Headless deployments** minimize overhead by specifying `ServiceSet::none()` and `DomainSet::harness()` to disable unnecessary background services.
- All implementation details reside in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs) and [`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs), with runnable examples available in [`examples/run_turn.rs`](https://github.com/tinyhumansai/openhuman/blob/main/examples/run_turn.rs) and [`examples/embed_headless.rs`](https://github.com/tinyhumansai/openhuman/blob/main/examples/embed_headless.rs).

## Frequently Asked Questions

### How does Harness differ from the OpenHuman CLI?

The CLI spawns a separate process that manages its own lifecycle and configuration parsing, while **`Harness`** provides a typed, programmatic API for direct integration into Rust applications. The `Harness` API mirrors CLI capabilities but operates entirely in-process via async Rust, making it suitable for library embedding where process isolation is undesirable.

### Can I share a Harness instance across multiple async tasks?

Yes. The `Harness` struct holds the Core runtime inside an **`Arc<CoreHandle>`**, making it cheap to clone and safe to share across concurrent tasks. Each call to `run()` creates a fresh `Session` instance, ensuring turn isolation while sharing the underlying runtime resources.

### What configuration options are available for headless embeddings?

Developers can disable UI-related services by passing **`ServiceSet::none()`** to the builder and restrict domains to the minimal set using **`DomainSet::harness()`**. Additional customization includes selecting specific `ToolGroups`, configuring `AutonomySettings` for agent permissions, and defining `SecurityPolicy` constraints—all through the `HarnessBuilder` interface defined in [`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs).