read_only
Observe only. All tool actions are blocked — including otherwise-safe
read commands like ls and cat. The safest choice for untrusted channels.
Read-only, supervised, and full autonomy levels and the tool-level approval gate.
Autonomy levels decide how much an agent can do on its own; the approval gate decides what it must check with you first. Together they are the innermost layer of Revka’s security model — every tool call is evaluated against the autonomy level before it runs, and in supervised mode the Approval Manager can pause for a yes/no decision on individual tool calls.
This page covers the three autonomy levels, how to set them, and how the tool-level approval gate behaves on the CLI versus in chat channels. Use it when you are deciding how much to trust an agent on a given channel, or when you want to stop being prompted for a tool you already trust.
The autonomy level is the policy engine’s entry point. It is enforced by
SecurityPolicy and controls whether the agent can take actions at all,
independent of the command allowlist, workspace boundary, and rate limiter that
sit alongside it.
read_only
Observe only. All tool actions are blocked — including otherwise-safe
read commands like ls and cat. The safest choice for untrusted channels.
supervised
The default. The agent acts within the allowlists, but medium- and high-risk
commands require approval (approved = true), and the Approval Manager can
prompt for individual tool calls.
full
No approval gates. Medium-risk approval prompting is skipped, but the command
allowlist, workspace boundary, and block_high_risk_commands are still
enforced.
Set the level in the [autonomy] section of ~/.revka/config.toml:
[autonomy]level = "supervised" # read_only | supervised | full| Key | Type | Default | Meaning |
|---|---|---|---|
level | string | "supervised" | read_only, supervised, or full |
The current level is injected into the agent’s system prompt automatically (via
SecurityPolicy::prompt_summary()), so the model knows what it is allowed to do.
The practical difference is the approval gate:
approved = true (see The approved flag). The
Approval Manager may also prompt interactively before a tool call.A non-wildcard allowlist entry is the exception worth knowing: if you add a
high-risk command such as ssh to allowed_commands, it bypasses
block_high_risk_commands, but in supervised mode it still needs
approved = true to run.
Beyond the per-command risk policy, Revka has a separate Approval Manager — a pre-execution hook that runs before LLM tool calls in supervised mode. It is distinct from workflow and SOP approval gates: those pause an entire run, while this operates at the level of a single tool call. It keeps a session-scoped “Always” allowlist and writes to the audit trail.
Tune which tools the gate prompts for using two lists in [autonomy]:
[autonomy]level = "supervised"auto_approve = ["file_read", "weather"] # never prompt for thesealways_ask = ["shell"] # always prompt, even if "Always" was chosen| Key | Type | Default | Meaning |
|---|---|---|---|
auto_approve | list | [] | Tools that are never prompted for |
always_ask | list | [] | Tools that always prompt, overriding the session “Always” allowlist |
A "*" wildcard in either list covers all tools. always_ask wins over the
session allowlist — even if you previously chose Always for a tool, listing
it in always_ask forces a prompt every time.
In an interactive CLI session, supervised mode prompts on stdin before running a tool that is not auto-approved:
🔧 Agent wants to execute: shell command: rm -rf ./build/ [Y]es / [N]o / [A]lways for shell:Yes — approve this one call.
No — deny this call. The denial is recorded (see Trust-adaptive autonomy).
Always — approve this call and add the tool to the session-scoped
“Always” allowlist so it is not prompted again this session — unless it is in
always_ask.
There is no stdin to read in a non-interactive context, such as a message arriving over Telegram, Discord, or another channel. In that mode, any tool that would require approval is auto-denied rather than left hanging.
One exception: MCP-namespaced tools (named service__tool) are auto-approved in
non-interactive mode.
approved flagThe approved field is how an explicit approval rides along with a tool call.
It appears on tools that can execute medium- or high-risk actions — most notably
shell — and on the cron and SOP tools that schedule them.
{ "command": "ls -la", "approved": false }approved (boolean, default false) — set true to explicitly approve a
medium- or high-risk command in supervised mode.In supervised mode, a medium/high-risk command with approved = false is
rejected by the policy with a "Blocked by security policy"-class error. Setting
approved = true is what satisfies the gate. In full mode the flag is not
needed for medium-risk commands; in read_only mode nothing executes regardless
of the flag.
The same field is honored by the cron and SOP surfaces — for example,
cron_add and cron_run accept "approved": true to pre-approve a medium-risk
shell job. Note that shell jobs created through the gateway cron API are not
pre-approved (approved defaults to false), so medium-risk commands scheduled
that way are rejected at run time.
The approved field is internal to Revka’s security model. When a tool call is
forwarded to an external MCP server, the wrapper strips approved first, because
MCP servers do not understand it.
The Approval Manager can be wired to a per-domain trust tracker. When it is, your approval decisions feed back into the agent’s effective autonomy, so an agent that keeps doing the wrong thing in a domain loses the ability to do it silently.
Every denial is logged as a UserOverride correction. Repeated corrections in a
domain push its trust score down. When a domain crosses the regression threshold,
its effective autonomy is downgraded by one tier — and the downgrade tightens the
approval gate accordingly:
| Effective downgrade | Effect on the gate |
|---|---|
Full → Supervised | The tool now prompts, even though the configured level is full |
Supervised → ReadOnly | The tool prompts even if it is in the session “Always” allowlist, preventing silent execution |
This is automatic — there is nothing to configure on the approval side. The
behavior is driven by the trust scoring engine; tune its thresholds in the
[trust] config section, documented under
prompt injection, leak detection & trust.
Recommended Start every channel at the lowest level that still lets the agent do its job:
read_only. The agent can answer questions
but cannot touch the system.supervised (the default). You stay in the
loop for anything risky via the approval gate.full, with a tight
allowed_commands allowlist and block_high_risk_commands = true so the
remaining guardrails still hold.Security model
How autonomy, the command policy, sandboxing, and the audit log compose. See Security model and Policy, commands & sandboxing.
The agent loop
Where the approval gate sits in the model-driven tool-call cycle. See The agent loop.
Workflow approvals
Run-level human approval gates, distinct from this tool-level gate. See Runs, approvals & checkpoints.
Emergency stop & OTP
Halt a runaway agent and gate sensitive actions behind a one-time code. See OTP gating & emergency stop.