# Understanding the Pi-Web Tool Presets System: NONE, READ_ONLY, DEFAULT, and FULL

> Explore the pi-web tool presets system: NONE, READ_ONLY, DEFAULT, and FULL. Learn how these security tiers manage external tool access for AI assistants and secure your sessions.

- Repository: [Alex Yang/pi-web](https://github.com/agegr/pi-web)
- Tags: deep-dive
- Published: 2026-08-13

---

**The pi-web tool presets system provides four security tiers—NONE, READ_ONLY, DEFAULT, and FULL—that restrict or enable external tool access for AI assistants, with configurations defined in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts) and enforced during session initialization in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts).**

The pi-web repository (`agegr/pi-web`) implements a granular permission architecture to sandbox AI capabilities. The **pi-web tool presets system** allows users to specify exactly which external operations—such as file system mutations, HTTP requests, or shell execution—an assistant may invoke during a chat session.

## What Are Pi-Web Tool Presets?

Tool presets are security policies that map to specific allow-lists of executable functions. When an `AgentSession` is created, the pi-web client sends a derived array of permitted tool names to the Pi SDK. The SDK then rejects any tool invocation not explicitly listed in that array.

The preset definitions live in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts), which exports the `ToolPreset` enum and the `applyPreset()` helper function. User preferences are persisted via [`lib/tool-preset-preference.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-preset-preference.ts), while the enforcement point resides in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) during `startRpcSession()`.

## The Four Preset Security Levels

### NONE (Maximum Security)

The **NONE** preset blocks all external tools. The assistant operates in a pure text-only mode with zero side effects.

- **Tool allow-list**: `[]` (empty array)
- **Use case**: Safe Q&A sessions where filesystem or network access must be completely prevented.

### READ_ONLY (Inspection Only)

The **READ_ONLY** preset permits observational tools while blocking any write or execution capabilities.

- **Tool allow-list**: `["readFile", "listFiles"]`
- **Use case**: Reviewing logs or inspecting codebases without risk of accidental modification.

### DEFAULT (Standard Operations)

The **DEFAULT** preset enables the standard suite of tools shipped with pi-web, balancing utility with safety.

- **Tool allow-list**: `["readFile", "writeFile", "httpFetch"]`
- **Use case**: Interactive coding assistance where the assistant needs to read files, write patches, and fetch documentation.

### FULL (Unrestricted Access)

The **FULL** preset grants access to all registered tools, including custom plugins installed by the user.

- **Tool allow-list**: `["*"]` (wildcard matching all tools)
- **Use case**: Administrative tasks requiring shell commands, plugin installation, or unrestricted system access.

## Implementation Architecture

The preset system spans three core modules that handle definition, persistence, and enforcement.

### Preset Definitions in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts)

This file contains the canonical enum and the mapping logic:

```typescript
// lib/tool-presets.ts
export enum ToolPreset {
  NONE = "none",
  READ_ONLY = "readOnly",
  DEFAULT = "default",
  FULL = "full",
}

const presetToolMap: Record<ToolPreset, string[]> = {
  [ToolPreset.NONE]: [],
  [ToolPreset.READ_ONLY]: ["readFile", "listFiles"],
  [ToolPreset.DEFAULT]: ["readFile", "writeFile", "httpFetch"],
  [ToolPreset.FULL]: ["*"],
};

export function applyPreset(preset: ToolPreset): string[] {
  return presetToolMap[preset] ?? presetToolMap[ToolPreset.DEFAULT];
}

```

### Preference Persistence in [`lib/tool-preset-preference.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-preset-preference.ts)

User selections survive page reloads through `localStorage`:

```typescript
// lib/tool-preset-preference.ts
export function getStoredToolPreset(): ToolPreset {
  const stored = localStorage.getItem('tool-preset');
  return Object.values(ToolPreset).includes(stored as ToolPreset) 
    ? (stored as ToolPreset) 
    : ToolPreset.DEFAULT;
}

export function storeToolPreset(preset: ToolPreset): void {
  localStorage.setItem('tool-preset', preset);
}

```

### Session Enforcement in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts)

During session creation, the preset translates into the `toolAllowList` parameter passed to the Pi SDK:

```typescript
// lib/rpc-manager.ts
import { applyPreset, ToolPreset } from "./tool-presets";

export async function startRpcSession(opts: {
  cwd: string;
  message: string;
  toolPreset?: ToolPreset;
}) {
  const tools = opts.toolPreset 
    ? applyPreset(opts.toolPreset) 
    : applyPreset(ToolPreset.DEFAULT);
    
  const wrapper = new AgentSessionWrapper({
    cwd: opts.cwd,
    initialMessage: opts.message,
    toolAllowList: tools,
  });
  // Session initialized with restricted capabilities...
}

```

## How Presets Flow from UI to SDK

The data flow follows four discrete stages when a user initiates a new chat:

1. **Selection**: The user chooses a preset from the dropdown in [`components/ChatInput.tsx`](https://github.com/agegr/pi-web/blob/main/components/ChatInput.tsx).
2. **Persistence**: `storeToolPreset()` writes the value to `localStorage`.
3. **Transmission**: The client POSTs to `/api/agent/new` with the tool array derived from `applyPreset()`.
4. **Enforcement**: [`rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/rpc-manager.ts) instantiates `AgentSessionWrapper`, passing the allow-list to the Pi SDK constructor via the `toolAllowList` property.

Once the session initializes, the SDK locks the tool configuration. Any attempt to invoke a tool outside the allow-list results in a "tool not allowed" error surfaced in the UI.

## Practical Usage Scenarios

| Scenario | Recommended Preset | Rationale |
|----------|-------------------|-----------|
| **Reviewing production logs** | `READ_ONLY` | Prevents accidental file modifications during audit. |
| **General coding assistance** | `DEFAULT` | Balances read/write access without shell execution risks. |
| **Safe demonstration mode** | `NONE` | Guarantees zero side effects during public demos. |
| **System administration** | `FULL` | Required for running shell commands and custom plugins. |

## Summary

- The **pi-web tool presets system** defines four security levels via the `ToolPreset` enum in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts).
- **NONE** blocks all tools, **READ_ONLY** permits inspection only, **DEFAULT** enables standard file and HTTP operations, and **FULL** allows unrestricted access including custom plugins.
- Preset preferences persist across sessions via `localStorage` managed by [`lib/tool-preset-preference.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-preset-preference.ts).
- The Pi SDK receives the final allow-list during `AgentSessionWrapper` construction in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts), locking capabilities for the session duration.
- Changing presets requires creating a new session; runtime modification is not supported by the underlying SDK.

## Frequently Asked Questions

### What is the default tool preset in pi-web?

If no preset is specified, the system falls back to `ToolPreset.DEFAULT`, which enables `readFile`, `writeFile`, and `httpFetch` according to the mapping in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts). This default is applied in `startRpcSession()` when the `toolPreset` option is undefined.

### How do I persist a tool preset selection across browser sessions?

The [`lib/tool-preset-preference.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-preset-preference.ts) module provides `storeToolPreset()` and `getStoredToolPreset()` functions that write to and read from the browser's `localStorage`. When the UI initializes, it calls `getStoredToolPreset()` to restore the user's last selection.

### Can I change the tool preset after starting a chat session?

No. The Pi SDK locks the `toolAllowList` at session construction time within `AgentSessionWrapper`. To use a different preset, you must terminate the current session and create a new one with the desired security level selected.

### Where are the tool allow-lists defined in the source code?

The canonical mappings reside in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts) within the `presetToolMap` record. This object explicitly lists which tool names (or the `"*"` wildcard for FULL) correspond to each `ToolPreset` enum value.