Skip to content

Permissions API

Declarative allow / deny / interrupt rules evaluated before host file tools and command tools run. See Permissions for definition and behaviour.

python
from elsai.permissions import (
    DenyPolicy,
    ExecutionPermission,
    FilesystemPermission,
    deny_destructive,
    deny_secrets,
    execution_preset,
    preset,
)

Configure on AgentConfig: filesystem_permissions, execution_permissions, deny_policy, and workspace_root.


FilesystemPermission

python
from elsai.permissions import FilesystemPermission

Frozen dataclass. First matching rule wins per path.

FieldTypeDefaultDescription
operationstuple["read" | "write", ...]requiredMust be non-empty
pathstuple[str, ...]requiredGlob patterns; must be non-empty
mode"allow" | "deny" | "interrupt""allow"Decision when the rule matches
namestr | NoneNoneRule id for audit and messages
reasonstr | NoneNoneDeny / interrupt prompt
guidancestr | NoneNoneSteer text for DenyPolicy(on_deny="guide")

Path prefix /workspace maps to AgentConfig.workspace_root. Relative tool paths also resolve against workspace_root.

Evaluated on host file_read, file_write, and editor; sandbox read_file / write_file / list_dir are not. See Permissions — Path mapping for the operation and path tables.

Presets

python
from elsai.permissions import preset, workspace_only, read_only, deny_secrets
Helperpreset(...) name
workspace_only()"workspace_only"
read_only()"read_only"
deny_secrets()"deny_secrets"

Unknown preset names raise ValueError. Behaviour of each preset is documented in Permissions — Filesystem presets.


ExecutionPermission

python
from elsai.permissions import ExecutionPermission

Frozen dataclass. Patterns are compiled as Python regexes at construction (re.search).

FieldTypeDefaultDescription
toolstuple[str, ...]required"shell", "python_repl", "execute"
patternstuple[str, ...]required unless require_workspace_cwdRegexes against command / code
mode"allow" | "deny" | "interrupt""allow"Decision when the rule matches
namestr | NoneNoneRule id
reasonstr | NoneNoneDeny / interrupt prompt
require_workspace_cwdboolFalseDeny when cwd is outside workspace_root
guidancestr | NoneNoneSteer text for guide denies

Empty patterns is allowed only when require_workspace_cwd=True. Invalid regex raises ValueError.

See Permissions — Command mapping for the input and cwd fields read from each tool.

Presets

python
from elsai.permissions import (
    execution_preset,
    deny_destructive,
    interrupt_all_shell,
    interrupt_all_execute,
    allow_safe_readonly_shell,
    require_workspace_cwd,
    host_shell_disabled,
)
Helperexecution_preset(...) name
deny_destructive()"deny_destructive"
interrupt_all_shell()"interrupt_all_shell"
interrupt_all_execute()"interrupt_all_execute"
allow_safe_readonly_shell()"allow_safe_readonly_shell"
require_workspace_cwd()"require_workspace_cwd"
host_shell_disabled()"host_shell_disabled"

Behaviour of each preset is documented in Permissions — Execution presets.


DenyPolicy

python
from elsai.permissions import DenyPolicy

Optional. Unset keeps soft-deny: cancel the tool and let the model continue.

FieldTypeDefault
on_deny"continue" | "stop" | "guide""continue"
on_budget_exceeded"continue" | "stop" | "guide""stop"
max_denies_per_invocationint | NoneNone
max_denies_per_tooldict[str, int] | NoneNone
max_denies_same_keyint | NoneNone
default_guidancestr | NoneNone
budget_guidancestr | NoneNone

Budget fields, when set, must be positive ints. Invalid actions raise ValueError.

on_deny="stop" sets invocation stop_reason to permission_denied (PERMISSION_DENIED_STOP_REASON).


Interrupt constants

python
from elsai.permissions import (
    FS_PERMISSION_INTERRUPT_NAME,       # "fs_permission"
    FS_PERMISSION_APPROVE_RESPONSE,     # "approve"
    EXEC_PERMISSION_INTERRUPT_NAME,     # "execution_permission"
    EXEC_PERMISSION_APPROVE_RESPONSE,   # "approve"
    WORKSPACE_PREFIX,                   # "/workspace"
    PERMISSION_DENIED_STOP_REASON,      # "permission_denied"
)

Resume an interrupt with response "approve" to run the tool. Any other response is a deny.


Plugins (auto-registered)

Do not pass these in AgentConfig.plugins for normal use. Agent registers them when the corresponding permission lists are non-empty.

python
from elsai.permissions import FilesystemPermissionPlugin, ExecutionPermissionsPlugin
ClassHookWhen
FilesystemPermissionPluginBeforeToolCallEventfilesystem_permissions is a non-empty list
ExecutionPermissionsPluginBeforeToolCallEventexecution_permissions is a non-empty list

Constructor: permissions, optional workspace_root, optional deny_policy.

Sub-agents with None permission lists inherit parent plugins via apply_inherited_permissions during as_tool(). An explicit empty list on the child disables inheritance.


Evaluation helpers

python
from elsai.permissions import (
    evaluate_filesystem_permission,
    evaluate_execution_permission,
    PermissionDecision,
)

Used by the plugins. Multi-path / multi-command aggregation: deny > interrupt > allow. No match → allow for that path or command.


Audit loggers

LoggerEvent name
elsai.filesystem.auditfilesystem.permission
elsai.execution.auditexecution.permission

Copyright © 2026 elsai foundry.