# How Reasonix Evaluates Permission Rules (Allow, Ask, Deny) for Tool Calls

> Discover how Reasonix evaluates tool call permissions using a 9-step gate for allow, ask, or deny decisions. Learn about safety classifications and admin overrides.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: how-to-guide
- Published: 2026-06-27

---

**Reasonix evaluates tool call permissions through a hierarchical 9-step gate implemented in [`internal/planmode/policy.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/planmode/policy.go) that checks tool names, safety classifications, read-only flags, and administrator overrides to decide whether to allow, block, or conditionally permit each invocation.**

When the DeepSeek-Reasonix model requests a tool invocation, the request passes through a strict **permission rules evaluation** system that determines if the call proceeds, requires user confirmation, or is rejected. This security gate operates on a fail-closed principle, ensuring that only explicitly trusted read-only operations execute during autonomous planning phases.

## The Permission Gate Architecture

The core decision logic resides in the `Policy.Decide` method defined in [`internal/planmode/policy.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/planmode/policy.go). This method accepts a `Call` struct containing the tool name, arguments, read-only status, and safety classification, then returns a `Decision` struct containing a `Blocked` boolean and a human-readable `Message` explaining any denial.

The evaluation follows a strict priority-ordered hierarchy of nine distinct checks, processed sequentially until a definitive verdict is reached.

## The 9-Step Evaluation Hierarchy

The `Decide` method implements the following rule chain:

1. **Bash Special Handling**: If the tool name is `"bash"`, control transfers to `decideBash` (lines 81-85), which parses the command using `shellsafe.CommandIsReadOnly` to verify the operation is read-only and rejects unsafe arguments.

2. **Known Blocked Tools**: If the tool appears in `knownBlockedTools` (including `write_file`, `complete_step`, and other write-capable tools), the call is **blocked** unconditionally in plan mode.

3. **Unsafe Safety Classification**: If the tool's `PlanModeClassifier` reports `PlanSafetyUnsafe` (lines 49-51), the call is **blocked** regardless of other flags.

4. **Always-Allowed Set**: Tools in the unconditional allow list (`ask`, `todo_write`) are **allowed** immediately without further checks (lines 89-92).

5. **Self-Reported Safe Read-Only**: If the tool reports `PlanSafetySafe` **and** `ReadOnly() == true`, the call is **allowed** (lines 55-60).

6. **Trusted Read-Only Tools**: If the tool is read-only and the flag is **trusted** (not marked `Untrusted`), the call is **allowed**. This covers built-in read-only tools and first-party MCP overrides (lines 61-66).

7. **Administrator Allow-List**: If the tool name appears in the **policy's `AllowedTools`** slice (populated from `plan_mode_allowed_tools` in [`reasonix.toml`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/reasonix.toml)), the call is **allowed** (lines 66-69).

8. **Untrusted Read-Only Hints**: If the tool is read-only but the flag came from an **untrusted external source** (`Untrusted == true`), the call is **blocked** with a message explaining that the hint must be pre-seeded via `trusted_read_only_tools` or declared in `plan_mode_allowed_tools` (lines 70-75).

9. **Default Deny**: If none of the above conditions match, the call is **blocked** as a writer tool, requiring the user to finish planning with read-only tools before approving writes (lines 76-79).

## Special Handling for Bash Commands

The `bash` tool receives unique treatment due to its ability to execute arbitrary shell commands. The `decideBash` function inspects the command string and arguments to ensure no write operations, background processes, or unsafe flags are present. Any command capable of modifying the filesystem or spawning detached processes results in a blocked decision with an explanatory message.

## Configuration Overrides

Administrators can bypass default restrictions by configuring the `plan_mode_allowed_tools` array in [`reasonix.toml`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/reasonix.toml). Tools listed in this configuration are added to the policy's `AllowedTools` slice, granting them explicit permission to run during plan mode regardless of their default classification.

## Code Examples

*Allowing a built-in read-only tool:*

```go
call := planmode.Call{
    Name:      "read_file",
    ReadOnly:  true,
    Untrusted: false,
    Safety:    planmode.PlanSafetyUnknown,
}
decision := policy.Decide(call)
// decision.Blocked == false

```

*Denying a writer tool without explicit permission:*

```go
call := planmode.Call{
    Name:      "write_file",
    ReadOnly:  false,
    Untrusted: false,
    Safety:    planmode.PlanSafetyUnknown,
}
decision := policy.Decide(call)
// decision.Blocked == true
// Message: "blocked: \"write_file\" is a writer tool ..."

```

*Configuring explicit permission via [`reasonix.toml`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/reasonix.toml):*

```toml
plan_mode_allowed_tools = ["git"]

```

With this configuration, the `git` tool is permitted during plan mode:

```go
call := planmode.Call{
    Name:      "git",
    ReadOnly:  true,
    Untrusted: false,
    Safety:    planmode.PlanSafetyUnknown,
}
decision := policy.Decide(call) // Allowed due to config override

```

*Validating bash commands:*

```go
args := json.RawMessage(`{"command":"git log --oneline","run_in_background":false}`)
call := planmode.Call{
    Name: "bash",
    Args: args,
}
decision := policy.Decide(call) // Allowed if command is read-only

```

If the command contains write operations (e.g., `git commit`), `decideBash` returns a blocked decision.

## Summary

- The permission gate is implemented in [`internal/planmode/policy.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/planmode/policy.go) via the `Policy.Decide` method.
- A 9-step hierarchical evaluation determines whether to allow, block, or deny each tool call.
- **Read-only** tools are allowed only if their flags are trusted or explicitly configured.
- **Bash** commands undergo additional parsing to verify they are read-only operations.
- Administrators can override defaults using the `plan_mode_allowed_tools` configuration in [`reasonix.toml`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/reasonix.toml).
- The system operates on a **fail-closed** principle: any ambiguous tool is treated as a writer and blocked.

## Frequently Asked Questions

### What happens if a tool claims to be read-only but comes from an untrusted MCP server?

If a remote MCP server marks a tool as read-only but sets `Untrusted == true`, the permission gate treats it as a writer tool and blocks the call. To allow such tools, administrators must either add them to `trusted_read_only_tools` or list them explicitly in `plan_mode_allowed_tools` within [`reasonix.toml`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/reasonix.toml).

### Why does Reasonix block the `bash` tool differently from other tools?

The `bash` tool can execute arbitrary shell commands, making it inherently risky. Instead of relying on metadata flags, `decideBash` parses the actual command string using `shellsafe.CommandIsReadOnly` to detect write operations or background process spawning, ensuring only safe, read-only commands execute during plan mode.

### Can I allow a normally blocked writer tool during plan mode?

Yes. While writer tools like `write_file` are blocked by default, you can add them to the `plan_mode_allowed_tools` array in your [`reasonix.toml`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/reasonix.toml) configuration file. This populates the policy's `AllowedTools` slice, bypassing the default restrictions for that specific tool.

### What is the difference between `PlanSafetySafe` and the `ReadOnly` flag?

`ReadOnly` is a boolean property indicating whether a tool modifies system state, while `PlanSafetySafe` is a classification from the tool's `PlanModeClassifier` indicating explicit opt-in for plan-mode execution. A tool must typically satisfy both conditions (or meet other override criteria) to pass the permission gate.