Workspace Architecture in OpenHuman: Action Directory, Workspace Directory, and the Two-Path-Root Security Invariant
OpenHuman enforces a strict two-path-root security invariant that isolates agent operations in action_dir (the sandbox) while protecting core state in workspace_dir, ensuring no file system access spans both roots.
OpenHuman implements a rigorous workspace architecture that separates agent filesystem access from internal core state. By dividing the filesystem into two distinct roots—action_dir for agent tools and workspace_dir for core internals—the platform prevents privilege escalation and data tampering. This design is enforced throughout the codebase in the tinyhumansai/openhuman repository through a strict security invariant implemented in the SecurityPolicy struct.
The Two-Path-Root Design
OpenHuman’s workspace architecture relies on two separate directory roots that serve fundamentally different purposes. This separation is defined in src/openhuman/config/schema/types.rs within the Config struct and enforced at runtime by the SecurityPolicy implementation.
action_dir: The Agent Sandbox
The action_dir serves as the read/write sandbox for all agent tools. Located by default at ~/OpenHuman/projects/ (derived from the user’s $HOME environment variable), this directory is where agents execute file operations, spawn shells, and store temporary outputs.
According to the source code in src/openhuman/config/schema/types.rs, this path populates the Config.action_dir field and is subsequently stored in the SecurityPolicy struct. When agents invoke tools like the shell implementation in src/openhuman/tools/impl/system/shell.rs, the working directory resolves against self.security.action_dir. Any attempt to access paths outside this root triggers a security rejection.
workspace_dir: Core Private State
The workspace_dir contains internal core state that only the OpenHuman core may access. Located at ~/.openhuman/users/<user-id>/workspace/, this directory houses sensitive resources including the memory database, approval files, and session artifacts.
Unlike action_dir, agents are never permitted to read from or write to this location. The Config.workspace_dir field, also defined in src/openhuman/config/schema/types.rs, establishes this boundary. Core services such as MemoryClient use this path exclusively, ensuring that internal state remains isolated from potentially untrusted agent code.
The Two-Path-Root Security Invariant
OpenHuman enforces an invariant that every file system access must be scoped to either action_dir or workspace_dir, never both. This prevents path traversal attacks and ensures complete isolation between agent capabilities and core internals.
The core-side SecurityPolicy in src/openhuman/security/policy.rs implements two critical validation functions:
-
is_workspace_internal_path– Returnstrueonly for paths residing underworkspace_dir. These paths are explicitly blocked for agent tools, guaranteeing that internal data cannot be tampered with from the agent side. -
is_action_dir_path– Validates that a requested path falls underaction_dir. If a tool attempts to access a location outside this root, the operation is denied with the error message "write rejected: forbidden path outside action_dir" as generated insrc/openhuman/tools/status/ops.rsat line 368.
This invariant is exercised throughout the codebase. Shell tools resolve their working directory via self.security.action_dir in src/openhuman/tools/impl/system/shell.rs, while file-write operations reject any path falling outside the action directory. Tests in tests/harness_embed.rs (lines 124‑125) assert that action_dir never starts with the workspace_dir prefix, ensuring the directories maintain proper separation even under configuration edge cases.
Implementation in Code
The security boundary manifests in concrete implementation patterns across the Rust codebase.
Creating a SecurityPolicy from user configuration:
// src/openhuman/config/schema/types.rs
let cfg = Config::load_or_init()?;
let security = SecurityPolicy {
action_dir: cfg.action_dir.clone(),
workspace_dir: cfg.workspace_dir.clone(),
// …other fields omitted
};
A tool validating write access against the action directory:
// Conceptual implementation based on src/openhuman/tools/status/ops.rs logic
fn write_file(security: &SecurityPolicy, path: &Path) -> Result<()> {
// Enforce the two‑path‑root invariant
if !security.is_action_dir_path(path) {
return Err(anyhow!("write rejected: forbidden path outside action_dir"));
}
// Normal write logic …
}
Core-only code accessing workspace internals:
// Core services access workspace_dir directly
fn load_memory(security: &SecurityPolicy) -> Result<MemoryClient> {
let db_path = security.workspace_dir.join("memory.db");
// This path is guaranteed never to be reachable by agents
MemoryClient::open(db_path)
}
The invariant is verified by test assertions:
// tests/harness_embed.rs lines 124‑125
#[test]
fn action_dir_not_inside_workspace() {
let harness = Harness::builder().build().await.unwrap();
assert!(!harness.action_dir().starts_with(&harness.workspace_dir()),
"action_dir must not sit inside the workspace");
}
Summary
- OpenHuman workspace architecture strictly separates agent filesystem access into two distinct roots:
action_dirfor agent operations andworkspace_dirfor core internals. action_dirdefaults to~/OpenHuman/projects/and serves as the sandbox where agents read and write files, execute shells, and operate without accessing sensitive system data.workspace_dirdefaults to~/.openhuman/users/<user-id>/workspace/and contains core state such as the memory database and session artifacts; agents are explicitly prohibited from accessing this root.- The two-path-root security invariant enforces that no single file operation can span both directories, with
is_workspace_internal_pathandis_action_dir_pathchecks insrc/openhuman/security/policy.rsproviding the enforcement mechanism. - Violation consequences include immediate rejection of file operations with the error "write rejected: forbidden path outside action_dir" when agents attempt to traverse outside their sandbox.
Frequently Asked Questions
What is the difference between action_dir and workspace_dir in OpenHuman?
action_dir is the agent's sandbox where tools read and write files, execute commands, and perform work, defaulting to ~/OpenHuman/projects/. workspace_dir is the core's private storage for internal state like the memory database and approval files, located at ~/.openhuman/users/<user-id>/workspace/ and completely inaccessible to agents. This separation ensures agents cannot corrupt system state or access sensitive user data.
How does OpenHuman prevent agents from accessing workspace_dir?
OpenHuman implements the is_workspace_internal_path check in src/openhuman/security/policy.rs that returns true only for paths under workspace_dir. Agent tools are configured to reject any operation where this check returns true, while core services use this same check to verify they are operating in the correct context. The SecurityPolicy struct maintains both paths and validates every file system request against these boundaries.
Where is the two-path-root security invariant enforced in the codebase?
The invariant is enforced in multiple locations: src/openhuman/security/policy.rs defines the validation logic through is_workspace_internal_path and is_action_dir_path; src/openhuman/tools/status/ops.rs (line 368) generates the forbidden path error message; src/openhuman/tools/impl/system/shell.rs resolves working directories against action_dir; and tests/harness_embed.rs (lines 124‑125) contains unit tests asserting that action_dir never resides within workspace_dir.
What happens if an agent tries to write outside action_dir?
The operation is immediately rejected with the error message "write rejected: forbidden path outside action_dir". This error originates from the tool operation logic in src/openhuman/tools/status/ops.rs when the is_action_dir_path check fails. The invariant ensures that agents cannot perform path traversal attacks to escape their sandbox or access system directories outside their designated action_dir root.
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 →