# How to Embed OpenHuman Core as a Rust Library Using Harness

> Embed OpenHuman AI core into your Rust app with Harness. Configure LLM, workspace, and access tier, then run agent turns for seamless integration.

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

---

**You can embed OpenHuman's AI agent core in any Rust application by using the `Harness` builder API to configure the LLM provider, workspace, and access tier, then calling `run()` or `turn()` to execute agent turns.**

The `openhuman` crate from the [tinyhumansai/openhuman](https://github.com/tinyhumansai/openhuman) repository exposes its core engine as a reusable Rust library. The primary entry point for programmatic integration is the `Harness` type, which provides a fluent builder interface to assemble a fully functional AI agent that matches the behavior of the desktop product.

## Understanding the Harness Architecture

`Harness` encapsulates everything required to run an AI agent turn, including the LLM provider configuration, persistence layer, security gates, and optional cloud services. According to the source code in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs), this design ensures that the core is instantiated **once** per process and can be reused across any number of conversational turns.

The builder pattern is implemented in [`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs) and enforces compile-time safety for required configuration components. Once constructed via `Harness::builder().build().await`, the instance manages its own async runtime and security boundaries, making it safe to embed into existing applications without disrupting their execution model.

## Configuring the Harness Builder

### Setting Up the LLM Provider

The `Provider` struct (defined in [`src/embed/harness/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/provider.rs)) supports OpenAI-compatible endpoints, Claude, and other LLM backends. You must specify the base URL, API key, and model name:

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

let harness = Harness::builder()
    .provider(
        Provider::openai_compatible(
            "https://api.openai.com/v1",
            std::env::var("OPENAI_API_KEY")?,
        )
        .model("gpt-4o"),
    )
    .workspace(Workspace::Ephemeral)
    .access(Access::full())
    .build()
    .await?;

```

### Choosing a Workspace Strategy

Workspace configuration (located in [`src/embed/harness/workspace.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/workspace.rs)) determines how the agent handles persistent state and temporary files:

- **`Workspace::Ephemeral`** – In-memory sandbox with no disk persistence
- **`Workspace::Dir(path)`** – Dedicated directory for agent files and tool workspaces
- **`Workspace::Inherit`** – Reuses the parent process environment

### Defining Access Permissions

The access tier (defined in [`src/embed/harness/access.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/access.rs)) controls which tools and policies the embedded agent may invoke:

- **`Access::full()`** – Unrestricted tool access
- **`Access::supervised()`** – Requires approval for sensitive operations
- **`Access::readonly()`** – Blocks all mutation operations

### Optional Cloud Backend and Services

You can optionally connect to TinyHumans cloud services by specifying a backend URL in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs). For extended functionality, [`src/embed/harness/mcp.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mcp.rs) exposes methods like `mcp()`, `services()`, and `tool_groups()` to enable micro-container protocols, cron jobs, and channel communications that mirror the full desktop product capabilities.

## Running Agent Turns

Once built, the `Harness` exposes two primary methods for execution:

- **`run(prompt)`** – Initiates a new conversation session
- **`turn(prompt)`** – Continues an existing session using a session ID

Both methods return a `TurnResult` containing `output_text`, generated tool calls, and the `session_id` for stateful multi-turn conversations. All I/O operations pass through the same security and approval gates used by the official UI.

```rust
// First turn creates a session
let first = harness.run("Summarise the repository.").await?;
println!("{}", first.output_text);

// Continue the same session
let second = harness
    .turn("Now detail the build process.")
    .session(&first.session_id)
    .send()
    .await?;

```

## Complete Integration Examples

### Single-Turn Execution

For one-off queries without persistence, use an ephemeral workspace and the `run` method:

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

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let harness = Harness::builder()
        .provider(
            Provider::openai_compatible(
                "https://api.openai.com/v1",
                std::env::var("OPENAI_API_KEY")?,
            )
            .model("gpt-4o"),
        )
        .workspace(Workspace::Ephemeral)
        .access(Access::full())
        .build()
        .await?;

    let result = harness.run("Explain how OpenHuman's architecture works.").await?;
    println!("Reply:\n{}", result.output_text);
    Ok(())
}

```

### Multi-Turn Session Management

To maintain context across multiple prompts, capture the `session_id` from the initial turn and pass it to subsequent `turn` calls:

```rust
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let harness = Harness::builder()
        .provider(
            Provider::openai_compatible(
                "https://api.openai.com/v1",
                std::env::var("OPENAI_API_KEY")?,
            )
            .model("gpt-4o-mini"),
        )
        .workspace(Workspace::Dir("my_workspace".into()))
        .access(Access::full())
        .build()
        .await?;

    let first = harness.run("List the main modules in this repo.").await?;
    println!("First reply: {}", first.output_text);

    let second = harness
        .turn("Give a brief description of each module.")
        .session(&first.session_id)
        .send()
        .await?;
    println!("Second reply: {}", second.output_text);
    Ok(())
}

```

### Embedding in a Third-Party Crate

Add the dependency to your [`Cargo.toml`](https://github.com/tinyhumansai/openhuman/blob/main/Cargo.toml):

```toml
[dependencies]
openhuman = { path = "../openhuman", features = ["full"] }
tokio = { version = "1", features = ["full"] }

```

Then expose the functionality through your library:

```rust
pub async fn embed_core() -> anyhow::Result<String> {
    let harness = openhuman::embed::harness::Harness::builder()
        .provider(
            openhuman::embed::harness::Provider::openai_compatible(
                "https://api.openai.com/v1",
                std::env::var("OPENAI_API_KEY")?,
            )
            .model("gpt-4o"),
        )
        .workspace(openhuman::embed::harness::Workspace::Ephemeral)
        .access(openhuman::embed::harness::Access::full())
        .build()
        .await?;

    let resp = harness.run("What is the purpose of the src/openhuman/web3 package?").await?;
    Ok(resp.output_text)
}

```

## Summary

- **Single entry point**: The `Harness` type in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs) provides the primary API for embedding OpenHuman core
- **Builder pattern**: Use `Harness::builder()` to configure Provider, Workspace, and Access tiers before calling `build().await`
- **Session management**: `run()` creates new conversations while `turn()` continues existing ones using session IDs
- **Security parity**: Embedded instances use identical security gates and tool policies as the desktop application
- **File locations**: Key implementations reside in [`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs), [`provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/provider.rs), [`workspace.rs`](https://github.com/tinyhumansai/openhuman/blob/main/workspace.rs), and [`access.rs`](https://github.com/tinyhumansai/openhuman/blob/main/access.rs)

## Frequently Asked Questions

### What is the difference between Harness::run() and Harness::turn()?

`Harness::run()` initiates a fresh conversation session and returns a `TurnResult` containing a new `session_id`. `Harness::turn()` requires chaining `.session(&existing_session_id)` to continue a previous conversation, maintaining context and accumulated state from prior turns.

### How do I configure the Harness to use Claude instead of OpenAI?

According to [`src/embed/harness/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/provider.rs), replace `Provider::openai_compatible()` with the Claude-specific constructor (or compatible endpoint URL) and adjust the model identifier accordingly. The provider system abstracts the underlying LLM implementation while maintaining a consistent interface for the `Harness`.

### Can I use a custom Tokio runtime instead of the one spawned by Harness?

Yes. While `Harness::builder().build().await` spawns an internal runtime by default, you can supply a custom Tokio runtime configuration through the `runtime()` method on the builder, as indicated in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs). This allows integration with existing async application architectures.

### What permissions does the Access::full() tier grant to the embedded agent?

`Access::full()` enables all available tools and removes policy restrictions, allowing the agent to execute file operations, network calls, and system commands without additional approval gates. For restricted environments, use `Access::supervised()` or `Access::readonly()` as defined in [`src/embed/harness/access.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/access.rs).