fabro/docs/public/agents/permissions.mdx
Release Repro a925275778
fix(agent): remove the read-before-write guard
`ReadBeforeWriteSandbox` blocked writes to any existing file the agent
had not read, tracked by a session read set populated only by
`read_file`, `grep`, `read_many_files`, and the Kimi `Read`.

The gpt56 profile has none of those. It mirrors Codex's tool contract --
`shell_command`, `apply_patch`/`edit_file`, `update_plan`, `web_search`
-- and reads through the shell, so its read set stayed permanently
empty and every edit to an existing file failed. In run
01KYD4360GN6SED4BYEVGYP4XT all 28 `edit_file` calls failed, 25 of them
on the guard. The agent read `package.json` with `sed` and `cat`,
hex-dumped it trying to diagnose the rejections, then routed around the
guard with `sed -i`, which the guard never covered. It prevented no
blind write; it converted content-anchored edits into an unreviewed
in-place shell rewrite.

Neither Codex nor Kimi Code enforces read-before-write at runtime.
Codex's `apply_patch` `Add File` overwrites an existing path silently;
Kimi Code's `Write` has no check at all. Both rely on the exact-match
requirement in their edit tools, which is stronger proof of inspection
than a read set, plus per-write approval.

Tool descriptions and the Kimi prompt keep telling the model to read
before editing -- that guidance matches Kimi Code's own `edit.md` and
still prevents `old_string not found` -- but no longer claim the
workspace refuses unread writes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 14:53:38 -04:00

113 lines
4.8 KiB
Text

---
title: "Permissions"
description: "Controlling which tools agents can use"
---
Permissions control which tools an agent can use without human approval. Fabro uses a three-tier permission model that balances agent autonomy with safety — read-only agents can explore the codebase freely, read-write agents can also edit files, and full-access agents can run arbitrary shell commands.
## Permission levels
| Level | Auto-approved tools | Prompted tools |
|---|---|---|
| `read-only` | `read_file`, `read_many_files`, `grep`, `glob`, `list_dir`, sub-agent tools | Everything else requires approval |
| `read-write` | All read tools + `write_file`, `edit_file`, `apply_patch`, sub-agent tools | `shell`, `web_search`, `web_fetch`, MCP tools |
| `full` | All tools including `shell`, `web_search`, `web_fetch`, MCP tools | None |
The default permission level is `read-write`.
## Tool categories
Every tool is classified into one of four categories that determine which permission level auto-approves it:
| Category | Tools | Minimum level |
|---|---|---|
| read | `read_file`, `read_many_files`, `grep`, `glob`, `list_dir` | `read-only` |
| write | `write_file`, `edit_file`, `apply_patch` | `read-write` |
| subagent | `spawn_agent`, `send_input`, `wait`, `close_agent` | `read-only` |
| shell | `shell`, `web_search`, `web_fetch`, MCP tools, unknown tools | `full` |
Unknown tools (including MCP tools) default to the `shell` category, requiring `full` permission for auto-approval.
## Setting permissions
### CLI flag
```bash
fabro exec --permissions read-only
fabro exec --permissions read-write
fabro exec --permissions full
```
### Non-interactive mode
When running non-interactively (no TTY or `--auto-approve` flag), tools outside the permission level are denied outright:
```bash
# In CI: only allow read and write tools, deny shell
fabro exec --permissions read-write --auto-approve
```
### Interactive escalation
In interactive mode, when an agent calls a tool outside its current permission level, Fabro prompts the user:
```
Agent wants to run: shell(command="cargo test")
Allow? [y]es / [a]lways / [n]o:
```
- **yes** -- allow this one call
- **always** -- upgrade the permission level for the rest of the session
- **no** -- deny the call (the agent receives an error and can try a different approach)
Choosing "always" on a write tool upgrades to `read-write`. Choosing "always" on a shell tool upgrades to `full`.
## How permissions interact with tools
### Read tools are always available
Regardless of permission level, agents can always read files, search with grep, and find files with glob. This means even a `read-only` agent can fully explore a codebase.
### Write tools require read-write or higher
The `write_file`, `edit_file`, and `apply_patch` tools are auto-approved at `read-write` and above. At `read-only`, these tools are either prompted (interactive) or denied (non-interactive).
### Shell requires full
The `shell` tool and web tools (`web_search`, `web_fetch`) are only auto-approved at the `full` level. This is the most permissive setting since shell commands can do anything the sandbox allows.
### Sub-agent tools are always allowed
Sub-agent management tools (`spawn_agent`, `send_input`, `wait`, `close_agent`) are auto-approved at all permission levels. Sub-agents inherit the parent's permission level, so a `read-only` parent spawns `read-only` children.
## Permission flow
The following sequence shows how Fabro decides whether to execute a tool call:
<img src="/images/permission-flow.svg" alt="Permission flow: tool call is checked against current permission level; if auto-approved it executes, otherwise in interactive mode the user is prompted, in non-interactive mode the tool is denied" />
## Workflow-level permissions
When agents run inside Fabro workflows, the workflow engine manages tool approval. Workflow agents typically run with full auto-approval since the workflow itself defines the trust boundary -- the sandbox provider (local, Docker, or Daytona) controls what the agent can actually access.
For CLI-backed workflow agents, each provider handles auto-approval differently:
- **Anthropic** (Claude Code) -- uses `--dangerously-skip-permissions` to bypass interactive prompts
- **OpenAI** (Codex) -- uses `--full-auto` mode
- **Gemini** -- uses `--yolo` flag
## Further reading
<Columns cols={2}>
<Card title="Tools" icon="wrench" href="/agents/tools">
Full reference for built-in tools and their parameters.
</Card>
<Card title="Environments" icon="server" href="/execution/environments">
Sandbox providers that control execution isolation.
</Card>
<Card title="MCP" icon="plug" href="/agents/mcp">
MCP tools follow the same permission model as built-in tools.
</Card>
<Card title="Sub-agents" icon="users" href="/agents/subagents">
Sub-agents inherit their parent's permission level.
</Card>
</Columns>