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.tokenor set viaOPENHUMAN_CORE_TOKEN. - The JSON-RPC dispatcher in
src/core/jsonrpc/mod.rsroutes all external calls under theopenhuman.*namespace. - Environment variables such as
OPENHUMAN_CORE_REUSE_EXISTINGandOPENHUMAN_ACTION_DIRcontrol 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →