Skip to main content

Overview

The permissions module provides pattern matching utilities to control which tools an agent can execute. It uses glob patterns to match tool names and parameters against allowlists.

Key Features

  • Glob pattern matching for tool parameters
  • Flexible allowlist/allowOnce/deny permission model
  • Composable permission rules
  • Support for parameter-level restrictions

Functions

matchesPermission()

Check if a tool call matches a specific permission rule.
const matches = matchesPermission(toolCall, permission);
toolCall
ToolCallLike
required
The tool call to check
toolCall.name
string
required
Name of the tool being called
toolCall.arguments
Record<string, unknown>
Arguments passed to the tool
permission
ToolPermission
required
The permission rule to match against
permission.tool
string
required
Tool name to match
permission.params
Record<string, string>
Parameter patterns (param name → glob pattern)
matches
boolean
Returns true if the tool call matches the permission rule

matchesPermissions()

Check if a tool call matches any permission in an allowlist or allowOnce list.
const allowed = matchesPermissions(toolCall, permissions);
toolCall
ToolCallLike
required
The tool call to check
permissions
Pick<Permissions, 'allowlist' | 'allowOnce'>
Permissions object with allowlist and/or allowOnce arrays
allowed
boolean
Returns true if the tool call matches any permission in the combined allowlist and allowOnce

Types

ToolPermission

Defines a permission rule for a tool.
interface ToolPermission {
  tool: string;
  params?: Record<string, string>; // param name → glob pattern
}

Permissions

Complete permissions structure for an agent.
interface Permissions {
  allowlist?: ToolPermission[];
  allowOnce?: ToolPermission[];
  deny?: Array<{ toolCallId: string; reason?: string }>;
}
allowlist
ToolPermission[]
Permissions that are always allowed. Matching tool calls execute without requesting approval.
allowOnce
ToolPermission[]
Permissions allowed once. After matching, the permission is removed from allowOnce.
deny
Array<{ toolCallId: string; reason?: string }>
Explicitly denied tool calls by ID with optional reasons.

ToolCallLike

Minimal interface for tool call matching.
interface ToolCallLike {
  name: string;
  arguments?: Record<string, unknown>;
}

Examples

Basic Tool Matching

import { matchesPermission } from "@llm-gateway/ai";

const toolCall = {
  name: "read",
  arguments: { path: "/data/file.txt" },
};

const permission = {
  tool: "read",
};

const matches = matchesPermission(toolCall, permission);
// true - tool name matches, no params specified

Parameter Pattern Matching

const toolCall = {
  name: "read",
  arguments: { path: "/data/users/john.json" },
};

// Allow reading any file in /data/users/
const permission = {
  tool: "read",
  params: {
    path: "/data/users/*",
  },
};

const matches = matchesPermission(toolCall, permission);
// true - path matches the glob pattern

Multiple Parameter Patterns

const toolCall = {
  name: "bash",
  arguments: {
    command: "ls",
    workdir: "/home/user/projects",
  },
};

const permission = {
  tool: "bash",
  params: {
    command: "ls", // Exact match
    workdir: "/home/user/*", // Glob pattern
  },
};

const matches = matchesPermission(toolCall, permission);
// true - both parameters match

Allowlist Checking

import { matchesPermissions } from "@llm-gateway/ai";

const permissions = {
  allowlist: [
    { tool: "read", params: { path: "/data/*" } },
    { tool: "grep", params: { path: "/data/*" } },
  ],
  allowOnce: [{ tool: "write", params: { path: "/tmp/*" } }],
};

const readCall = {
  name: "read",
  arguments: { path: "/data/file.txt" },
};

const allowed = matchesPermissions(readCall, permissions);
// true - matches allowlist

const writeCall = {
  name: "write",
  arguments: { path: "/tmp/output.txt" },
};

const allowedOnce = matchesPermissions(writeCall, permissions);
// true - matches allowOnce

Complex Glob Patterns

// Match any .txt or .md file
const permission = {
  tool: "read",
  params: {
    path: "**/*.{txt,md}",
  },
};

matchesPermission({ name: "read", arguments: { path: "docs/guide.md" } }, permission);
// true

matchesPermission({ name: "read", arguments: { path: "src/code.ts" } }, permission);
// false

// Match files but not directories
const filePermission = {
  tool: "read",
  params: {
    path: "**/!(*/)" // Matches anything that doesn't end with /
  },
};

Permission Builder Helper

function createFilePermission(tool: string, basePath: string): ToolPermission {
  return {
    tool,
    params: {
      path: `${basePath}/**/*`,
    },
  };
}

const permissions = {
  allowlist: [
    createFilePermission("read", "/data"),
    createFilePermission("write", "/output"),
    { tool: "bash", params: { command: "ls" } },
  ],
};

Runtime Permission Derivation

import type { ToolDefinition } from "@llm-gateway/ai";

const readTool: ToolDefinition = {
  name: "read",
  description: "Read a file",
  schema: z.object({ path: z.string() }),
  derivePermission: (params) => ({
    tool: "read",
    params: {
      path: params.path, // Allow this specific file
    },
  }),
  execute: async (input) => {
    // ...
  },
};

// When user approves with "always", the orchestrator calls derivePermission
// and adds the result to the agent's allowlist

Directory-Scoped Permissions

const permissions = {
  allowlist: [
    // Allow all read operations in specific directories
    { tool: "read", params: { path: "/data/**" } },
    { tool: "glob", params: { path: "/data/**" } },
    { tool: "grep", params: { path: "/data/**" } },

    // Allow write operations only in output directory
    { tool: "write", params: { path: "/output/**" } },

    // Allow bash commands in project directory
    { tool: "bash", params: { workdir: "/project/**" } },
  ],
};

Glob Pattern Reference

Permissions use the picomatch library with bash mode enabled.

Common Patterns

PatternMatches
*Any characters except /
**Any characters including / (recursive)
?Single character
[abc]Any character in the set
{a,b}Either a or b
!(pattern)Anything except the pattern

Examples

// Match specific file
{ path: "config.json" }

// Match all files in directory
{ path: "/data/*" }

// Match all files recursively
{ path: "/data/**/*" }

// Match specific extension
{ path: "**/*.ts" }

// Match multiple extensions
{ path: "**/*.{ts,js,tsx,jsx}" }

// Match except pattern
{ path: "!**/node_modules/**" }

// Combine patterns (both must match)
{
  path: "/data/**/*.json",
  size: "<1000000" // Custom validation if supported
}

Build docs developers (and LLMs) love