# How to Use the OpenHuman Harness API to Embed the Agent in a Rust Binary

> Embed the OpenHuman agent in your Rust binary using the Harness API. Easily create agent runtimes for single-turn and multi-turn conversations with async methods.

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

---

**The OpenHuman Harness API exposes a builder-pattern façade that creates a fully-configured agent runtime, allowing you to embed the OpenHuman agent into any Rust binary with async methods for single-turn prompts and multi-turn conversations.**

The `tinyhumansai/openhuman` repository distributes its core agent logic as a library crate named `openhuman`. The **`Harness`** type—re-exported at the crate root—serves as the primary entry point for programmatic use. Located in [`src/openhuman/agent/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/mod.rs), this type provides a minimal, async API that mirrors the runtime used by the official desktop UI.

## Understanding the Harness Architecture

The `Harness` type implements a builder-pattern lifecycle. Calling **`Harness::builder()`** returns a `HarnessBuilder` (defined in [`src/openhuman/agent/harness/session/builder/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/session/builder/mod.rs)) that captures configuration for the LLM provider, workspace persistence, and security policy. Once configured, invoking `.build().await` yields an initialized `Harness` instance ready to process prompts.

The builder accepts four critical configuration domains:

- **Provider selection** – Determines the LLM backend and model via [`src/openhuman/agent/harness/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/provider.rs)
- **Workspace handling** – Controls where the agent stores its action directory and artifacts via [`src/openhuman/agent/harness/workspace.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/workspace.rs)
- **Access tier** – Defines autonomy levels (`full`, `supervised`, `readonly`) via [`src/openhuman/agent/harness/access.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/access.rs)
- **Backend URL** – Points to the TinyHumans backend for authentication and billing, defaulting to production

## Configuring the Provider and Workspace

### Selecting an LLM Provider

The `Provider` enum abstracts multiple LLM backends. Use **`Provider::openai_compatible()`** to target OpenAI or any OpenAI-compatible endpoint:

```rust
Provider::openai_compatible("https://api.openai.com/v1", "sk-…")
    .model("gpt-4o")

```

This logic lives in [`src/openhuman/agent/harness/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/provider.rs). The provider configuration supports custom endpoints, enabling use with local models or alternative cloud providers that adhere to the OpenAI API specification.

### Choosing Workspace Persistence

The `Workspace` enum in [`src/openhuman/agent/harness/workspace.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/workspace.rs) offers three variants:

- **`Workspace::Ephemeral`** – Creates a temporary directory deleted on process exit, ideal for stateless automation
- **`Workspace::Dir(path)`** – Pins a persistent location on disk for the action directory and tool outputs
- **`Workspace::Inherit`** – Uses an existing workspace context

The workspace location determines where sandboxed tools write files and where the agent stores its artifact cache.

### Setting Access Tiers

Security policies are enforced via the **`Access`** type in [`src/openhuman/agent/harness/access.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/access.rs):

- **`Access::full()`** – Grants unrestricted tool usage and file system mutation
- **`Access::supervised()`** – Requires confirmation for destructive actions
- **`Access::readonly()`** – Blocks write operations entirely

The selected tier is encoded into the core's `SecurityPolicy` during `build()`.

## Running Single-Turn and Multi-Turn Conversations

### Single-Turn Execution

For one-shot prompts, use **`harness.run(prompt).await`**, defined in [`src/openhuman/agent/harness/session/turn/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/session/turn/mod.rs). This method initializes a session, sends the prompt, and returns the complete reply.

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

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    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::Ephemeral)
        .access(Access::full())
        .backend_url("https://api.tinyhumans.ai")
        .build()
        .await?;

    let reply = harness.run("Summarize the OpenHuman architecture.").await?;
    println!("Agent reply:\n{}", reply.message);
    Ok(())
}

```

### Multi-Turn Conversation Handling

For stateful interactions, **`harness.turn(prompt).await`** returns a **`TurnHandle`** that persists session context. The handle exposes methods to continue the conversation, inspect the session ID, or retrieve the full transcript.

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

#[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::Dir("./my_workspace".into()))
        .access(Access::full())
        .build()
        .await?;

    let mut turn: TurnHandle = harness.run("You are a helpful assistant.").await?.into();

    for user_msg in [
        "What is the purpose of the `Harness` builder?",
        "Give me a concise example of tool usage.",
    ] {
        turn = turn.turn(user_msg).await?;
        println!("Assistant: {}", turn.reply().message);
    }

    let transcript = turn.transcript().await?;
    println!("Full transcript ({} turns):", transcript.len());
    for entry in transcript {
        println!("> {}", entry.message);
    }

    Ok(())
}

```

The transcript retrieval logic resides in [`src/openhuman/agent/harness/session/transcript.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/session/transcript.rs), while turn state management is handled in [`src/openhuman/agent/harness/session/turn/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/session/turn/mod.rs).

## Enabling Sandboxed Tool Execution

To execute sandboxed tools—such as the `python_exec` tool—set the **`OPENHUMAN_SANDBOX_MODE`** environment variable before building the harness. The sandbox context is managed in [`src/openhuman/agent/harness/sandbox_context.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/sandbox_context.rs).

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

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    std::env::set_var("OPENHUMAN_SANDBOX_MODE", "sandboxed");

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

    let reply = harness.run(
        "Run this Python code and return its output:\n```python\nprint(2 * 7)\n```"
    ).await?;

    println!("Tool output: {}", reply.message);
    Ok(())
}

```

Tool registration occurs in [`src/openhuman/tools/registry.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/registry.rs), while result artifacts are processed through [`src/openhuman/agent/harness/tool_result_artifacts/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/tool_result_artifacts/mod.rs).

## Summary

Embedding the OpenHuman agent requires minimal boilerplate:

- Import **`openhuman::Harness`** from the crate root
- Chain configuration methods on **`Harness::builder()`** to select providers, workspace type, and access tier
- Await **`build()`** to instantiate the runtime
- Use **`run()`** for single-turn requests or **`turn()`** for multi-turn sessions with transcript persistence
- Enable **`OPENHUMAN_SANDBOX_MODE`** environment variable before instantiation to allow tool execution

## Frequently Asked Questions

### What is the difference between `run()` and `turn()` methods in the Harness API?

**`run()`** executes a single prompt within a new session and returns the final message, making it ideal for one-shot tasks. **`turn()`** initiates or continues a multi-turn conversation, returning a `TurnHandle` that preserves session state across multiple async calls and exposes the transcript history.

### How do I persist agent state between process restarts?

Pass **`Workspace::Dir(path)`** to the builder instead of `Workspace::Ephemeral`. According to the implementation in [`src/openhuman/agent/harness/workspace.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/workspace.rs), this pins the action directory and artifact storage to a specific filesystem location, allowing the agent to resume from existing state on subsequent process launches.

### Can I use the OpenHuman Harness API with local LLMs or only cloud providers?

You can use any OpenAI-compatible endpoint. The **`Provider::openai_compatible()`** method in [`src/openhuman/agent/harness/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/provider.rs) accepts a custom base URL, enabling integration with local inference servers (such as Ollama or vLLM) that expose the OpenAI API schema, in addition to commercial cloud providers.

### How do I restrict the agent's ability to modify files?

Set the access tier to **`Access::readonly()`** or **`Access::supervised()`** via the builder method defined in [`src/openhuman/agent/harness/access.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness/access.rs). The `readonly` tier blocks all destructive tool invocations, while `supervised` requires explicit confirmation before executing write operations, encoding these constraints into the core `SecurityPolicy`.