13. Tool permissions and approval

AVL Code applies fine-grained policy to every tool call.

13.1 Three-state permission

Each tool:

  • ✓ Allow: pass through.
  • ◇ Ask: pop an approval modal on every call.
  • ✗ Deny: reject directly.

Configurable per work mode; common patterns: enable write tools under execute, disable all writes under plan. The three states apply to subagents as well (a denied tool is unavailable on the subagent side too), and leftover tool config is cleaned up automatically after a plugin / external service is uninstalled.

13.2 Approve before use

When a tool marked "Ask" is about to run:

  1. The desktop pops an approval dialog showing the tool name, parameters and impact.
  2. You pick:
    • ✓ Allow (once)
    • ✓ Always allow: adds tool+parameter pattern to the allow list.
    • ✗ Deny
  3. The dialog shows a 30-second countdown; no response by the end counts as Deny.

13.2.1 Unrestricted mode (advanced)

To the right of the mode slider in the input area is a shield switch, for advanced users who know what they're doing. Turning it on goes through a confirmation dialog (with a 5-second cooling-off — the confirm button starts disabled and counts down "Please read the risk note 5s…"; it can't be clicked until it reaches 0, and Enter also doesn't activate it). Once on, a red banner stays put as a reminder; toggling off takes effect immediately.

Scope: per-session, in-memory only; cleared on restart.

On removes three frictions:

Friction When unrestricted
Tool approval Skip the approval modal (no per-call ask / deny / defer); tools execute directly
Command allow-list fs.exec is no longer restricted by the command allow-list
Network filter web.fetch / web.bing no longer filter internal / loopback / link-local addresses

Hard guards still apply (unaffected by the switch):

  • samples/ sandbox isolation.
  • rm -rf argument validation.
  • The injection-denylist (fork bombs / writing /etc / curl|sh / eval).
  • The http(s) protocol allow-list.

Slash-command shortcut — type directly in the input box:

  • /unrestricted (or Chinese alias /无限) — toggle the current session's unrestricted mode. Turning on still goes through the 5-second risk-confirmation dialog; turning off is immediate. The Chinese alias is hidden from the command palette and /help (avoids a duplicate row) but still executes when typed.

Message marking for the no-guardrails span: the consecutive messages produced while unrestricted mode is on are enclosed as a whole by a light border — start and end at a glance, so a later review shows immediately which content was generated without guardrails. Toggling off closes the border on the spot; while the mode is still on, no premature "end" boundary is drawn. Subagents can recursively inherit the mode on demand, and messages produced under inheritance carry the same marking.

13.2.2 Local mode: cut the built-in internet tools in one click

The exact opposite direction from unrestricted mode — local mode switches off this session's built-in internet capability in one go, which suits material you'd rather not send out, or an environment with no connectivity anyway.

Where the switch is: the internet toggle in the input area. The default is "Internet tools enabled"; clicking raises a "Disable internet tools?" confirmation, and confirming applies it.

What gets switched off:

  • Web fetch and search
  • GitHub search
  • VirusTotal / GTI threat-intel cloud lookups
  • Online vulnerability DB sync

What is not affected (important — don't read this as "the network is off"):

  • Network access from shell commands (e.g. curl) — this switch does not block it
  • Network access from external MCP tools
  • Communication with the model service itself

Effect on model choice: in local mode, this session's data only goes to the model the session itself uses —

  • code.ask, sec.decompile and memory auto-extraction no longer pick a 澜砥 model by routing; they always use the current session's model;
  • subtasks always use the main session's model (ignoring the subtask routing strategy and any model in the subagent definition);
  • hooks use the model of the session that triggered them; if it can't be determined, that hook's model call is skipped rather than using another session's model;
  • routines posted into a local-mode session use that session's model.

Scope: per session, and internet tools are restored automatically after a restart; subagents inherit the restriction. While it's on, tasks that rely on internet research (looking things up, cloud threat analysis, pulling the latest vulnerability data) will be noticeably limited — that's expected.

Slash command: type /local in the input box to toggle it.

13.3 Always-allow granularity

Granularity Coverage When to use
Once only Single call Cautious evaluation
Same tool + same args One specific call shape Recommended default
Same tool + any args Any call to this tool Internal scripts
Entire workspace Every tool in this workspace Isolated environments only

13.4 Multi-device approval

The same approval request shows up on the desktop dialog and every bound remote channel (e.g. WeChat); the first response wins, and later replies from other devices are reported as already answered. A commonly-confused rule: the deny > defer > ask > allow priority order belongs to the hook layer — it merges permission decisions returned by multiple hooks within one evaluation, and has nothing to do with multi-device responses.

13.5 Remote approval

If WeChat is bound, every "Ask" approval mirrors to the bound chat. Reply with:

Command Equivalent desktop action
/approve <id> ✓ Allow once
/always <id> ✓ Always allow
/deny <id> ✗ Deny
No reply Times out as deny when the 30 s countdown ends

13.6 Persistence

Approval decisions are not stored in a separate audit log: only "Always allow" is persisted — written to the workspace-level authorization file hook-approvals.yaml (authorization fingerprint + decision time), viewable and revocable under Settings → Hooks. "Allow once" and "Deny" affect only the current call and leave no record.