Understanding the OpenHuman Command Permission Model: From classify_command to Autonomy Tiers
OpenHuman enforces security through a three-stage command permission model that classifies incoming requests into coarse-grained categories, evaluates them against configurable autonomy tiers, and returns explicit Allow, Prompt, or Block decisions before execution.
The tinyhumansai/openhuman repository implements a robust command permission model that governs how AI agents execute tools, filesystem operations, and network requests. This security framework maps raw RPC calls to structured permission classes and validates them against user-defined autonomy boundaries configured in ~/.openhuman/config.toml. The implementation spans three core Rust modules that handle command classification, policy evaluation, and tier-based capability enforcement.
The Three Stages of the Permission Pipeline
The command permission model operates through a sequential pipeline that inspects every command before execution. Each stage transforms the raw request into a concrete security decision based on static analysis and runtime configuration.
Command Classification via classify_command
Every incoming request—whether a JSON-RPC call, CLI invocation, or internal tool execution—first passes through the classification layer. In src/openhuman/security/command_classification.rs, the classify_command function inspects the command name and arguments to assign a CommandClass variant.
The classifier recognizes five primary categories: Read, Write, Network, Install, and Destructive. For example, a call to /rpc/agent/execute_tool that targets the filesystem returns CommandClass::Write, while a network fetch operation returns CommandClass::Network.
use openhuman::security::command_classification::classify_command;
use openhuman::security::CommandClass;
let cmd_name = "/rpc/agent/execute_tool";
let args = json!({ "tool_name": "write_file", "path": "/tmp/foo.txt" });
let class: CommandClass = classify_command(cmd_name, &args);
assert_eq!(class, CommandClass::Write);
Policy Evaluation with gate_decision
Once classified, the command enters the policy engine defined in src/openhuman/security/policy.rs. The gate_decision function accepts the CommandClass and the current AutonomyTier, then computes a GateDecision—either Allow, Prompt, or Block.
The function first consults hard-coded security constraints in src/openhuman/security/blocked_paths.rs, which lists always-forbidden directories like system credential stores. If the command targets these paths, it is immediately blocked regardless of tier. Otherwise, the function applies tier-specific logic to determine whether the operation proceeds silently, requires user approval, or is denied.
use openhuman::security::policy::{gate_decision, GateDecision};
use openhuman::config::schema::autonomy::AutonomyTier;
use openhuman::security::CommandClass;
let tier = AutonomyTier::Supervised; // read from Config
let class = CommandClass::Install; // from classify_command
let decision: GateDecision = gate_decision(&tier, class);
match decision {
GateDecision::Allow => println!("Proceed"),
GateDecision::Prompt => println!("Show approval UI"),
GateDecision::Block => println!("Reject"),
}
Autonomy Tier Enforcement
The final layer enforces capabilities defined in src/openhuman/config/schema/autonomy.rs. OpenHuman supports three distinct autonomy tiers that determine the agent's operational boundaries:
- readonly: Permits only
Readand optionallyNetworkoperations; all writes and installations are blocked - supervised: Allows
ReadandWriteoperations, but escalatesDestructiveorInstallcommands toPromptstatus requiring user approval - full: Grants blanket
Allowstatus to all command classes except those explicitly listed in the always-forbidden table
Users configure their tier via the TOML configuration file, where optional flags like allow_network further refine the capability set.
# ~/.openhuman/config.toml
[autonomy]
tier = "supervised" # options: "readonly", "supervised", "full"
allow_network = true # optional, defaults to false for readonly
Runtime Enforcement and Decision Handling
The command permission model enforces decisions once per turn, preventing agents from bypassing gates mid-interaction. When gate_decision returns:
- Allow: The runtime immediately executes the command
- Prompt: The UI layer presents an approval card through the logic in
src/openhuman/security/approval.rs, suspending execution until the user accepts or rejects - Block: The system aborts the command and returns a permission error to the caller
This ensures that destructive operations cannot proceed without explicit human oversight when running in supervised or readonly modes.
Summary
- The command permission model classifies all requests via
classify_commandinsrc/openhuman/security/command_classification.rsinto coarse-grainedCommandClassvariants - The
gate_decisionfunction insrc/openhuman/security/policy.rsevaluates classified commands against the currentAutonomyTierand blocked path lists - Three autonomy tiers—readonly, supervised, and full—define capability boundaries in
src/openhuman/config/schema/autonomy.rs - Decisions result in
Allow,Prompt, orBlockstates, with interactive approval handled bysrc/openhuman/security/approval.rs - Hard-blocked paths in
src/openhuman/security/blocked_paths.rsoverride tier permissions to protect sensitive system resources
Frequently Asked Questions
How does OpenHuman determine which CommandClass to assign?
The classify_command function inspects the RPC method name and argument structure to categorize operations. File write operations return CommandClass::Write, network requests return CommandClass::Network, and package installations return CommandClass::Install. This classification is deterministic and occurs before any policy evaluation.
What is the difference between the supervised and full autonomy tiers?
The supervised tier allows standard read and write operations but requires user approval for destructive changes and software installations. The full tier grants automatic permission to all command classes except those targeting explicitly blocked paths like credential stores. Supervised mode is recommended for autonomous agents operating in production environments.
Can I customize which paths are always blocked?
Yes. While the default hard-blocked paths are defined in src/openhuman/security/blocked_paths.rs, the policy engine checks this list before evaluating autonomy tiers. Administrators can modify the source to include additional protected directories, or future versions may expose these restrictions via configuration files.
What happens when a command receives a Prompt decision?
When gate_decision returns GateDecision::Prompt, the runtime invokes the approval workflow in src/openhuman/security/approval.rs. This pauses execution and displays an interactive card in the UI detailing the requested operation, allowing the user to approve or deny the specific command instance before it proceeds.
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 →