# Understanding `action_dir` vs `workspace_dir` in OpenHuman: Security Boundaries Explained

> Learn the difference between OpenHuman's action_dir and workspace_dir. Understand their security roles and how they protect sensitive data in AI agent operations.

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

---

**OpenHuman's `action_dir` serves as a sandboxed directory where AI agents can read and write files, while `workspace_dir` acts as a protected vault storing encrypted credentials and core state, with the core enforcing strict isolation to prevent agents from accessing sensitive data.**

The `tinyhumansai/openhuman` repository implements a dual-directory security model in its Rust core to separate agent operations from confidential system data. Understanding the distinction between **`action_dir`** and **`workspace_dir`** is critical for deploying secure AI workflows, as these paths define the boundary between untrusted agent code and sensitive user credentials stored in the core workspace.

## Core Concepts: The Agent Sandbox vs. The Core Vault

### `action_dir`: The Agent Read/Write Root

The **`action_dir`** represents the filesystem root that tools and agents may access for all file operations. According to the source code in [`src/openhuman/security/policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy.rs), this directory defaults to `$HOME/OpenHuman/projects` (or the `OPENHUMAN_ACTION_DIR` environment variable) and serves as the anchor for all relative paths supplied to tools.

When an agent executes file operations—such as `file_read`, `file_write`, or shell commands—the core resolves these against `action_dir`. For example, in [`src/openhuman/tools/impl/system/shell.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/impl/system/shell.rs), the shell tool resolves its current working directory to `security.action_dir`, ensuring all command execution occurs within the sandbox.

### `workspace_dir`: The Protected Core Workspace

Conversely, the **`workspace_dir`** functions as an internal store for OpenHuman's persistent state, including the SQLite key-ring, encrypted OAuth tokens, and session caches. Located at `$HOME/.openhuman` by default (overridable via `OPENHUMAN_WORKSPACE_DIR`), this directory is never exposed to agent tools or implementations.

As implemented in the configuration schema, the core uses this path exclusively for internal persistence mechanisms like `core_state`, `keyring`, and `credential_store`. The strict confidentiality boundary ensures that private keys and authentication data remain inaccessible to potentially untrusted agent code.

## Security Implications and Enforcement Mechanisms

### Isolation Through Path Validation

The core enforces that agents cannot escape the `action_dir` sandbox. In [`src/openhuman/tools/status/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/status/ops.rs) (line 368), the implementation checks that any target path starts with the `action_dir` prefix before allowing file writes. If a tool attempts to access a path outside this boundary, the core returns a "forbidden path outside action_dir" error, preventing directory traversal attacks.

### The Subdirectory Invariant

A critical security policy prevents `action_dir` from being a subdirectory of `workspace_dir`. The test in [`tests/harness_embed.rs`](https://github.com/tinyhumansai/openhuman/blob/main/tests/harness_embed.rs) (lines 124-125) asserts this invariant, verifying that the agent's working directory never starts with the workspace path. This prevents configuration mistakes that would grant agents indirect access to encrypted credentials stored in the workspace.

Violating this rule would allow malicious or buggy agents to read or modify private data, making the check a hard security guard that fails at compile-time during testing.

## Configuring OpenHuman Directories

You can override these paths when constructing the core:

```rust
use openhuman_core::{CoreBuilder, Config};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let core = CoreBuilder::new()
        .config(Config {
            action_dir: PathBuf::from("/tmp/agent-sandbox"),
            workspace_dir: PathBuf::from("/var/lib/openhuman/private"),
            ..Default::default()
        })
        .build()
        .await?;
    
    Ok(())
}

```

When implementing custom tools, always validate paths against the security policy:

```rust
use std::path::Path;
use openhuman_core::security::SecurityPolicy;

fn write_agent_file(
    security: &SecurityPolicy, 
    rel_path: &Path, 
    data: &[u8]
) -> Result<(), std::io::Error> {
    let dest = security.action_dir.join(rel_path);
    
    // Enforce the action_dir boundary
    if !dest.starts_with(&security.action_dir) {
        return Err(std::io::Error::new(
            std::io::ErrorKind::PermissionDenied,
            "forbidden path outside action_dir"
        ));
    }
    
    std::fs::write(dest, data)
}

```

## Summary

- **`action_dir`** acts as a public sandbox for agent file operations, defaulting to `$HOME/OpenHuman/projects`, with all paths validated against this root via checks in [`src/openhuman/tools/status/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/status/ops.rs).
- **`workspace_dir`** serves as a private vault for core secrets and state, defaulting to `$HOME/.openhuman`, and remains completely isolated from agent access according to the `SecurityPolicy` in [`src/openhuman/security/policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy.rs).
- The core enforces isolation at runtime through path prefix checks that reject any file operation attempting to escape the action directory.
- Compile-time tests in [`tests/harness_embed.rs`](https://github.com/tinyhumansai/openhuman/blob/main/tests/harness_embed.rs) guarantee that `action_dir` can never reside inside `workspace_dir`, preventing credential leakage through misconfiguration.
- Both directories are configurable via environment variables (`OPENHUMAN_ACTION_DIR`, `OPENHUMAN_WORKSPACE_DIR`) or programmatically via `CoreBuilder`.

## Frequently Asked Questions

### Can I set `action_dir` inside `workspace_dir`?

No. The core's security policy explicitly forbids this configuration. The test suite in [`tests/harness_embed.rs`](https://github.com/tinyhumansai/openhuman/blob/main/tests/harness_embed.rs) validates that `action_dir` never starts with the `workspace_dir` path. Placing the agent directory inside the workspace would violate the confidentiality boundary, potentially exposing encryption keys and OAuth tokens to agent processes.

### What happens if an agent tries to access files outside `action_dir`?

The core rejects the operation with a permission error. In [`src/openhuman/tools/status/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/status/ops.rs), the system validates that all target paths start with the `action_dir` prefix before executing file operations. Any attempt to traverse upward or access absolute paths outside the sandbox results in a "forbidden path outside action_dir" error.

### How do I configure these directories using environment variables?

Set `OPENHUMAN_ACTION_DIR` to override the default sandbox location and `OPENHUMAN_WORKSPACE_DIR` to change the core workspace path. These values are parsed during configuration initialization and stored in the `SecurityPolicy` struct defined in [`src/openhuman/security/policy.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/policy.rs).

### Why does OpenHuman separate these directories instead of using a single location?

The separation maintains a clear trust boundary between untrusted agent code and sensitive core data. The `action_dir` contains user-controlled project files that agents can freely modify, while the `workspace_dir` houses the SQLite key-ring and encrypted credentials that only the core should touch. This architecture prevents agents from accidentally or maliciously corrupting authentication data while allowing safe file operations in the sandbox.