# How OpenHuman's Privacy Mode Prevents Inference Data from Leaving the Machine

> Discover how OpenHuman's privacy mode stops inference data from leaving your machine by blocking network requests and disabling remote bridges. Keep your data local and secure.

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

---

**OpenHuman's privacy mode enforces a runtime `LocalOnly` policy that atomically blocks every outbound network request, discards cloud-bound audio segments, and disables remote chat bridges before any inference data can egress the local machine.**

OpenHuman, maintained by tinyhumansai, is an open-source framework that balances local inference with optional cloud-connected features. OpenHuman's privacy mode guarantees that prompts, audio, and model outputs remain on-device by gating all potential egress paths through a single live-policy lock. Because the mode is hot-swappable via RPC, users can switch to `LocalOnly` instantly without restarting the core.

## Privacy Mode Architecture and Live Policy

The privacy setting originates in the user configuration (`config.privacy.mode`) and is injected into a global **SecurityPolicy** when the core initializes.

In [`src/openhuman/security/policy/types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy/types.rs), the policy struct holds the mode:

```rust
pub struct SecurityPolicy {
    // ...,
    pub privacy_mode: PrivacyMode,
}

```

At startup, the core copies this value into a process-wide `RwLock` managed by the live-policy layer in [`src/openhuman/security/live_policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/live_policy.rs):

```rust
let mut guard = state.privacy_mode.write()?;
*guard = policy.privacy_mode;

```

This `live_policy` guard allows every component to read the active mode without reloading the entire configuration. When a user changes the setting through the `openhuman.config_set_privacy_mode` RPC handler defined in [`src/openhuman/config/rpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/rpc.rs), the system creates a new `SecurityPolicy` that differs only in `privacy_mode` and atomically replaces the locked value. This hot-swap design means the policy survives unrelated configuration reloads and remains effective until explicitly changed.

## Network Egress Enforcement Points

Every tool that could transmit data off-device checks `live_policy::current_privacy_mode()` immediately before the actual network operation. If the active mode is `LocalOnly`, the operation aborts.

### HTTP Request Guard

The generic HTTP tool in [`src/openhuman/tools/impl/network/http_request.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/network/http_request.rs) blocks outbound requests before building an egress descriptor:

```rust
if matches!(live_policy::current_privacy_mode(), PrivacyMode::LocalOnly) {
    tracing::debug!(target: "[http-request]", "blocked: local-only privacy mode");
    return Err(Error::PrivacyMode);
}

```

This check prevents REST API calls, telemetry pings, and remote model inference from leaving the machine.

### Web Fetch Tool

The async web-fetch implementation in [`src/openhuman/tools/impl/network/web_fetch.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/network/web_fetch.rs) applies the identical gate:

```rust
if matches!(live_policy::current_privacy_mode(), PrivacyMode::LocalOnly) {
    // block the fetch
}

```

Because both the synchronous HTTP tool and the async fetch tool enforce the same rule, no remote download can occur while privacy mode is active.

### Voice Processing Pipeline

In [`src/openhuman/voice/always_on.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/voice/always_on.rs), the always-on audio pipeline inspects the privacy flag before transmitting long-running segments:

```rust
if privacy_mode_is_enabled {
    // drop audio segment and reset the processor
}

```

If privacy mode is on, the segment is discarded entirely, ensuring intermediate audio data never reaches a cloud transcription or inference service.

### Web Chat Progress Bridge

The progress bridge in [`src/openhuman/web_chat/progress_bridge.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/web_chat/progress_bridge.rs) contains a storage-level privacy gate that disables forwarding captured content to the backend:

```rust
// Storage-level privacy gate (#4454): capture_content (off by default)

```

With this bridge disabled, chat history and captured content remain purely local.

## How to Toggle and Verify Privacy Mode

Users and developers can interact with the privacy mode through the RPC surface without restarting OpenHuman.

### Query the Current Mode

In [`src/tui/controls.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/tui/controls.rs), the TUI queries the live state:

```rust
let privacy = runtime.invoke("openhuman.config_get_privacy_mode", json!({}));
match privacy {
    Ok(mode) => { /* display current mode */ }
    Err(_) => { /* handle error */ }
}

```

### Set the Mode at Runtime

To atomically switch to `LocalOnly`, invoke the setter RPC:

```rust
runtime.invoke(
    "openhuman.config_set_privacy_mode",
    json!({ "mode": "LocalOnly" })
);

```

This call updates the `RwLock` in [`src/openhuman/security/live_policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/live_policy.rs), and all subsequent egress checks immediately see the new value.

### Add Privacy Checks to Custom Tools

Third-party tools can reuse the same gate by importing the live-policy module:

```rust
use openhuman::security::live_policy;

fn maybe_send_request() -> Result<()> {
    if matches!(live_policy::current_privacy_mode(), PrivacyMode::LocalOnly) {
        tracing::debug!("privacy mode active – aborting outbound request");
        return Err(Error::PrivacyMode);
    }
    // normal request logic ...
    Ok(())
}

```

For configuration reloads that need to refresh the policy without an RPC call, use the reload helper:

```rust
use openhuman::security::live_policy::reload_privacy;

fn apply_new_mode(new_mode: PrivacyMode) -> Result<()> {
    reload_privacy(new_mode)?;
    Ok(())
}

```

## Summary

- OpenHuman's privacy mode is stored in `config.privacy.mode` and injected into a global `SecurityPolicy` at startup.
- A process-wide `RwLock` inside `openhuman::security::live_policy` holds the active `PrivacyMode`, allowing atomic, runtime hot-swaps.
- The `openhuman.config_set_privacy_mode` RPC updates the lock without restarting the core.
- Every potential egress point—including HTTP requests, web fetches, voice audio segments, and web-chat bridges—reads `live_policy::current_privacy_mode()` and aborts if `LocalOnly` is active.
- Custom tools can import the same live-policy module to enforce consistent privacy guarantees.

## Frequently Asked Questions

### What happens to inference requests when OpenHuman's privacy mode is set to LocalOnly?

All outbound inference requests are blocked at the network layer. Both the HTTP request tool and the web fetch tool check `live_policy::current_privacy_mode()` before opening any connection and return `Error::PrivacyMode` immediately if `LocalOnly` is active.

### Can I switch privacy modes without restarting OpenHuman?

Yes. The live-policy layer uses an `RwLock` that is atomically updated through the `openhuman.config_set_privacy_mode` RPC. As soon as the lock is written, every component sees the new mode, so no restart is required.

### Does privacy mode affect local inference performance?

No. OpenHuman's privacy mode is purely an egress gate; it does not alter local model execution or throttle compute. It only prevents data from leaving the machine by blocking network operations and discarding audio segments destined for cloud services.

### How does the voice pipeline handle audio when privacy mode is enabled?

In [`src/openhuman/voice/always_on.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/voice/always_on.rs), long-running audio segments are dropped and the processor resets when the privacy flag is active. This ensures no audio buffer is queued for remote transcription or cloud inference.