Permissions API¶
Types¶
PermissionAction¶
pydantic_ai_backends.permissions.types.PermissionAction = Literal['allow', 'deny', 'ask']
module-attribute
¶
PermissionOperation¶
pydantic_ai_backends.permissions.types.PermissionOperation = Literal['read', 'write', 'edit', 'execute', 'glob', 'grep', 'ls']
module-attribute
¶
PermissionRule¶
pydantic_ai_backends.permissions.types.PermissionRule
¶
Bases: BaseModel
A rule that matches paths/commands and specifies an action.
Rules are evaluated in order - first matching rule wins.
Patterns use fnmatch-style matching with support for ** (recursive).
Example
Source code in src/pydantic_ai_backends/permissions/types.py
pattern
instance-attribute
¶
Glob pattern to match against paths or commands.
Supports fnmatch patterns:
- * matches any characters except /
- ** matches any characters including / (recursive)
- ? matches any single character
- [seq] matches any character in seq
action
instance-attribute
¶
Action to take when pattern matches: "allow", "deny", or "ask".
description = ''
class-attribute
instance-attribute
¶
Human-readable description of why this rule exists.
OperationPermissions¶
pydantic_ai_backends.permissions.types.OperationPermissions
¶
Bases: BaseModel
Permissions configuration for a single operation type.
Contains a default action and a list of rules that override the default for specific patterns.
Example
Source code in src/pydantic_ai_backends/permissions/types.py
PermissionRuleset¶
pydantic_ai_backends.permissions.types.PermissionRuleset
¶
Bases: BaseModel
Complete permissions configuration for all operations.
Defines default behavior and per-operation permissions. Each operation can have its own default and rules.
Example
Source code in src/pydantic_ai_backends/permissions/types.py
default = 'ask'
class-attribute
instance-attribute
¶
Global default action when operation has no specific config.
read = None
class-attribute
instance-attribute
¶
Permissions for read operations.
write = None
class-attribute
instance-attribute
¶
Permissions for write operations.
edit = None
class-attribute
instance-attribute
¶
Permissions for edit operations.
execute = None
class-attribute
instance-attribute
¶
Permissions for execute operations (shell commands).
glob = None
class-attribute
instance-attribute
¶
Permissions for glob operations.
grep = None
class-attribute
instance-attribute
¶
Permissions for grep operations.
ls = None
class-attribute
instance-attribute
¶
Permissions for ls operations.
get_operation_permissions(operation)
¶
Get permissions for a specific operation.
Returns the operation-specific permissions if defined, otherwise creates default permissions using the global default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operation
|
PermissionOperation
|
The operation type to get permissions for. |
required |
Returns:
| Type | Description |
|---|---|
OperationPermissions
|
OperationPermissions for the specified operation. |
Source code in src/pydantic_ai_backends/permissions/types.py
Checker¶
PermissionChecker¶
pydantic_ai_backends.permissions.checker.PermissionChecker
¶
Checks operations against a permission ruleset.
Rules are evaluated in order and the first match wins. With no match the operation's default applies, falling back to the ruleset's global default.
Example
from pydantic_ai_backends.permissions import DEFAULT_RULESET, PermissionChecker
async def ask_user(op: str, target: str, reason: str) -> bool:
return input(f"Allow {op} on {target}? ").lower() == "y"
checker = PermissionChecker(ruleset=DEFAULT_RULESET, ask_callback=ask_user)
action = checker.check_sync("read", "/path/to/file")
allowed = await checker.check("write", "/path/to/file", "Save changes")
Source code in src/pydantic_ai_backends/permissions/checker.py
| Python | |
|---|---|
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | |
ruleset
property
¶
The ruleset being checked against.
__init__(ruleset, ask_callback=None, ask_fallback='error')
¶
Initialize the checker.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ruleset
|
PermissionRuleset
|
The ruleset to check against. |
required |
ask_callback
|
AskCallback | None
|
Async callback for "ask" actions. |
None
|
ask_fallback
|
AskFallback
|
What an unanswerable "ask" does — |
'error'
|
Source code in src/pydantic_ai_backends/permissions/checker.py
check_sync(operation, target)
¶
Resolve the action for an operation without invoking any callback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operation
|
PermissionOperation
|
The operation type. |
required |
target
|
str
|
The path or command being accessed. |
required |
Source code in src/pydantic_ai_backends/permissions/checker.py
check(operation, target, reason='')
async
¶
Resolve an operation, asking for approval when the rules say so.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operation
|
PermissionOperation
|
The operation type. |
required |
target
|
str
|
The path or command being accessed. |
required |
reason
|
str
|
Human-readable reason, passed to the callback. |
''
|
Returns:
| Type | Description |
|---|---|
bool
|
True when the operation is allowed. |
Raises:
| Type | Description |
|---|---|
PermissionDeniedError
|
If it is denied, or approval was refused. |
PermissionAskError
|
If approval is needed, no callback can give it
and |
Source code in src/pydantic_ai_backends/permissions/checker.py
is_allowed(operation, target)
¶
Whether the operation would proceed without asking.
is_denied(operation, target)
¶
Whether the operation would be refused outright.
requires_approval(operation, target)
¶
Whether the operation would need user approval.
PermissionAskError¶
Raised when a permission check resolves to "ask" but no ask_callback is
available and ask_fallback="error".
pydantic_ai_backends.permissions.checker.PermissionAskError
¶
Bases: Exception
Raised when an operation needs approval and ask_fallback="error".
Named PermissionAskError so it does not shadow the builtin
PermissionError (an OSError subclass) for importers of this module.
Attributes:
| Name | Type | Description |
|---|---|---|
operation |
The operation that needed approval. |
|
target |
The path or command it addressed. |
|
reason |
Why approval was being sought. |
Source code in src/pydantic_ai_backends/permissions/checker.py
PermissionError¶
Deprecated
PermissionError is a deprecated alias for
PermissionAskError.
It shadows the builtin PermissionError; use PermissionAskError instead.
pydantic_ai_backends.permissions.checker.PermissionError
¶
Bases: PermissionAskError
Deprecated alias for :class:PermissionAskError.
Source code in src/pydantic_ai_backends/permissions/checker.py
PermissionDeniedError¶
pydantic_ai_backends.permissions.checker.PermissionDeniedError
¶
Bases: Exception
Raised when an operation is explicitly denied.
Attributes:
| Name | Type | Description |
|---|---|---|
operation |
The operation that was denied. |
|
target |
The path or command it addressed. |
|
rule |
The rule that denied it, when a rule rather than a default did. |
Source code in src/pydantic_ai_backends/permissions/checker.py
Presets¶
DEFAULT_RULESET¶
pydantic_ai_backends.permissions.presets.DEFAULT_RULESET = PermissionRuleset(default='ask', read=OperationPermissions(default='allow', rules=deny_rules(SECRETS_PATTERNS, SECRETS_DESCRIPTION)), write=OperationPermissions(default='ask', rules=deny_rules(SECRETS_PATTERNS, SECRETS_DESCRIPTION)), edit=OperationPermissions(default='ask', rules=deny_rules(SECRETS_PATTERNS, SECRETS_DESCRIPTION)), execute=OperationPermissions(default='ask', rules=deny_rules(DANGEROUS_COMMANDS, DANGEROUS_DESCRIPTION)), glob=OperationPermissions(default='allow'), grep=OperationPermissions(default='allow'), ls=OperationPermissions(default='allow'))
module-attribute
¶
Safe default: reads allowed except secrets, writes and commands ask first.
PERMISSIVE_RULESET¶
pydantic_ai_backends.permissions.presets.PERMISSIVE_RULESET = PermissionRuleset(default='allow', read=OperationPermissions(default='allow', rules=deny_rules(SECRETS_PATTERNS, SECRETS_DESCRIPTION)), write=OperationPermissions(default='allow', rules=deny_rules(SECRETS_PATTERNS + SYSTEM_PATTERNS, SYSTEM_DESCRIPTION)), edit=OperationPermissions(default='allow', rules=deny_rules(SECRETS_PATTERNS + SYSTEM_PATTERNS, SYSTEM_DESCRIPTION)), execute=OperationPermissions(default='allow', rules=deny_rules(DANGEROUS_COMMANDS, DANGEROUS_DESCRIPTION)), glob=OperationPermissions(default='allow'), grep=OperationPermissions(default='allow'), ls=OperationPermissions(default='allow'))
module-attribute
¶
Everything allowed except secrets, system paths and dangerous commands.
READONLY_RULESET¶
pydantic_ai_backends.permissions.presets.READONLY_RULESET = PermissionRuleset(default='deny', read=OperationPermissions(default='allow', rules=deny_rules(SECRETS_PATTERNS, SECRETS_DESCRIPTION)), write=OperationPermissions(default='deny'), edit=OperationPermissions(default='deny'), execute=OperationPermissions(default='deny'), glob=OperationPermissions(default='allow'), grep=OperationPermissions(default='allow'), ls=OperationPermissions(default='allow'))
module-attribute
¶
Reads, listings and searches only — nothing may change or run.
STRICT_RULESET¶
pydantic_ai_backends.permissions.presets.STRICT_RULESET = PermissionRuleset(default='ask', read=OperationPermissions(default='ask', rules=deny_rules(SECRETS_PATTERNS, SECRETS_DESCRIPTION)), write=OperationPermissions(default='ask', rules=deny_rules(SECRETS_PATTERNS, SECRETS_DESCRIPTION)), edit=OperationPermissions(default='ask', rules=deny_rules(SECRETS_PATTERNS, SECRETS_DESCRIPTION)), execute=OperationPermissions(default='ask', rules=deny_rules(DANGEROUS_COMMANDS, DANGEROUS_DESCRIPTION)), glob=OperationPermissions(default='ask'), grep=OperationPermissions(default='ask'), ls=OperationPermissions(default='ask'))
module-attribute
¶
Every operation requires explicit approval.
create_ruleset¶
pydantic_ai_backends.permissions.presets.create_ruleset(*, default='ask', allow_read=True, allow_write=False, allow_edit=False, allow_execute=False, allow_glob=True, allow_grep=True, allow_ls=True, deny_secrets=True)
¶
Build a ruleset from per-operation allow/ask switches.
Each allow_* flag chooses between "allow" and "ask" for that
operation's default.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
default
|
PermissionAction
|
Global default for operations with no configuration. |
'ask'
|
allow_read
|
bool
|
Allow reads outright rather than asking. |
True
|
allow_write
|
bool
|
Allow writes outright rather than asking. |
False
|
allow_edit
|
bool
|
Allow edits outright rather than asking. |
False
|
allow_execute
|
bool
|
Allow commands outright rather than asking. |
False
|
allow_glob
|
bool
|
Allow globbing outright rather than asking. |
True
|
allow_grep
|
bool
|
Allow searching outright rather than asking. |
True
|
allow_ls
|
bool
|
Allow listings outright rather than asking. |
True
|
deny_secrets
|
bool
|
Deny the paths in |
True
|
Source code in src/pydantic_ai_backends/permissions/presets.py
Patterns¶
SECRETS_PATTERNS¶
pydantic_ai_backends.permissions.presets.SECRETS_PATTERNS = ['**/.env', '**/.env.*', '**/*.pem', '**/*.key', '**/*.crt', '**/credentials*', '**/secrets*', '**/*secret*', '**/*password*', '**/.aws/**', '**/.ssh/**', '**/.gnupg/**']
module-attribute
¶
Paths that typically hold credentials.
SYSTEM_PATTERNS¶
pydantic_ai_backends.permissions.presets.SYSTEM_PATTERNS = ['/etc/**', '/var/**', '/usr/**', '/bin/**', '/sbin/**', '/boot/**', '/sys/**', '/proc/**']
module-attribute
¶
Paths owned by the operating system rather than the workspace.
Callback Types¶
AskCallback¶
pydantic_ai_backends.permissions.checker.AskCallback = Callable[[PermissionOperation, str, str], Awaitable[bool]]
module-attribute
¶
Approval callback: (operation, target, reason) -> whether to allow.
AskFallback¶
pydantic_ai_backends.permissions.checker.AskFallback = Literal['deny', 'error']
module-attribute
¶
What an "ask" does when no callback can answer it.