# How to Integrate OpenHuman with Other Systems: A Complete JSON-RPC Guide

> Integrate OpenHuman with other systems using its JSON-RPC HTTP server for seamless external program control. Connect via bearer token auth and send HTTP POST requests to invoke agent methods and device commands.

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

---

**Integrate OpenHuman with other systems by connecting to its local JSON-RPC HTTP server using bearer token authentication, enabling external programs to invoke agent methods and device commands via standard HTTP POST requests.**

OpenHuman is an open-source AI agent platform built around a Rust core that exposes a local JSON-RPC interface. Whether you are building automation scripts, third-party plugins, or enterprise integrations, understanding how to integrate OpenHuman with other systems allows you to leverage its agent execution capabilities from any programming language or environment.

## Architecture Overview

The integration architecture centers on a **Rust core binary** (`openhuman-core`) that runs an HTTP server on a dynamically assigned port. According to the source code in [`src/main.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/main.rs), the server starts automatically and writes a bearer token to `~/.openhuman/core.token` for client authentication.

The JSON-RPC dispatcher, implemented in [`src/core/jsonrpc/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/jsonrpc/mod.rs), handles all remote procedure calls under the `openhuman.*` namespace. The desktop UI communicates via the Tauri command `core_rpc_relay`, which forwards calls to the same endpoint used by external clients. The transport abstraction supports LAN, tunnel, or cloud strategies as detailed in the [`gitbooks/developing/architecture.md`](https://github.com/tinyhumansai/openhuman/blob/main/gitbooks/developing/architecture.md) guide.

### Token-Based Security Model

Security relies on a bearer token system defined in [`src/openhuman/config/schema/types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/types.rs). When the core starts, it generates a token and persists it to the filesystem. Clients must include this token in the `Authorization: Bearer <token>` header with every request. The Tauri-based desktop UI uses this same mechanism, meaning external integrations follow an identical authentication pattern to the native interface.

Frontend configuration management in [`app/src/utils/config.ts`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/utils/config.ts) handles the token retrieval and port configuration for the Tauri UI, providing a reference implementation for client-side integration logic.

## Environment Configuration for Integration

Before starting the core, configure these environment variables loaded by [`scripts/load-dotenv.sh`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/load-dotenv.sh):

- **OPENHUMAN_CORE_REUSE_EXISTING**: Set to reuse an already-running core instance rather than spawning a new process.
- **OPENHUMAN_CORE_TOKEN**: Supply a static bearer token for non-interactive clients, bypassing the automatic token file generation.
- **OPENHUMAN_ACTION_DIR**: Define the filesystem root where agents may read and write files during execution.

These variables are available to both the Rust core and the Tauri UI frontend, ensuring consistent configuration across the stack.

## Connecting to the JSON-RPC Server

### Step 1: Start the Core

Launch the HTTP server using Cargo:

```bash
cargo run --bin openhuman-core serve

```

The server binds to a local port and prints the listening address. It simultaneously writes the authentication token to `~/.openhuman/core.token`.

### Step 2: Read the Bearer Token

Retrieve the token for your client application:

```bash
cat ~/.openhuman/core.token

```

Alternatively, set `OPENHUMAN_CORE_TOKEN` to a predefined value before starting the core to enable static authentication.

### Step 3: Send JSON-RPC Requests

Post requests to `http://127.0.0.1:<port>/rpc` with the proper authorization header. All methods use the JSON-RPC 2.0 specification under the `openhuman.*` namespace.

## Integration Code Examples

### Shell Integration with curl

List available devices using a standard curl command:

```bash
TOKEN=$(cat ~/.openhuman/core.token)
PORT=45321   # Replace with the port printed by the core

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"jsonrpc":"2.0","id":1,"method":"openhuman.devices_list","params":{}}' \
  http://127.0.0.1:$PORT/rpc

```

### Node.js Client Implementation

Execute an agent from a Node.js application using `node-fetch`:

```javascript
import fetch from 'node-fetch';
import { readFile } from 'fs/promises';

const token = await readFile(`${process.env.HOME}/.openhuman/core.token`, 'utf8');
const port = 45321; // Replace with actual port

const request = {
  jsonrpc: '2.0',
  id: 1,
  method: 'openhuman.agent_execute',
  params: { name: 'my-agent', input: 'hello' }
};

const response = await fetch(`http://127.0.0.1:${port}/rpc`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token.trim()}`
  },
  body: JSON.stringify(request)
});

console.log(await response.json());

```

### Native Rust Client

For Rust applications, use `reqwest` to communicate with the core:

```rust
use reqwest::blocking::Client;
use std::{fs, path::PathBuf};

fn main() -> anyhow::Result<()> {
    let token_path = PathBuf::from(env!("HOME")).join(".openhuman/core.token");
    let token = fs::read_to_string(token_path)?.trim().to_string();
    let port = 45321; // Replace with actual port

    let client = Client::new();
    let payload = serde_json::json!({
        "jsonrpc": "2.0",
        "id": 1,
        "method": "openhuman.agent_execute",
        "params": { "name": "my-agent", "input": "hello" }
    });

    let resp = client
        .post(&format!("http://127.0.0.1:{}/rpc", port))
        .bearer_auth(&token)
        .json(&payload)
        .send()?
        .json::<serde_json::Value>()?;

    println!("Response: {:#?}", resp);
    Ok(())
}

```

## Extending OpenHuman with Custom Tools

OpenHuman supports custom integrations through the **Tool trait**. Agents can invoke tools to perform actions like HTTP requests or shell commands. Each tool implements the trait defined in [`src/openhuman/tools/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/mod.rs).

To add a custom HTTP integration tool, implement the `Tool` trait:

```rust
// src/openhuman/tools/impl/http.rs
use super::Tool;
use reqwest::blocking::Client;

pub struct HttpTool {
    client: Client,
}

impl HttpTool {
    pub fn new() -> Self {
        Self { client: Client::new() }
    }
}

impl Tool for HttpTool {
    fn name(&self) -> &'static str { "http" }

    fn execute(&self, args: serde_json::Value) -> anyhow::Result<serde_json::Value> {
        let url = args["url"]
            .as_str()
            .ok_or_else(|| anyhow::anyhow!("missing `url` argument"))?;
        let resp = self.client.get(url).send()?;
        let body = resp.text()?;
        Ok(serde_json::json!({
            "status": resp.status().as_u16(),
            "body": body
        }))
    }
}

```

Register the tool in [`src/openhuman/tools/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/mod.rs) and rebuild the core to expose the new functionality to agents.

## Summary

- OpenHuman exposes a **JSON-RPC HTTP server** via the Rust core ([`src/main.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/main.rs)), allowing any HTTP client to integrate.
- Authentication requires a **bearer token** written to `~/.openhuman/core.token` or set via `OPENHUMAN_CORE_TOKEN`.
- The **JSON-RPC dispatcher** in [`src/core/jsonrpc/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/jsonrpc/mod.rs) routes all external calls under the `openhuman.*` namespace.
- **Environment variables** such as `OPENHUMAN_CORE_REUSE_EXISTING` and `OPENHUMAN_ACTION_DIR` control core behavior and filesystem access.
- Custom integrations extend capabilities by implementing the **Tool trait** in [`src/openhuman/tools/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/mod.rs).

## Frequently Asked Questions

### What port does OpenHuman use for JSON-RPC?

OpenHuman uses a dynamically assigned port selected by the operating system when the core starts. The port is printed to stdout and can be discovered by examining the core output. External clients must use this specific port for all JSON-RPC requests to `http://127.0.0.1:<port>/rpc`.

### How do I authenticate external clients with OpenHuman?

External clients authenticate using a **bearer token** mechanism. The core writes a token to `~/.openhuman/core.token` on startup as implemented in [`src/openhuman/config/schema/types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/types.rs). Clients must include this token in the `Authorization: Bearer <token>` HTTP header with every request. For automated systems, set `OPENHUMAN_CORE_TOKEN` to a static value before starting the core.

### Can I run multiple OpenHuman core instances simultaneously?

By default, starting a new core instance will spawn a separate server. Set `OPENHUMAN_CORE_REUSE_EXISTING` to connect to an already-running instance rather than starting a new one. This environment variable, loaded by [`scripts/load-dotenv.sh`](https://github.com/tinyhumansai/openhuman/blob/main/scripts/load-dotenv.sh), prevents port conflicts and ensures your integration connects to the correct singleton core.

### How do I add custom integrations to OpenHuman?

Custom integrations require implementing the **Tool trait** in Rust. Create a new struct implementing the trait methods (`name()` and `execute()`), then register it in [`src/openhuman/tools/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/mod.rs). Rebuild the core with `cargo build` to include the new tool. Agents can then invoke your custom tool by name during execution, enabling integration with external APIs, databases, or hardware devices.