> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ollim.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Permissions

> Control which tools the agent can use with permission modes and approval workflows.

ollim-bot controls which tools the agent can use through a permission
system. You choose a permission mode, and the bot enforces it — from
silent denial of unapproved tools all the way to full bypass.

## Permission modes

Switch modes with the `/permissions` slash command or persistently
with [`/config permission_mode`](/core-usage/slash-commands#config).

| Mode                | Behavior                                                                                                                              |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `dontAsk`           | Silent denial of tools not in the session-allowed set. No prompt. **Default.**                                                        |
| `default`           | Discord message with reaction buttons for each tool use.                                                                              |
| `acceptEdits`       | File edits and filesystem commands (`mkdir`, `touch`, `rm`, `mv`, `cp`) auto-approved, others prompt.                                 |
| `bypassPermissions` | All tools auto-approved in the main session, no prompts. Background forks still use their own [tool restrictions](#background-forks). |

### Persistence

`/permissions` changes the mode for the current session only — it
resets to the default (`dontAsk`) on restart. Use `/config permission_mode`
to persist the mode across restarts.

### Fork scoping

Permission modes are **fork-scoped** — changing the mode inside an
interactive fork leaves the main session unchanged once the fork exits.
Note that `dontAsk` uses a module-level flag, so switching to or from
`dontAsk` in a fork temporarily affects the main session during the fork.
The original mode is restored when you exit the fork.

## Approval flow

In `default` mode, unapproved tool use triggers an interactive approval
prompt in your Discord DM. (`acceptEdits` auto-approves file edits and
filesystem commands, and `bypassPermissions` approves everything in the
main session — neither triggers the approval flow below.)

<Steps>
  <Step title="Agent requests a tool">
    The agent attempts to use a tool that isn't in the session-allowed set.
  </Step>

  <Step title="Bot sends an approval message">
    A message appears in your DM showing the tool label
    (name + arguments). Three emoji reactions are added automatically.
  </Step>

  <Step title="You react">
    React with one of the three emojis to respond:

    | Reaction | Effect                                                           |
    | -------- | ---------------------------------------------------------------- |
    | ✅        | **Allow** — approve this single tool use                         |
    | ❌        | **Deny** — reject this tool use                                  |
    | 🔓       | **Always** — approve and add the tool to the session-allowed set |
  </Step>

  <Step title="Result is applied">
    The approval message is edited to show the outcome
    (`allowed`, `denied`, or `always allowed`), and the agent
    proceeds or receives a denial.
  </Step>
</Steps>

Approvals time out after **60 seconds**. An unanswered prompt is treated
as a denial, and the message is edited to show `expired`.

## Session-allowed set

When you react with 🔓 (**Always**), the tool is added to a session-allowed
set. Future uses of that tool are auto-approved without prompting — even
in `dontAsk` mode.

* The session-allowed set is **shared** across the main session and interactive forks.
* `/clear` resets the session-allowed set (and cancels any pending approvals).
* The set is in-memory only — it does not persist across bot restarts.

## Background forks

Background forks always run with `permission_mode="default"` —
regardless of your main session's setting. Even if you've set
`bypassPermissions` or `acceptEdits`, background forks don't inherit
that mode. This ensures tool gating and **ping budget** enforcement
are always active for background tasks.

Beyond permission mode, background forks have their own tool
restrictions based on the job's YAML configuration:

* **Ping tools** (`ping_user`, `discord_embed`) — allowed only when
  `allow-ping` is `true` in the job's YAML
* **Reporting tools** (`report_updates`, `follow_up_chain`) — allowed
  unless `update-main-session` is `blocked`

All other tools not in the fork's `allowed-tools` list are denied. The
agent in a background fork cannot trigger approval prompts — see
[Background forks](/scheduling/background-forks) for details.

## Deny messages

The deny message varies by context so the agent understands why a tool
was blocked:

| Situation                            | Deny message                                                     |
| ------------------------------------ | ---------------------------------------------------------------- |
| Background fork (pings disabled)     | `"pings disabled for this job"`                                  |
| Background fork (reporting blocked)  | `"reporting blocked for this job"`                               |
| Background fork (other tools)        | `"{tool} is not available in background forks"`                  |
| `dontAsk` mode (not session-allowed) | `"{tool} requires permission — denied silently in current mode"` |

## State directory write-protection

The `state/` directory under `~/.ollim-bot/` contains infrastructure
files — session IDs, credentials, ping budget, and runtime config. These
files are managed by ollim-bot itself, not by the agent.

The agent can **read** files in `state/` but cannot modify them. Any
write or edit attempt targeting `state/` is automatically denied — this
applies in the main session, interactive forks, and background forks.

<Accordion title="How write-protection works">
  Protection is enforced at two layers:

  1. **Tool hook** — a pre-execution hook intercepts Write and Edit calls.
     If the target path falls inside `state/`, the call is denied with
     `"state/ is write-protected"`.
  2. **Pattern validation** — tool patterns are validated at startup and
     dispatch time. Patterns that could match the `state/` directory
     (like `Edit(**)`) are rejected before the job runs.
</Accordion>

## Customizing tool sets

Both the main session and background forks start with hard-coded
default tool sets. You can extend — or, for background forks,
completely replace — those defaults by creating a `tool-policy.yaml`
file in `~/.ollim-bot/`.

The file is optional. When it doesn't exist, the built-in defaults
apply. Changes take effect without a restart — the file is re-read
when its modification time changes.

### Keys

| Key                               | Type        | Effect                                                                                               |
| --------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------- |
| `main_session.additional_allowed` | `list[str]` | Merged into the main session's default tools. Duplicates are ignored.                                |
| `bg_forks.additional_allowed`     | `list[str]` | Merged into the default background fork tools. Duplicates are ignored.                               |
| `bg_forks.override`               | `list[str]` | **Replaces** the default background fork tools entirely. Takes precedence over `additional_allowed`. |

<Warning>`bg_forks.override` removes all default tools — including read-only
helpers like `Read(./**.md)`. Use `additional_allowed` unless you need
full control over the background fork tool set.</Warning>

### Example

A minimal `tool-policy.yaml` that adds `git status` to the main session and calendar access to background forks:

```yaml title="~/.ollim-bot/tool-policy.yaml" theme={null}
main_session:
  additional_allowed:
    - "Bash(git status)"

bg_forks:
  additional_allowed:
    - "Bash(ollim-bot cal *)"
```

### Agent-managed additions

When the agent creates a routine that needs tools beyond the defaults,
it can either add `allowed-tools` to the routine's YAML frontmatter
(scoped to that job) or append to `bg_forks.additional_allowed` in
`tool-policy.yaml` (applies to all background forks).

See [File formats](/configuration/file-formats#tool-policy-tool-policyyaml)
for the full key reference.

## Visual feedback

Inline labels during streaming show what the agent is doing — and what got blocked.
When `dontAsk` mode or an explicit rejection denies a tool, the label
shows with strikethrough text:

| Outcome           | Rendering                                                                    |
| ----------------- | ---------------------------------------------------------------------------- |
| Approved/executed | `-# *Read(reminders/foo.md)*`                                                |
| Denied            | `-# *~~Read(reminders/foo.md)~~ — denied (use /permissions ask to approve)*` |
| Errored           | `-# *~~Read(reminders/foo.md)~~ — error*`                                    |

In `dontAsk` mode, the stream shows denied tools with strikethrough so
you see what the agent tried without receiving approval prompts.
In `default` mode, tools you reject via the ❌ reaction also appear
struck through. Tools that fail during execution also render with
strikethrough and an " — error" suffix.

## Cancellation

Pending approval prompts are automatically cancelled (treated as denials)
when any of the following occur:

* You use `/clear` — resets the session-allowed set and cancels all pending approvals
* You interrupt the agent — cancels pending approvals for the current turn
* You exit an interactive fork — cancels any approvals pending inside the fork

Cancelled prompts are deleted to avoid orphaned messages in the channel.

## Examples

<Tabs>
  <Tab title="dontAsk (default)">
    In `dontAsk` mode, any tool not in the session-allowed set is silently
    denied — no message appears.

    ```text theme={null}
    /permissions dontAsk
    ```

    This is the default. The agent operates autonomously within its
    allowed toolset without interrupting you for approvals.
  </Tab>

  <Tab title="default (interactive)">
    In `default` mode, each tool use not already in the session-allowed set
    produces an approval message. You review and react.

    ```text theme={null}
    /permissions default
    ```

    Use this when you want visibility into what tools the agent is calling.
    React with 🔓 on tools you trust to avoid repeated prompts.
  </Tab>

  <Tab title="bypassPermissions">
    In `bypassPermissions` mode, all tools are auto-approved. No prompts
    appear.

    ```text theme={null}
    /permissions bypassPermissions
    ```

    <Warning>This mode gives the agent unrestricted tool access. All [subagents](/extending/subagents) inherit this mode and it cannot be overridden per-subagent. Use with caution.</Warning>
  </Tab>
</Tabs>

## Next steps

<Columns cols={2}>
  <Card title="Slash commands" icon="terminal" href="/core-usage/slash-commands">
    Full reference for all slash commands including `/permissions`.
  </Card>

  <Card title="Forks" icon="code-branch" href="/core-usage/forks">
    How interactive and background forks interact with permission scoping.
  </Card>

  <Card title="Discord tools" icon="wrench" href="/extending/mcp-tools">
    Reference for all Discord tools the agent can use.
  </Card>

  <Card title="Background forks" icon="clock" href="/scheduling/background-forks">
    Tool restrictions and allowed tool configuration for background forks.
  </Card>
</Columns>
