Permission Plugin
Control which tools the model can execute through policy-based access control with blacklist/whitelist rules and interactive approval.
| Name | permission |
| Type | Client-configured Plugin |
| Tools Provided | askPermission |
| User Commands | permissions |
| Auto-approved | permissions |
Two Distinct Roles
The permission plugin serves two independent roles:
-
Permission Enforcement (Middleware)
Wraps tool execution to check permissions before any tool runs. Enabled viaconfigure_tools(permission_plugin=...) -
Proactive Check Tool
ExposesaskPermissionfor the model to query permissions. Enabled viaexpose_tool("permission")
from jaato import PluginRegistry
from shared import PermissionPlugin
# Create permission plugin
permission = PermissionPlugin()
permission.initialize({
'channel_type': 'console',
'policy': {
'default': 'ask',
'whitelist_tools': ['readFile', 'web_search'],
'blacklist_tools': ['rm', 'sudo'],
}
})
# Configure on client for enforcement
client.configure_tools(
registry,
permission_plugin=permission,
)
# Optionally expose askPermission tool
registry.expose_tool('permission')
# Enforcement only (no askPermission tool)
client.configure_tools(registry, permission_plugin=permission)
# Enforcement + proactive checks
client.configure_tools(registry, permission_plugin=permission)
registry.expose_tool('permission')
# No enforcement, proactive only (not recommended)
registry.expose_tool('permission')
Configuration Parameters
config_path
Path to permissions.json configuration file.
| Type | str |
| Default | ".jaato/permissions.json" |
channel_type
How to request approval from the user.
| Type | "console" | "webhook" | "file" |
| Default | "console" |
channel_config
Configuration for the approval channel.
| Type | Dict[str, Any] |
| Default | {} |
policy
Inline policy dict (overrides config file).
| Type | Dict[str, Any] |
| Default | From config file |
permission = PermissionPlugin()
permission.initialize({
'channel_type': 'console',
'policy': {
'default': 'ask',
'whitelist_tools': [
'readFile',
'web_search',
'getPlanStatus',
],
'blacklist_tools': [
'rm -rf *',
'sudo *',
],
'whitelist_patterns': ['read*', 'get*'],
'blacklist_patterns': ['*delete*', '*remove*'],
}
})
{
"channel_type": "console",
"channel_timeout": 30,
"default": "ask",
"whitelist_tools": ["readFile", "web_search"],
"blacklist_tools": ["rm", "sudo"],
"whitelist_patterns": ["read*"],
"blacklist_patterns": ["*delete*"]
}
Policy Rules
Permission decisions are made in this order:
- Blacklist check: If tool matches blacklist, deny
- Whitelist check: If tool matches whitelist, allow
- Default policy: Apply default (allow/deny/ask)
Default Policies
| Policy | Behavior |
|---|---|
allow | Auto-approve all unmatched tools |
deny | Auto-deny all unmatched tools |
ask | Prompt channel for each unmatched tool |
Pattern Matching
Whitelist/blacklist support glob patterns:
*matches any characters?matches single character[seq]matches characters in seq
# Permissive: allow all, block dangerous
{
'default': 'allow',
'blacklist_patterns': ['*delete*', '*remove*', 'sudo*'],
}
# Restrictive: deny all, allow specific
{
'default': 'deny',
'whitelist_tools': ['readFile', 'web_search'],
}
# Interactive: ask for unknown
{
'default': 'ask',
'whitelist_tools': ['readFile'], # Auto-approve reads
'blacklist_tools': ['rm'], # Auto-deny deletes
}
User Command
permissions
Manage session permissions on-the-fly. Changes persist for the current session only.
Subcommands
| Command | Description |
|---|---|
permissions show | Display current effective policy |
permissions check <tool> | Test what decision a tool would get |
permissions allow <pattern> | Add to session whitelist |
permissions deny <pattern> | Add to session blacklist |
permissions default <policy> | Set session default (allow/deny/ask) |
permissions clear | Reset all session modifications |
permissions command only affect
the current session. They don't modify the config file.
> permissions show
Current Policy:
Default: ask
Whitelist: readFile, web_search
Blacklist: rm, sudo
> permissions allow cli_based_tool
Added 'cli_based_tool' to session whitelist
> permissions default allow
Session default set to 'allow'
> permissions check updateFile
Tool: updateFile
Decision: ASK (no rule match, default policy)
> permissions clear
Session modifications cleared
Interactive Approval
When a tool requires approval (policy is "ask" or no rule match), the channel prompts the user:
Console Channel
Shows tool details and waits for keyboard input:
[y]es: Allow this execution[n]o: Deny this execution[a]lways: Allow and add to session whitelist[never]: Deny and add to session blacklist
Custom Display
Plugins can provide custom formatting for their tools via
format_permission_request(). For example, file_edit
shows unified diffs for file modifications.
Tool: cli_based_tool
Intent: List files to find config
Arguments:
{
"command": "ls -la /etc"
}
[y]es / [n]o / [a]lways / [never]: _
Tool: updateFile
Summary: Update file: src/main.py (+5/-2 lines)
--- src/main.py (original)
+++ src/main.py (modified)
@@ -1,5 +1,8 @@
import sys
+import os
+from pathlib import Path
def main():
- print("hello")
+ print("Hello, World!")
[y]es / [n]o / [a]lways / [never]: _
askPermission Tool
Allows the model to proactively check if a tool is allowed before attempting execution.
Parameters
| Name | Type | Required |
|---|---|---|
tool_name | string | Yes |
intent | string | Yes |
arguments | object | No |
Response
| Field | Type | Description |
|---|---|---|
allowed | bool | Whether tool is permitted |
reason | string | Explanation of decision |
rule_matched | string | Which rule applied |
# Model checks before executing
askPermission(
tool_name="cli_based_tool",
intent="Delete temporary files to free disk space",
arguments={"command": "rm -rf /tmp/cache/*"}
)
# Response
{
"allowed": false,
"reason": "Tool matches blacklist pattern",
"rule_matched": "rm*"
}
{
"allowed": true,
"reason": "Tool is whitelisted",
"rule_matched": "readFile"
}