# How the Approval Gate in OpenHuman Prevents Unauthorized Agent Operations While Allowing Background Tasks

> Discover how OpenHuman's approval gate secures agent operations. It enforces risk-based authorization, parking interactive sessions for user consent and auto-approving background tasks for seamless workflow.

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

---

**The OpenHuman approval gate intercepts every tool invocation in the request-handling pipeline to enforce risk-based authorization, parking interactive sessions for user consent while automatically approving background tasks marked with `is_background = true`.**

The `tinyhumansai/openhuman` repository implements a security-focused execution model where agent-generated operations cannot invoke sensitive tools without explicit permission. By embedding the **approval gate in OpenHuman** directly into the core dispatch pipeline through [`src/openhuman/security/approval/gate.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/gate.rs), the system guarantees least-privilege execution for user-facing interactions without disrupting automated cron jobs or autonomous agent workflows.

## Core Architecture of the Approval System

The approval mechanism centers on [`src/openhuman/security/approval/gate.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/gate.rs), where the `ApprovalGate` struct evaluates every tool call against session context and risk classification before execution proceeds.

### Risk Tier Classification

Every tool definition registers a **risk tier** (low, medium, or high) in [`src/openhuman/security/approval/types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/types.rs). The gate uses this classification to determine whether a specific operation requires human oversight based on the session's configured approval mode.

### Execution Context Detection

The gate distinguishes between **foreground** (interactive) and **background** execution contexts through the `is_background` boolean flag. This distinction resides in the core logic of [`gate.rs`](https://github.com/tinyhumansai/openhuman/blob/main/gate.rs), where the `should_prompt` method checks this flag to decide whether to initiate the approval workflow or permit immediate execution.

## Interactive Session Protection

When a user-facing chat or interactive turn triggers a tool call, the gate treats the operation as foreground execution and applies the full consent protocol.

### Parking and Pending Requests

If the session's approval mode is `required` for the tool's risk tier, `ApprovalGate::process` parks the turn and inserts a pending request into the store at [`src/openhuman/security/approval/store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/store.rs). The UI then queries these pending items via the JSON-RPC endpoint `openhuman.approval_list_pending`, defined in [`src/openhuman/security/approval/schemas.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/schemas.rs).

### User Decisions via RPC

Users resolve parked requests through the `openhuman.approval_decide` RPC endpoint, selecting from three options:

- **Approve**: Grants permanent permission for this tool in the current session
- **Deny**: Rejects the operation permanently  
- **ApproveOnce**: Allows the single operation and requires confirmation for subsequent calls

```json
// Query pending approvals from the frontend
GET /rpc/openhuman.approval_list_pending

```

```json
// Submit a decision for a specific audit ID
POST /rpc/openhuman.approval_decide
{
  "auditId": "a1b2c3",
  "decision": "ApproveOnce"
}

```

## Background Task Automation

Operations flagged as background tasks bypass the interactive prompt to support autonomous agents and scheduled jobs.

### The Background Bypass Mechanism

In [`src/openhuman/security/approval/gate.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/gate.rs), the `should_prompt` method returns `false` immediately when `ctx.is_background` equals `true`. This allows the gate to treat these turns as trusted, executing the tool without user intervention.

```rust
// Create a background turn that skips approval gates
let turn = harness
    .turn("Refresh my feed.")
    .session(&session_id)
    .background(true)  // Marks as background task
    .send()
    .await?;

```

### Maintaining Security Boundaries

Background bypass applies only to turns explicitly created with the background flag. Standard interactive sessions cannot accidentally trigger this bypass, ensuring that user-facing agents cannot mask malicious operations as background tasks.

## Decision Persistence and Audit Infrastructure

The gate maintains a tamper-evident record of all decisions to support "Approve Once" semantics and compliance requirements.

### SQLite Storage Layer

Decisions persist in `approval/approval.db` via functions in [`src/openhuman/security/approval/store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/store.rs). When `approval_store::decide` records a choice, subsequent calls from the same session automatically inherit the outcome, preventing redundant prompting for approved tools.

### Audit Trail RPC

Administrators and developers can query the complete history of pending requests, decisions, and execution outcomes through `openhuman.approval_list_recent_decisions`. This creates a comprehensive log for debugging agent behavior and verifying security policy adherence.

## Integration with the Tool Dispatch Pipeline

The approval gate integrates directly into the execution pathway through the `ToolHook` trait implementation in [`src/core/dispatch.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/dispatch.rs).

### The Process Hook

All tool invocations flow through `ApprovalGate::process`, which acts as a mandatory checkpoint. This integration guarantees that **no tool can execute without the gate's consent check** unless the caller explicitly marks the turn as background. The dispatcher registration ensures the gate evaluates every operation, regardless of whether it originates from a chat interface, API call, or internal agent loop.

```rust
// Manual check pattern for custom tool implementations
if approval_gate.should_prompt(&ctx, tool_risk) {
    approval_gate.park(&ctx, tool_risk).await?;
} else {
    tool.run().await?;
}

```

## Summary

- The **approval gate in OpenHuman** sits between tool parsing and execution in [`src/openhuman/security/approval/gate.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/gate.rs), enforcing mandatory authorization checks via `ApprovalGate::process`.
- **Risk tiers** defined in [`types.rs`](https://github.com/tinyhumansai/openhuman/blob/main/types.rs) classify tools as low, medium, or high sensitivity to determine authorization requirements.
- **Interactive sessions** trigger the parking mechanism, storing pending requests in the SQLite-backed store ([`store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/store.rs)) and awaiting user decisions via `openhuman.approval_decide`.
- **Background tasks** skip user prompts when `is_background = true`, allowing autonomous agents to execute without interruption while maintaining security boundaries for foreground operations.
- **Decision persistence** in `approval/approval.db` enables "Approve Once" semantics across session lifetimes, reducing friction for trusted workflows.
- **Audit trails** captured in [`store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/store.rs) provide tamper-evident logs accessible via `openhuman.approval_list_recent_decisions` for compliance and debugging.

## Frequently Asked Questions

### Can background tasks be forced to require manual approval?

No. By design, background tasks marked with `is_background = true` bypass the interactive prompt entirely as implemented in [`gate.rs`](https://github.com/tinyhumansai/openhuman/blob/main/gate.rs). If you need oversight for automated workflows, run them as foreground sessions with elevated approval modes rather than background tasks.

### How does the system handle sessions where the user selects "Approve Once"?

When a user submits `"decision": "ApproveOnce"` via the `openhuman.approval_decide` RPC endpoint, `approval_store::decide` in [`src/openhuman/security/approval/store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/store.rs) records this choice in the SQLite database. The gate permits the immediate operation but removes the persistent grant, requiring future re-authorization for identical tool calls.

### Where is the approval state stored between application restarts?

All pending requests, decisions, and audit logs persist in `approval/approval.db` using the SQLite backend managed by [`src/openhuman/security/approval/store.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/security/approval/store.rs). This ensures that approval states survive process restarts and can be reconstructed when the OpenHuman core restarts.

### What prevents a malicious agent from marking all turns as background to bypass approval?

The `is_background` flag requires explicit construction through the turn builder API (`.background(true)`), which is typically restricted to authenticated system contexts or specific automation harnesses. Interactive user sessions cannot arbitrarily set this flag without code-level access to the session builder, maintaining the security boundary between foreground and background execution contexts.