# OpenHuman Harness API: Run Agent Turns as Library Calls in Rust

> Discover how the OpenHuman Harness API enables embedding hosts to execute agent turns as library calls in Rust. Integrate agent logic seamlessly with the Harness API.

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

---

**The OpenHuman Harness API provides a typed façade that lets embedding hosts configure a `HarnessBuilder`, instantiate a single process-wide `CoreRuntime`, and execute agent turns via the `run()` or `turn()` methods.**

The OpenHuman framework enables developers to embed autonomous AI agents directly into Rust applications. The **OpenHuman Harness API** abstracts the complex bootstrap logic of the core runtime, exposing a clean interface for running agent turns as ordinary library calls. This article examines the implementation in `src/embed/harness/` and demonstrates how to configure providers, manage workspaces, and execute conversational turns.

## Initializing the OpenHuman Harness API with HarnessBuilder

The entry point for embedding hosts is the **`HarnessBuilder`** defined in [`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs) at line 22. This builder collects all runtime dependencies before instantiating the global core state.

Configuration parameters include:

- **Workspace**: Ephemeral or persistent directory for agent file operations
- **Provider**: Model endpoint configuration via [`src/embed/harness/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/provider.rs)
- **Access**: Permission tiers defined in [`src/embed/harness/access.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/access.rs)
- **Session**: Authentication context required for custom provider routing
- **Backend URL**: Optional redirection for telemetry and session checks away from the hosted TinyHumans backend

When `build().await?` is invoked, the builder constructs a `Config` and `DomainSet`/`ServiceSet` pair, then passes them to `CoreBuilder` in [`src/core/runtime/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/builder.rs). The implementation enforces a **single-instance constraint** per process using the `HARNESS_LIVE` atomic flag, which is cleared only when the `Harness` is dropped (see [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs) lines 85-88).

### Single Process Constraint and Runtime Requirements

Embedding hosts must supply their own Tokio runtime; the Harness does not create one. Per the constants defined in [`src/core/runtime/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/mod.rs), the runtime thread stack size must exceed `AGENT_WORKER_STACK_BYTES` to prevent overflow during sub-agent spawning. Attempting to instantiate a second `Harness` in the same process will panic due to the `HARNESS_LIVE` guard.

## Executing Agent Turns via the Harness API

Once initialized, the `Harness` struct in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs) exposes two methods for running agent turns:

**`run(message)`** – Creates a fresh `Turn`, applies default provider routes and model settings from the builder, then immediately dispatches the request. This method is ideal for stateless interactions.

**`turn(message)`** – Returns a mutable `Turn` builder from [`src/embed/agent/turn.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/agent/turn.rs) that allows customization of the model, access origin, or session ID before calling `.send().await`. Use this method when maintaining conversation state or overriding defaults.

Both methods are implemented at lines 38-63 of [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs) and require an active `Session` because the core gates custom provider routing behind session validation.

### Session and Provider Requirements

The `Session` parameter (e.g., `Session::local("my-host")`) is mandatory for embedding hosts using custom LLM providers. Without a valid session, the core rejects provider routing requests. For hosts running without TinyHumans backend accounts, the `backend_url` builder method redirects session checks and telemetry to an alternative endpoint.

## Complete Implementation Example

The following Rust code demonstrates a complete embedding host configuration using the OpenHuman Harness API:

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

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Configure the HarnessBuilder with provider and workspace settings
    let harness = Harness::builder()
        .provider(
            Provider::openai_compatible(
                "https://api.openai.com/v1",
                "sk-my-secret-key",
            )
            .model("gpt-4o")
        )
        .workspace(Workspace::Ephemeral)
        .access(Access::full())
        .session(Session::local("my-embedder"))
        .backend_url("https://my-backend.example")
        .build()
        .await?;

    // Execute a simple turn
    let outcome = harness
        .run("Summarize the OpenHuman architecture.")
        .await?;
    println!("Reply: {}", outcome.reply);

    // Continue with a custom turn maintaining session context
    let follow_up = harness
        .turn("What are the security guarantees?")
        .session(&outcome.session_id)
        .send()
        .await?;
    println!("Reply: {}", follow_up.reply);

    Ok(())
}

```

Key implementation details:

- `Provider::openai_compatible` configures a custom inference endpoint via [`src/embed/harness/provider.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/provider.rs)
- `Workspace::Ephemeral` creates a temporary directory bound to the `Harness` lifetime, handled in [`src/embed/harness/workspace.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/workspace.rs)
- `Session::local` satisfies authentication requirements without backend login
- The `turn()` method preserves conversation state via the `session_id` parameter before calling `send().await`

## Summary

- The **OpenHuman Harness API** lives in `src/embed/harness/` and provides the only sanctioned interface for embedding agents as library calls.
- **HarnessBuilder** at [`src/embed/harness/builder.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/builder.rs) collects configuration and enforces single-process instantiation via the `HARNESS_LIVE` flag cleared in the `Drop` implementation.
- **Agent turns** execute via `run()` for immediate dispatch or `turn()` for customizable interactions requiring mutable state.
- **Embedding hosts** must provide a Tokio runtime with sufficient stack size (`AGENT_WORKER_STACK_BYTES`) and a valid `Session` for custom provider routing.
- **Backend calls** can be redirected via `backend_url` for hosts operating without TinyHumans cloud accounts.

## Frequently Asked Questions

### Can I create multiple Harness instances in the same process?

No. The OpenHuman core runtime prohibits multiple concurrent `Harness` instances. The `HARNESS_LIVE` atomic flag in [`src/embed/harness/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/harness/mod.rs) ensures exactly one global `CoreRuntime` exists per process. Attempting to call `build()` twice will trigger a runtime panic. To manage multiple agent configurations, you must either restart the process or reconfigure the existing `Harness` instance.

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

The `run()` method executes a complete agent turn immediately using default configurations from the `HarnessBuilder`, returning the outcome directly. The `turn()` method returns a `Turn` builder from [`src/embed/agent/turn.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/embed/agent/turn.rs) that allows pre-send customization of models, access tiers, or session identifiers. Use `run()` for simple, stateless requests and `turn()` when you need to override defaults or maintain conversational context across multiple calls.

### Why does the Harness require a Session for custom providers?

The core gates all custom provider routing behind session validation as a security measure. The `Session` type—whether obtained via `Session::local()` for embedded hosts or through backend authentication—proves the host has permission to route inference requests to non-default endpoints. Without an active session, the `send()` method will return an authentication error when using custom `Provider` configurations.

### How do I configure the Tokio runtime for OpenHuman embedding?

Embedding hosts must initialize their own Tokio runtime before calling `Harness::builder()`. According to [`src/core/runtime/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/runtime/mod.rs), the runtime must use a thread stack size of at least `AGENT_WORKER_STACK_BYTES` (typically 2MB or larger) to accommodate recursive agent spawning. The Harness does not spawn its own async runtime or threads; it relies entirely on the host application's executor.