> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/vercel-labs/agent-browser/llms.txt
> Use this file to discover all available pages before exploring further.

# Action Policies

> Gate destructive actions and require confirmation for sensitive operations

# Action Policies

Action policies provide fine-grained control over what actions an AI agent can perform. Use static policy files to gate destructive actions or require explicit confirmation for sensitive operations.

## Quick Start

```bash theme={null}
# Create policy file
cat > policy.json <<EOF
{
  "default": "deny",
  "allow": ["navigate", "click", "fill", "get", "snapshot"]
}
EOF

# Apply policy
agent-browser --action-policy ./policy.json open example.com
```

## Policy File Format

Action policies are JSON files with the following structure:

```json theme={null}
{
  "default": "allow" | "deny",
  "allow": ["category1", "category2"],
  "deny": ["category3", "category4"]
}
```

### Fields

<table>
  <thead>
    <tr>
      <th>Field</th>
      <th>Type</th>
      <th>Required</th>
      <th>Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><code>default</code></td>
      <td><code>"allow" | "deny"</code></td>
      <td>Yes</td>
      <td>Default policy for actions not in allow/deny lists</td>
    </tr>

    <tr>
      <td><code>allow</code></td>
      <td><code>string\[]</code></td>
      <td>No</td>
      <td>Action categories to explicitly allow</td>
    </tr>

    <tr>
      <td><code>deny</code></td>
      <td><code>string\[]</code></td>
      <td>No</td>
      <td>Action categories to explicitly deny (takes precedence)</td>
    </tr>
  </tbody>
</table>

## Action Categories

Actions are grouped into categories for easier policy management:

<table>
  <thead>
    <tr>
      <th>Category</th>
      <th>Actions</th>
      <th>Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><code>navigate</code></td>
      <td>navigate, back, forward, reload, tab\_new</td>
      <td>Page navigation</td>
    </tr>

    <tr>
      <td><code>click</code></td>
      <td>click, dblclick, tap</td>
      <td>Click interactions</td>
    </tr>

    <tr>
      <td><code>fill</code></td>
      <td>fill, type, keyboard, inserttext, select, multiselect, check, uncheck, clear, selectall, setvalue</td>
      <td>Form input and text entry</td>
    </tr>

    <tr>
      <td><code>download</code></td>
      <td>download, waitfordownload</td>
      <td>File downloads</td>
    </tr>

    <tr>
      <td><code>upload</code></td>
      <td>upload</td>
      <td>File uploads</td>
    </tr>

    <tr>
      <td><code>eval</code></td>
      <td>evaluate, evalhandle, addscript, addinitscript, addstyle, expose, setcontent</td>
      <td>JavaScript evaluation (high risk)</td>
    </tr>

    <tr>
      <td><code>snapshot</code></td>
      <td>snapshot, screenshot, pdf, diff\_snapshot, diff\_screenshot, diff\_url</td>
      <td>Page inspection and diffing</td>
    </tr>

    <tr>
      <td><code>scroll</code></td>
      <td>scroll, scrollintoview</td>
      <td>Scrolling</td>
    </tr>

    <tr>
      <td><code>wait</code></td>
      <td>wait, waitforurl, waitforloadstate, waitforfunction</td>
      <td>Waiting operations</td>
    </tr>

    <tr>
      <td><code>get</code></td>
      <td>gettext, content, innerhtml, innertext, inputvalue, url, title, getattribute, count, boundingbox, styles, isvisible, isenabled, ischecked, responsebody, getbyrole, getbytext, etc.</td>
      <td>Read-only data retrieval</td>
    </tr>

    <tr>
      <td><code>network</code></td>
      <td>route, unroute, requests</td>
      <td>Network interception</td>
    </tr>

    <tr>
      <td><code>state</code></td>
      <td>state\_save, state\_load, cookies\_set, storage\_set, credentials</td>
      <td>Browser state manipulation</td>
    </tr>

    <tr>
      <td><code>interact</code></td>
      <td>hover, focus, drag, press, keydown, keyup, mousemove, mousedown, mouseup, wheel, dispatch</td>
      <td>Low-level interactions</td>
    </tr>
  </tbody>
</table>

## Policy Evaluation

When an action is requested, the policy is evaluated in this order:

1. **Internal actions** - Always allowed (launch, close, session management, etc.)
2. **Explicit deny** - If category is in `deny` list, action is denied
3. **Confirmation required** - If category is in `--confirm-actions`, prompt user (if interactive)
4. **Explicit allow** - If category is in `allow` list, action is allowed
5. **Default policy** - Use `default` value ("allow" or "deny")

### Internal Actions

These actions bypass policy checks and are always allowed:

* Browser management: `launch`, `close`, `tab_list`, `tab_switch`, `tab_close`
* Session management: `session`
* Information: `cookies_get`, `storage_get`, `state_list`, `state_show`
* Debugging: `console`, `errors`, `highlight`, `trace_start`, `trace_stop`
* Auth: `auth_save`, `auth_login`, `auth_list`, `auth_delete`, `auth_show`
* Confirmation: `confirm`, `deny`

## Common Policy Patterns

### Read-Only Agent

Allow only inspection, no interaction:

```json theme={null}
{
  "default": "deny",
  "allow": ["navigate", "get", "snapshot", "scroll", "wait"]
}
```

### Safe Interaction Agent

Allow navigation and form filling, deny dangerous actions:

```json theme={null}
{
  "default": "allow",
  "deny": ["eval", "download", "upload", "network", "state"]
}
```

### Minimal Permissions

Only essential actions:

```json theme={null}
{
  "default": "deny",
  "allow": ["navigate", "click", "fill", "get", "snapshot"]
}
```

### Development Mode

Allow everything except eval:

```json theme={null}
{
  "default": "allow",
  "deny": ["eval"]
}
```

## Action Confirmation

Require explicit user approval for sensitive action categories:

```bash theme={null}
# Require confirmation for eval and download
agent-browser \
  --confirm-actions eval,download \
  --confirm-interactive \
  open example.com
```

### Confirmation Flow

When an action requires confirmation:

1. Agent requests the action
2. CLI prompts user with action details
3. User approves (`confirm`) or denies (`deny`)
4. Action proceeds or is rejected

**Example:**

```bash theme={null}
# Agent tries to evaluate JavaScript
agent-browser eval "console.log('test')"

# User sees prompt:
# Action requires confirmation:
#   Category: eval
#   Action: Evaluate JavaScript: console.log('test')
# 
# Approve this action?
#   agent-browser confirm
#   agent-browser deny

# User approves
agent-browser confirm

# Action executes
```

### Interactive vs Non-Interactive

* **Interactive mode** (`--confirm-interactive`): Prompts user via CLI
* **Non-interactive mode**: Auto-denies if stdin is not a TTY

This prevents hanging in CI/CD environments.

### Confirmation Categories

Common categories to require confirmation:

* `eval` - JavaScript execution (high risk)
* `download` - File downloads (data exfiltration risk)
* `upload` - File uploads (may leak local files)
* `network` - Network interception (can modify responses)
* `state` - State manipulation (can steal cookies)

## Hot Reloading

Policy files are automatically reloaded every 5 seconds. Update the policy without restarting the browser:

```bash theme={null}
# Start with initial policy
agent-browser --action-policy ./policy.json open example.com

# Edit policy.json
vi policy.json

# Policy is automatically reloaded
# Next action uses new policy (within 5 seconds)
```

This enables dynamic policy adjustment during agent sessions.

## Environment Variables

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Description</th>
      <th>Example</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td><code>AGENT\_BROWSER\_ACTION\_POLICY</code></td>
      <td>Path to action policy JSON file</td>
      <td><code>./policy.json</code></td>
    </tr>

    <tr>
      <td><code>AGENT\_BROWSER\_CONFIRM\_ACTIONS</code></td>
      <td>Comma-separated action categories requiring confirmation</td>
      <td><code>eval,download</code></td>
    </tr>

    <tr>
      <td><code>AGENT\_BROWSER\_CONFIRM\_INTERACTIVE</code></td>
      <td>Enable interactive confirmation prompts</td>
      <td><code>true</code></td>
    </tr>
  </tbody>
</table>

## Configuration File

Set action policy in `agent-browser.json`:

```json theme={null}
{
  "actionPolicy": "./policy.json",
  "confirmActions": "eval,download",
  "confirmInteractive": true
}
```

## Programmatic API

Check and enforce action policies programmatically:

```typescript theme={null}
import {
  loadPolicyFile,
  checkPolicy,
  getActionCategory,
  describeAction,
  type ActionPolicy,
  type PolicyDecision
} from 'agent-browser/action-policy';

// Load policy from file
const policy: ActionPolicy = loadPolicyFile('./policy.json');
console.log(policy);
// {
//   default: 'deny',
//   allow: ['navigate', 'click', 'fill'],
//   deny: ['eval']
// }

// Check if action is allowed
const confirmCategories = new Set(['download']);
const decision: PolicyDecision = checkPolicy('evaluate', policy, confirmCategories);
console.log(decision); // 'deny' (eval is in deny list)

const decision2 = checkPolicy('click', policy, confirmCategories);
console.log(decision2); // 'allow' (click is in allow list)

const decision3 = checkPolicy('download', policy, confirmCategories);
console.log(decision3); // 'confirm' (download requires confirmation)

// Get action category
const category = getActionCategory('fill');
console.log(category); // 'fill'

const category2 = getActionCategory('dblclick');
console.log(category2); // 'click'

// Describe action for user prompts
const description = describeAction('navigate', { url: 'https://example.com' });
console.log(description); // 'Navigate to https://example.com'

const description2 = describeAction('evaluate', { script: 'console.log("test")' });
console.log(description2); // 'Evaluate JavaScript: console.log("test")'
```

### Auto-reloading Policy

```typescript theme={null}
import { initPolicyReloader, reloadPolicyIfChanged } from 'agent-browser/action-policy';

// Initialize reloader
const policy = loadPolicyFile('./policy.json');
initPolicyReloader('./policy.json', policy);

// Check for updates (max once per 5 seconds)
setInterval(() => {
  const updatedPolicy = reloadPolicyIfChanged();
  if (updatedPolicy) {
    console.log('Policy reloaded:', updatedPolicy);
  }
}, 1000);
```

## Best Practices

### 1. Start with Deny-by-Default

For production agents, use deny-by-default and explicitly allow required actions:

```json theme={null}
{
  "default": "deny",
  "allow": ["navigate", "click", "fill", "get", "snapshot"]
}
```

### 2. Always Deny Eval

JavaScript evaluation is high-risk. Deny it unless absolutely necessary:

```json theme={null}
{
  "default": "allow",
  "deny": ["eval"]
}
```

Denying `eval` also prevents bypassing domain allowlist (see [Domain Allowlist](/security/domain-allowlist)).

### 3. Require Confirmation for Downloads

Prevent data exfiltration by requiring confirmation for downloads:

```bash theme={null}
agent-browser \
  --confirm-actions download \
  --confirm-interactive \
  open example.com
```

### 4. Combine with Domain Allowlist

For maximum security, use both action policy and domain allowlist:

```bash theme={null}
agent-browser \
  --allowed-domains "myapp.com,*.myapp.com" \
  --action-policy ./policy.json \
  open https://myapp.com
```

### 5. Use Hot Reloading for Testing

During development, use hot reloading to adjust policies without restarting:

```bash theme={null}
# Start browser with policy
agent-browser --action-policy ./policy.json open example.com

# Edit policy.json as needed
# New policy takes effect automatically
```

## Troubleshooting

### Action denied by policy

**Symptom**: Action fails with error like `Action 'evaluate' denied by policy`

**Solution**: Add the action's category to the `allow` list:

```json theme={null}
{
  "default": "deny",
  "allow": ["navigate", "click", "eval"]
}
```

Or change default to `"allow"` and only deny specific categories.

### Unrecognized action category warning

**Symptom**: Warning like `unrecognized action category "typo" in policy file`

**Solution**: Fix the typo in your policy file. Valid categories are:

* navigate, click, fill, download, upload, eval, snapshot, scroll, wait, get, network, state, interact

### Confirmation prompts in CI/CD

**Symptom**: Agent hangs waiting for confirmation in CI/CD environment

**Solution**: Don't use `--confirm-interactive` in non-interactive environments. Instead, use action policy to deny actions:

```json theme={null}
{
  "default": "allow",
  "deny": ["eval", "download"]
}
```

### Policy file not found

**Symptom**: Error like `ENOENT: no such file or directory`

**Solution**: Ensure the policy file path is correct (relative to current directory):

```bash theme={null}
# Absolute path
agent-browser --action-policy /home/user/policy.json

# Relative path
agent-browser --action-policy ./policy.json

# Or use environment variable
export AGENT_BROWSER_ACTION_POLICY=./policy.json
agent-browser open example.com
```

## See Also

* [Security Overview](/security/overview) - All security features
* [Domain Allowlist](/security/domain-allowlist) - Network restriction
* [Auth Vault](/security/auth-vault) - Credential storage
