mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-07 08:27:12 +00:00
Invert the docs convention so the Mintlify-published site lives under docs/public/ and internal artifacts (strategy docs, brainstorms, plans, etc.) sit at docs/ root or docs/internal/. Tools that default to writing into docs/ now land in the catch-all instead of leaking into the published tree. - Move Mintlify content (administration/, agents/, api-reference/, changelog/, core-concepts/, examples/, execution/, getting-started/, human-tools/, integrations/, languages/, reference/, tutorials/, workflows/, images/, logo/, docs.json, favicon.svg, dot-highlight.js) into docs/public/. - Collapse docs-internal/ into docs/internal/. - Update Rust path references (fabro-api/build.rs, fabro-server, fabro-dev), TypeScript generator arg, CI path filters, clippy.toml reasons, AGENTS.md/CLAUDE.md, and README.md image refs. Mintlify dashboard project root must be updated to docs/public/ in a follow-up. .mintignore move/trim and .claude/skills/ updates land in a separate commit.
122 lines
5.5 KiB
Text
122 lines
5.5 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.
|
|
|
|
## Read-before-write guardrail
|
|
|
|
Independent of the permission system, Fabro enforces a **read-before-write guardrail** that applies to all permission levels. Even with `full` permissions, an agent must read an existing file before modifying or deleting it. See [Tools: Read-before-write guardrail](/agents/tools#read-before-write-guardrail) for details.
|
|
|
|
This guardrail operates at the sandbox layer and works alongside (not instead of) the permission system. A tool call must pass **both** checks:
|
|
|
|
1. The tool's category must be allowed by the current permission level
|
|
2. If writing to an existing file, the file must have been previously read
|
|
|
|
## 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>
|