# How Tool Presets Work in Pi Web: PRESET_NONE, DEFAULT, and FULL Explained

> Understand Pi Web tool presets like PRESET_NONE, DEFAULT, and FULL. Learn how constants and helper functions manage assistant capabilities for session initialization.

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

---

**TLDR:** Pi Web controls assistant capabilities through three constant arrays defined in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts), using helper functions to bidirectionally map between preset names and concrete tool lists during session initialization.

The `agegr/pi-web` repository implements a session-based tool management system that restricts which built-in tools an AI assistant can invoke. Understanding how `PRESET_NONE`, `PRESET_DEFAULT`, and `PRESET_FULL` function is essential for configuring secure agent interactions and managing filesystem access permissions.

## The Three Preset Constants in lib/tool-presets.ts

The file [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts) exports three constant arrays that serve as the single source of truth for available tool combinations. These constants define the security boundaries for agent capabilities.

### PRESET_NONE – Complete Tool Restriction

`PRESET_NONE` is defined as an empty array, representing the most restrictive configuration where the assistant cannot access any built-in tools.

### PRESET_DEFAULT – Core File Operations

`PRESET_DEFAULT` enables the four essential tools required for basic interaction:

- `read`
- `bash`
- `edit`
- `write`

This preset provides sufficient access for reading files, executing shell commands, and modifying content without exposing filesystem search utilities.

### PRESET_FULL – Extended Search Capabilities

`PRESET_FULL` includes all tools from the default preset plus three additional filesystem search utilities:

- `grep`
- `find`
- `ls`

The complete definition in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts) establishes these arrays and creates a validation set:

```typescript
const PRESET_NONE = [];
const PRESET_DEFAULT = ["read", "bash", "edit", "write"];
const PRESET_FULL = ["bash", "read", "edit", "write", "grep", "find", "ls"];

const BUILTIN_TOOL_NAMES = new Set(PRESET_FULL);

```

## Converting Between Presets and Tool Arrays

The module provides bidirectional translation utilities to convert between user-facing preset names and the concrete tool arrays stored in session state.

### Detecting the Active Preset with getPresetFromTools

When a session initializes with a specific allow-list, the `getPresetFromTools` function determines which preset label applies by comparing sorted tool arrays:

```typescript
function getPresetFromTools(activeTools: string[]): string {
  const active = [...activeTools].sort().join(",");
  
  if (active === [...PRESET_DEFAULT].sort().join(",")) return "default";
  if (active === [...PRESET_FULL].sort().join(",")) return "full";
  return "none";
}

```

This string comparison approach ensures that tool order does not affect preset detection. If the active tools match `PRESET_DEFAULT`, the function returns `"default"`; if they match `PRESET_FULL`, it returns `"full"`; otherwise, it defaults to `"none"`.

### Resolving Preset Names with getPresetFromName

To convert a preset selection into an actionable tool list, `getPresetFromName` performs the inverse operation:

```typescript
function getPresetFromName(preset: string): string[] {
  if (preset === "none") return [...PRESET_NONE];
  if (preset === "full") return [...PRESET_FULL];
  return [...PRESET_DEFAULT];
}

```

This function returns a copy of the appropriate constant array, ensuring that modifications to the returned list do not affect the original preset definitions.

## How Presets Are Applied Across the Codebase

The preset system integrates into the application at three critical layers: session initialization, user interface controls, and runtime security validation.

### Session Initialization in rpc-manager.ts

When creating a new agent session via `POST /api/agent/new`, the selected tool list is passed to [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts). The RPC manager stores this allow-list in the session state, determining which tools the assistant can invoke during that specific conversation.

### UI Configuration Controls

Frontend components like [`components/ToolsConfig.tsx`](https://github.com/agegr/pi-web/blob/main/components/ToolsConfig.tsx) present users with a dropdown selector that maps to the three preset strings. When a user selects a preset, the UI calls `getPresetFromName` to generate the actual `toolNames` array sent to the API.

### Runtime Validation with BUILTIN_TOOL_NAMES

At runtime, the system uses `BUILTIN_TOOL_NAMES`—a `Set` constructed from `PRESET_FULL`—to validate tool execution requests. This prevents arbitrary tool injection by verifying that any requested tool exists within the full built-in set before execution.

## Summary

- **PRESET_NONE** disables all built-in tools, returning an empty array for maximum restriction.
- **PRESET_DEFAULT** enables core file interaction tools: `read`, `bash`, `edit`, and `write`.
- **PRESET_FULL** extends the default set with search utilities: `grep`, `find`, and `ls`.
- **`getPresetFromTools`** identifies which preset label corresponds to an active tool list by comparing sorted string representations.
- **`getPresetFromName`** converts preset strings into concrete tool arrays for session configuration.
- **`BUILTIN_TOOL_NAMES`** provides runtime validation to ensure only predefined tools from `PRESET_FULL` can execute.

## Frequently Asked Questions

### What is the difference between PRESET_DEFAULT and PRESET_FULL?

**PRESET_DEFAULT** includes only the four essential tools (`read`, `bash`, `edit`, `write`) needed for basic file operations and command execution. **PRESET_FULL** adds three search utilities (`grep`, `find`, `ls`) that enable the assistant to locate files and search content across the filesystem, providing broader discovery capabilities at the cost of increased access scope.

### How does Pi Web determine which preset is currently active?

The system uses the `getPresetFromTools` function in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts), which sorts the active tool list and compares it against sorted versions of `PRESET_DEFAULT` and `PRESET_FULL`. If the sorted active list matches `PRESET_DEFAULT`, it returns `"default"`; if it matches `PRESET_FULL`, it returns `"full"`; otherwise, it returns `"none"`.

### Can custom tool presets be added beyond the three built-in options?

While the source code defines only three constants (`PRESET_NONE`, `PRESET_DEFAULT`, `PRESET_FULL`), the architecture supports custom tool arrays because `getPresetFromTools` falls back to `"none"` for any non-matching list. However, the UI components like [`ToolsConfig.tsx`](https://github.com/agegr/pi-web/blob/main/ToolsConfig.tsx) would require modification to expose additional preset options to users.

### Where is the tool preset validation enforced during runtime?

Runtime validation occurs using `BUILTIN_TOOL_NAMES`, a `Set` derived from `PRESET_FULL` defined in [`lib/tool-presets.ts`](https://github.com/agegr/pi-web/blob/main/lib/tool-presets.ts). This set contains all valid built-in tool names, and the RPC manager uses it to verify that requested tools exist within the allowed set before execution, preventing unauthorized tool invocation.