Permissions and Confirmations
Last updated
The two permission modes, which entry point uses which, and how confirmation prompts are routed.
Permission mode
| Mode | Behavior |
|---|---|
safe | Each non-ReadOnly tool call requires user confirmation |
auto | Every tool runs without confirmation, except writes outside the working directory and irreversible commands (below); only takes effect while the working directory qualifies, otherwise the safe rules apply |
The working directory qualifies for
auto when it is a subdirectory of $HOME, not $HOME itself, and not a denied or sensitive path (filesystem.WorkDirAllowsAll). The gate is enforced by the harness in internal/agents/exec/toolCall.go, not by the prompt. Under auto a call still asks when:- Outside the working directory — an
edit_file,remove_fileorrestore_filepath, arun_command/background_commandargv token that is absolute,~or.., awrite_pathsentry, or anrmoperand that lands inside$HOMEbut outside the working directory asks once; after approval that path is granted for the rest of the session - Irreversible command (
internal/agents/exec/irreversible.go) — asks even when an allow rule matches; only "Yes, allow this turn" skips it for the rest of the turn. Covered: Git history loss (reset --hard,clean, force push, remote branch deletion); a download piped into an interpreter, or a script that reaches the network and reads a secret; uploading a sensitive file; infrastructure apply / delete (terraform,tofu,pulumi,cdk,kubectl,helm); cloud CLI delete / deploy / IAM changes (gcloud,az,doctl,aws,gsutil); deploy CLIs (firebase,vercel,netlify,wrangler,fly,serverless); database migrations; destructive SQL (DROP/TRUNCATE,DELETE/UPDATEwithoutWHERE);gh pr merge,gh repo deleteand similar, and mutatinggh apicalls
Path tiers apply in every mode: a sensitive path inside
$HOME needs a plain confirmation (no password); a path outside $HOME, an argv starting with sudo, and sandbox: false need the system password. Password prompts drop "Yes, don't ask again" and "Yes, allow this turn"; plain confirmations keep them. Before v1.3.7 a path outside $HOME under auto was rejected without a prompt; it now asks for the password. Since v1.3.10 read_files and find_files read a path outside $HOME without a prompt when it is on the readable list (system and package locations such as /usr, /etc, /opt, plus readable_path in config.json).rm in an argv moves its targets to the trash: inside the working directory it runs under auto, elsewhere in $HOME it asks, outside $HOME it needs the password; rm inside sh -c is refused. network: true on run_command / background_command confirms under safe and runs under auto.Mode by entry point
The active permission mode (
safe vs auto) is decided by entry point:| Entry | Mode |
|---|---|
| TUI | auto when the starting working directory qualifies, otherwise safe; toggled per session with Shift+Tab |
POST /v1/send | safe while the web dashboard has a confirmation listener open and the request sets neither enable_edit nor enable_sandbox; confirms are answered there. Otherwise (v1.3.9) API auto mode: no prompts, read-only unless enable_edit:true, sandboxed unless enable_sandbox:false, see REST API. agen -p always uses API auto mode. The allow_all request field was removed |
POST /v1/chat/completions | auto; the work directory defaults to $HOME, which does not qualify, so the safe rules apply unless the request names a qualifying work directory |
| Telegram | safe (confirm gate uses a Telegram inline-keyboard select) |
| Discord | safe (confirm gate uses a Discord select menu) |
| Resumed pending task | Keeps the mode stored with the task |
| Subagent | Inherits the parent's mode; under auto it is not limited to the working directory |
The permission mode is not rendered into the turn context or the system prompt: the
## Permission Mode section and configs/prompts/system_prompt/inject/permission/*.md were Removed in v1.3.7, and the gate above is applied by the harness alone. Commands on the read-only list skip the gate in every mode.Auto-approval rules
These rules decide which calls ask under
safe (and under auto when the working directory does not qualify). A tool that carries a mode is gated by it: list / read / search are treated as read-only and skip confirmation, while mode=remove (edit_skill / edit_tool) always confirms even on an otherwise auto-approved tool. The same holds for remove_file and restore_file, which since v1.3.11 replace edit_file's remove / restore modes (Removed in v1.3.11): an allow rule never skips them.Beyond that, a call skips the prompt when its tool is registered
AlwaysAllow, an http_request uses GET, or a run_command / background_command argv matches the read-only list (an argv token that touches a sensitive path stops the match); open_file on a URL and read_files on a sensitive file always ask, and so does a command call with sandbox: false (v1.3.0) or an argv starting with sudo (v1.3.2), which needs the system password even under auto, an allow-all Skill or a matching allow rule. Every other call is checked against the allow list (internal/agents/exec/allow):| Item | Detail |
|---|---|
| Files | ~/.config/agenvoy/allow_tool (global) and <workDir>/.agenvoy/allow_list (project), one entry per line, # starts a comment; both are loaded and unioned |
| Entry | name approves every call of that tool; name(argGlob) approves only calls whose subject matches. The subject is the space-joined argv for run_command and background_command (run_command_background was renamed, Removed in v1.3.2), the absolute path for edit_file, METHOD URL for http_request (method defaulting to GET), otherwise the path (made absolute against the work directory), url or target argument, else the raw JSON arguments. Since v1.3.0 relative paths are resolved before matching, and an empty argv, edit_file path or http_request URL never matches a rule and cannot be remembered |
| Glob | Used for both the name and argGlob, anchored to the whole string: * matches within one / segment, ** crosses / (since v1.3.0 **/ also matches zero directories, so src/**/*.go covers src/main.go), ? matches one non-/ character, and \*, \?, \\ are literal |
| Remember | Approving a prompt with remember writes name(<subject>) to the project allow_list, escaping *, ? and \ in the subject so the entry matches only that exact call |
| MCP | /mcp → server → tools, or POST /v1/allowlist with {tool: {prefix, entries}}, replaces every global entry under mcp__<server>__ with the given set; each entry must start with that prefix, and including prefix* collapses the set to a whole-server grant |
| Skills | ~/.config/agenvoy/allow_skill and <workDir>/.agenvoy/allow_skill list Skill names; a run whose active Skill is listed executes as allow-all |
Origin-routed confirmations
Every interactive request carries an origin prefix —
cli-, chat-, tg-, or dc-. CLI confirmations are consumed only by the TUI — since v1.2.0 they travel over the daemon socket to the TUI window that started the run, not to every open TUI — web requests by the web confirmation stream, and Telegram or Discord requests by their matching channel listeners. A confirmation from a channel other than the TUI that is left unanswered for five minutes is skipped and the task is kept as pending (since v1.1.1 TUI confirmations wait without a time limit), so one channel can neither intercept nor indefinitely hold another channel's prompt.