Purpose of the HTTP and Socket.IO Transport Layer in OpenHuman Core
The HTTP and Socket.IO transport layer in OpenHuman implements a dual-socket architecture that separates synchronous command execution from real-time event streaming, allowing the React/Tauri frontend to invoke RPC methods over HTTP while receiving asynchronous state updates via WebSocket.
The tinyhumansai/openhuman repository implements a Rust-based core process that must communicate bidirectionally with a React and Tauri desktop interface. To handle both request-response commands and continuous data streams without blocking, the core exposes two complementary transport mechanisms: an HTTP JSON-RPC endpoint for control operations and a Socket.IO channel for real-time events.
Dual-Socket Architecture Overview
OpenHuman’s transport layer follows a control plane / data plane separation. The HTTP transport serves as the control plane, handling isolated, stateless RPC calls that return immediate responses. The Socket.IO transport functions as the data plane, pushing high-frequency updates—including chat turns, tool-result deltas, and approval requests—to connected clients without polling.
This design prevents long-running streams from blocking command execution. When the core processes a tool invocation, the HTTP request returns immediately while the actual progress streams through the Socket.IO connection.
HTTP JSON-RPC Transport for Synchronous Commands
The HTTP transport exposes the core’s RPC methods at the /rpc endpoint using the JSON-RPC 2.0 protocol. This provides a simple request-response API that the Tauri frontend consumes through the relay_http_rpc command, which forwards browser-side requests to the Rust core.
The endpoint handles actions such as fetching configuration, starting conversation turns, and invoking tools. Each call is dispatched through the core’s internal JSON-RPC handler implemented in src/core/jsonrpc.rs, returning structured responses to the caller.
Implementation Details
In src/core/jsonrpc.rs, the core initializes an HTTP listener that routes incoming POST requests to the appropriate internal controllers. The React frontend accesses this through coreRpcClient.ts, which packages method calls and parameters into JSON-RPC payloads.
For example, initiating a conversation turn requires a single HTTP request:
// coreRpcClient.ts – invokes the start_turn RPC method
await coreRpcClient.call('openhuman.turns_start', {
thread_id: conversationId,
prompt: userMessage
});
The core processes this synchronously and returns the new turn ID, while the actual message streaming occurs over the Socket.IO transport.
Socket.IO Transport for Real-Time Event Streaming
The Socket.IO transport opens a persistent WebSocket connection at /socket.io, enabling the core to broadcast asynchronous events to all connected clients. This mechanism delivers incremental updates for chat messages, tool execution progress, artifact status changes, and security approval requests.
All real-time domain events originate on the core’s internal event bus and bridge to Socket.IO in src/core/socketio.rs. The central event type, WebChannelEvent, defined at line 138, standardizes the payload structure emitted to frontends.
WebChannelEvent Structure and Broadcasting
The WebChannelEvent struct encapsulates events with a namespace, name, and JSON payload. When the core publishes an event, the socketio module translates it into a Socket.IO emission. For instance, when a tool requires user approval, the security gate emits an event that propagates to the UI:
// src/openhuman/security/approval/gate.rs
crate::core::socketio::emit_web_channel_event(WebChannelEvent {
namespace: "approval".into(),
name: "request".into(),
payload: serde_json::json!({
"request_id": request_id,
"agent": agent_name
}),
});
This event flows from the internal bus to the socket bridge at line 34 of src/core/socketio.rs, which broadcasts it to all connected clients immediately.
Frontend Integration Patterns
The React frontend consumes both transports through dedicated services. The coreRpcClient manages HTTP JSON-RPC calls, while services/socketService.ts maintains a singleton Socket.IO client that maps incoming WebChannelEvent objects to Redux state updates.
When the core emits a tool result delta, the socket service dispatches it to the appropriate slice:
// services/socketService.ts
socket.on('tool:result', (event: WebChannelEvent) => {
// event contains the incremental tool output
dispatch(updateToolResult(event.payload));
});
This architecture ensures the UI remains synchronized with the core’s internal state without blocking the main thread on long-running operations.
Summary
- OpenHuman uses HTTP JSON-RPC at
/rpcfor synchronous command execution (control plane) and Socket.IO at/socket.iofor asynchronous event streaming (data plane). - The
WebChannelEventtype insrc/core/socketio.rs(line 138) standardizes real-time payloads broadcast to the React/Tauri frontend. - HTTP requests are handled by
src/core/jsonrpc.rsand consumed viarelay_http_rpcin Tauri, while Socket.IO events bridge the core’s internal bus to the frontend throughservices/socketService.ts. - This dual-socket design prevents blocking: commands return immediately via HTTP while progress streams continuously via WebSocket.
Frequently Asked Questions
Why does OpenHuman use two transports instead of a single WebSocket?
Using separate transports decouples command execution from event streaming. HTTP JSON-RPC provides a simple, stateless interface for actions that require immediate confirmation, while Socket.IO handles high-frequency, push-style updates without blocking the request-response cycle. This separation keeps the core responsive when processing long-running tool invocations.
What is WebChannelEvent in OpenHuman?
WebChannelEvent is the core event struct defined at line 138 of src/core/socketio.rs that encapsulates all real-time communications between the Rust core and the frontend. It contains a namespace, event name, and JSON payload, standardizing how chat turns, tool results, and approval requests transmit over the Socket.IO connection.
How does the Tauri frontend communicate with the OpenHuman core?
The Tauri frontend uses two mechanisms: it invokes relay_http_rpc to forward JSON-RPC calls to the HTTP endpoint at /rpc, and it connects to services/socketService.ts to receive WebSocket events from /socket.io. This dual approach allows the React UI to both command the core and subscribe to its internal event bus.
Can remote clients connect to OpenHuman's transport layer?
Yes, according to the architecture documentation, remote frontends can connect through the same endpoints used by the local Tauri UI. The HTTP JSON-RPC endpoint and Socket.IO server accept connections from any client that can reach the core’s network interface, enabling remote monitoring and control through the TunnelTransport relay.
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 →