# How OpenHuman's Rust Core and React/Tauri Shell Architecture Works Together

> Discover how OpenHuman's Rust core and React/Tauri shell architecture integrate. Learn about their communication via JSON-RPC and security features for efficient desktop app development.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: architecture
- Published: 2026-08-29

---

**OpenHuman pairs a Rust-based core library handling all business logic with a React frontend embedded in a Tauri desktop shell, communicating via an in-memory JSON-RPC channel secured by a per-session bearer token.**

OpenHuman is an AI agent framework developed by tinyhumansai that separates high-performance backend operations from the user interface through a distinct two-layer architecture. The system centers on a portable Rust core that manages agents, memory, and tool execution, while the Tauri-based desktop application provides a React/TypeScript frontend. This design enables the core to run in-process as a background Tokio task, eliminating network latency while maintaining strict security boundaries.

## Core Startup Inside the Tauri Shell

When the desktop application launches, Tauri executes the `start_core_process` command defined in [`app/src-tauri/src/core_process.rs`](https://github.com/tinyhumansai/openhuman/blob/main/app/src-tauri/src/core_process.rs). This command constructs the core using `CoreBuilder`, configures the appropriate domain and service sets, and spawns the runtime as a Tokio task within the same process.

```rust
// app/src-tauri/src/core_process.rs (simplified)
let core = CoreBuilder::new()
    .domains(DomainSet::full())
    .services(ServiceSet::desktop())
    .build()
    .await?;
let handle = CoreProcessHandle::new(core);
handle.start().await?;

```

Upon initialization, the core binds to a random localhost port and generates a hex-encoded bearer token. The Tauri command `core_rpc_token` passes this token to the React UI, ensuring the credential lives only in process memory and never touches the filesystem.

## JSON-RPC Transport Layer

The Rust core exposes its public API through modules located in `src/openhuman/web_chat`, which register JSON-RPC controllers following the `openhuman.web_chat_*` naming convention. The file [`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs) automatically discovers these controllers, while [`src/core/jsonrpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/jsonrpc.rs) handles request routing through a generic dispatcher.

The transport layer implements a lightweight HTTP server that authenticates requests via the `Authorization: Bearer <token>` header. This in-memory token validation ensures that only the local UI instance can invoke core methods during the application lifecycle.

## React UI Integration and RPC Client

The React frontend communicates with the core through the `coreRpcClient` service located at [`app/src/services/coreRpcClient.ts`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/services/coreRpcClient.ts). This client constructs requests to `http://127.0.0.1:<port>/rpc`, injects the bearer token retrieved from the Tauri backend, and serializes method calls according to the JSON-RPC 2.0 specification.

```typescript
// app/src/services/coreRpcClient.ts (simplified)
export async function invokeRpc<T>(method: string, params: unknown) {
  const token = await invoke<string>('core_rpc_token', {});
  const resp = await fetch(`http://127.0.0.1:${port}/rpc`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params }),
  });
  const { result } = await resp.json();
  return result as T;
}

```

The application bootstrap in [`app/src/App.tsx`](https://github.com/tinyhumansai/openhuman/blob/main/app/src/App.tsx) establishes a provider chain that exposes this client throughout the component tree:

```

Sentry.ErrorBoundary → Redux Provider → PersistGate → CoreStateProvider → 
SocketProvider → ChatRuntimeProvider → HashRouter → CommandProvider

```

The `CoreStateProvider` initializes the connection by invoking `coreRpcClient.invokeRpc('openhuman.web_chat_snapshot', …)` to synchronize the UI state with the core's current snapshot.

## Real-Time Data Flow: Processing a Chat Turn

The architecture handles real-time agent interactions through an event-driven pipeline. When a user submits a message, the data flows through these layers:

1. **UI Action**: The React component calls `coreRpcClient.invokeRpc('openhuman.web_chat_turn', { prompt })`.

2. **Core Processing**: The request reaches [`src/openhuman/web_chat/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web_chat/ops.rs), which instantiates a `Harness` (defined in [`src/openhuman/medulla/contract.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/medulla/contract.rs)) to execute the agent turn.

3. **Event Streaming**: As the agent processes the turn, it generates `HarnessEvent` payloads representing tool calls, tool results, and message chunks. These stream back to the UI through the persistent RPC connection.

4. **State Synchronization**: The `ChatRuntimeProvider` consumes these events, dispatches updates to the Redux store, and triggers re-renders of the conversation interface.

## Security Model and Process Isolation

OpenHuman implements multiple security layers to protect against unauthorized tool execution and data exfiltration.

**Per-Session Authentication**: The bearer token generated at startup in [`core_process.rs`](https://github.com/tinyhumansai/openhuman/blob/main/core_process.rs) acts as a capability token. Any process lacking this specific token cannot communicate with the core's JSON-RPC endpoint, effectively sandboxing the API within the single application instance.

**Approval Gates**: The core enforces user confirmation for sensitive operations through the mechanism defined in [`src/openhuman/security/approval.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval.rs). This gate can pause tool execution mid-harness until the UI receives explicit user consent.

**Tool Policy Enforcement**: All I/O operations route through [`src/openhuman/tools/policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/policy.rs), which evaluates permissions against the current execution tier and enforces sandbox limits, timeouts, and resource constraints.

```rust
// Rust: launching the core from the Tauri command (core_process.rs)
#[tauri::command]
pub async fn start_core_process() -> Result<(), String> {
    let core = CoreBuilder::new()
        .domains(DomainSet::full())
        .services(ServiceSet::desktop())
        .build()
        .await
        .map_err(|e| e.to_string())?;
    CoreProcessHandle::new(core).start().await.map_err(|e| e.to_string())
}

```

```typescript
// TypeScript: sending a chat turn from a React component
import { invokeRpc } from '../services/coreRpcClient';

async function sendTurn(prompt: string) {
  const turnResult = await invokeRpc<any>('openhuman.web_chat_turn', { prompt });
  console.log('Turn started', turnResult);
}

```

## Summary

- **In-Process Architecture**: The Rust core runs as a Tokio task inside the Tauri process, eliminating network overhead while maintaining logical separation from the React UI.
- **Secure JSON-RPC Channel**: Communication occurs over localhost HTTP with a per-session bearer token generated in [`core_process.rs`](https://github.com/tinyhumansai/openhuman/blob/main/core_process.rs) and validated by the dispatcher in [`src/core/jsonrpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/jsonrpc.rs).
- **Provider Chain Pattern**: The React frontend initializes the RPC client through nested providers in [`App.tsx`](https://github.com/tinyhumansai/openhuman/blob/main/App.tsx), making core methods available throughout the component tree via [`coreRpcClient.ts`](https://github.com/tinyhumansai/openhuman/blob/main/coreRpcClient.ts).
- **Event-Driven Updates**: Agent turns produce streaming `HarnessEvent` payloads from [`src/openhuman/medulla/contract.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/medulla/contract.rs) that update the UI in real-time without polling.
- **Layered Security**: The combination of in-memory tokens, approval gates in [`src/openhuman/security/approval.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval.rs), and tool policies in [`src/openhuman/tools/policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/policy.rs) ensures fine-grained control over agent capabilities.

## Frequently Asked Questions

### How does the React frontend discover the Rust core's port and authentication token?

When Tauri launches the application, the `start_core_process` command in [`app/src-tauri/src/core_process.rs`](https://github.com/tinyhumansai/openhuman/blob/main/app/src-tauri/src/core_process.rs) starts the core on a random available port and generates a hex-encoded bearer token. The React UI retrieves this token by invoking the Tauri command `core_rpc_token`, which returns the in-memory credential needed to authenticate JSON-RPC requests to the local HTTP endpoint.

### Can the Rust core run independently of the Tauri desktop application?

Yes. The core is designed as a portable library that can be embedded in multiple contexts. While the desktop shell uses `CoreBuilder` with `ServiceSet::desktop()` to run in-process, the same core can operate in CLI mode, Docker containers, or remote services by configuring different service sets. The JSON-RPC interface remains consistent regardless of the host environment.

### What prevents unauthorized applications from accessing the core's JSON-RPC endpoint?

Security relies on the per-session bearer token that exists only in the memory of the running process. Since the token is randomly generated at startup and never written to disk or exposed through environment variables, external processes cannot authenticate requests to `http://127.0.0.1:<port>/rpc`. Additionally, the core binds exclusively to localhost, refusing external network connections.

### How does the system handle long-running agent operations without blocking the UI?

The Rust core processes agent turns asynchronously using Tokio tasks defined in [`src/openhuman/web_chat/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web_chat/ops.rs). Rather than waiting for the entire turn to complete, the core streams `HarnessEvent` objects back to the React client as they occur. The `ChatRuntimeProvider` in the UI layer consumes these events incrementally, allowing the interface to render partial results and tool execution status while the background task continues processing.