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

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, 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, 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 guide.

Token-Based Security Model

Security relies on a bearer token system defined in 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 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:

  • 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:

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:

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:

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:

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:

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.

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

// 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 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), 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 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.

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. 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, 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →