# How Session Tool Definitions Are Managed and the Filtering Mechanism in Craft Agents

> Discover how session tool definitions are managed in <CODE>SESSION_TOOL_DEFS</CODE> and explore the filtering mechanism in Craft Agents for precise control over tool subsets by mode and flags.

- Repository: [Craft Docs/craft-agents-oss](https://github.com/lukilabs/craft-agents-oss)
- Tags: internals
- Published: 2026-04-18

---

**All session tool definitions are centrally declared in `SESSION_TOOL_DEFS` within [`packages/session-tools-core/src/tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/tool-defs.ts), and a suite of filtering helpers derive consistent subsets by execution mode, safety mode, and optional feature flags.**

The `lukilabs/craft-agents-oss` repository provides a robust architecture for managing session tool definitions and their filtering mechanism. This system ensures that all tools—whether executed locally via a registry or delegated to a backend—are defined in a single source of truth while exposing flexible filtering capabilities for different consumers. Understanding how tool definitions are managed and filtered is essential for integrating with the Claude SDK, Pi/MCP adapters, or building custom UI components.

## Core Definition File in craft-agents-oss

The canonical source of truth for all session-scoped tools resides in [`packages/session-tools-core/src/tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/tool-defs.ts). This file exports the `SESSION_TOOL_DEFS` array, which contains every tool definition used throughout the system.

[View source on GitHub](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/tool-defs.ts)

### Anatomy of a Session Tool Definition

Each entry in `SESSION_TOOL_DEFS` follows the `SessionToolDef` interface. Here is the structure of a typical definition:

```ts
export const SESSION_TOOL_DEFS: SessionToolDef[] = [
  {
    name: 'SubmitPlan',
    description: TOOL_DESCRIPTIONS.SubmitPlan,
    inputSchema: SubmitPlanSchema,
    executionMode: 'registry',   // runs via a concrete handler
    safeMode: 'allow',           // visible in “Explore/Safe” mode
    handler: handleSubmitPlan,
  },
  // … many more entries …
];

```

The key fields that define how session tool definitions are managed include:

| Field | Meaning |
|-------|---------|
| **name** | Identifier used by the LLM and UI |
| **description** | Human-readable summary shown in tool pickers |
| **inputSchema** | Zod schema that validates the tool's arguments |
| **executionMode** | `'registry'` (handled by a local function) or `'backend'` (delegated to a backend adapter) |
| **safeMode** | `'allow'` (safe for "Explore" mode) or `'block'` (blocked unless the user explicitly enables unsafe tools) |
| **handler** | Function that implements the tool (null for backend-only tools) |
| **readOnly?** | If `true`, the tool cannot modify session state |

## Filtering Helpers and Mechanism

The filtering mechanism is implemented in the same [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) file and re-exported through [`packages/session-tools-core/src/index.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/index.ts). These helpers guarantee that all parts of the system see a consistent, feature-aware view of the tools.

### Available Filtering Functions

The following table lists the core filtering helpers that manage how tool definitions are exposed to consumers:

| Helper | Purpose | Source Location |
|--------|---------|-----------------|
| `getSessionToolDefs(options?)` | Returns the full definitions, optionally excluding the experimental `send_developer_feedback` tool. | [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) (lines 41-49) |
| `getSessionToolNames(options?)` | Returns a `Set<string>` of tool names, respecting the same filter as above. | [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) (lines 60-64) |
| `getSessionToolRegistry(options?)` | Builds a `Map<string, SessionToolDef>` for O(1) lookup, filtered the same way. | [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) (lines 55-57) |
| `getSessionBackendToolNames(options?)` | Subset of names whose `executionMode === 'backend'`. | [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) (lines 68-71) |
| `getSessionRegistryToolNames(options?)` | Subset of names whose `executionMode === 'registry'`. | [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) (lines 74-77) |
| `getSessionSafeAllowedToolNames(opts?)` | Names whose `safeMode === 'allow'`. Supports an optional prefix (used by the Pi SDK). | [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) (lines 86-95) |
| `getSessionSafeBlockedToolNames(opts?)` | Names whose `safeMode === 'block'`. Also supports a prefix. | [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) (lines 98-107) |
| `getToolDefsAsJsonSchema({prefix?, includeDeveloperFeedback?})` | Converts the filtered definitions to JSON-Schema for MCP/PI consumption, applying a name prefix and optionally omitting experimental tools. | [`tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/tool-defs.ts) (lines 56-75) |

### SessionToolFilterOptions Interface

All filtering helpers accept a `SessionToolFilterOptions` object that controls the filtering mechanism:

```ts
export interface SessionToolFilterOptions {
  /** Include the experimental send_developer_feedback tool. */
  includeDeveloperFeedback?: boolean;
}

```

When `includeDeveloperFeedback` is omitted, it defaults to `true`, meaning experimental tools are included unless explicitly filtered out.

### Filtering by Execution Mode

The filtering mechanism distinguishes between two execution modes:

- **`getSessionRegistryToolNames()`** returns tools with `executionMode: 'registry'` that run via concrete handler functions locally.
- **`getSessionBackendToolNames()`** returns tools with `executionMode: 'backend'` that delegate execution to a backend adapter.

This separation allows the system to route tool calls appropriately based on where the logic executes.

### Filtering by Safety Mode

Safety filtering is critical for the "Explore" mode UI. The mechanism provides:

- **`getSessionSafeAllowedToolNames`** returns tools with `safeMode: 'allow'`, which the Electron UI consumes to hide potentially unsafe tools from casual users.
- **`getSessionSafeBlockedToolNames`** returns tools with `safeMode: 'block'`, requiring explicit user consent to be enabled.

Both functions support an optional `prefix` parameter, which the Pi SDK proxy utilizes to add the `mcp__session__` namespace to all tool names.

## Practical Usage Examples

The filtering mechanism is consumed by multiple components in the `lukilabs/craft-agents-oss` repository.

### Excluding Experimental Tools

To retrieve definitions without the experimental feedback tool:

```ts
import { getSessionToolDefs } from '@craft-agent/session-tools-core';

const safeDefs = getSessionToolDefs({ includeDeveloperFeedback: false });
// safeDefs will contain every tool except “send_developer_feedback”.

```

### Pi SDK Integration

The Pi SDK proxy in [`packages/shared/src/agent/backend/pi/session-tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/shared/src/agent/backend/pi/session-tool-defs.ts) adds the `mcp__session__` prefix and respects the `developerFeedback` feature flag:

```ts
import { getSessionSafeAllowedToolNames } from '@craft-agent/session-tools-core';

const prefixed = getSessionSafeAllowedToolNames({ prefix: 'mcp__session__' });
// Returns names like “mcp__session__call_llm”, “mcp__session__script_sandbox”, …

```

[View source on GitHub](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/shared/src/agent/backend/pi/session-tool-defs.ts)

### UI Component Consumption

The tool picker in the Electron renderer queries `getSessionSafeAllowedToolNames` to display only the tools safe for casual users, ensuring that blocked tools remain hidden unless the user explicitly enables unsafe mode.

### Testing Validation

The test suite in [`packages/session-tools-core/src/tool-defs-filtering.test.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/tool-defs-filtering.test.ts) ensures the filtering helpers remain synchronized with the canonical list:

[View source on GitHub](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/tool-defs-filtering.test.ts)

## How the Filtering Guarantees Consistency

The filtering mechanism ensures architectural consistency across the `craft-agents-oss` codebase through five key principles:

1. **Single Source of Truth** – All tool metadata lives in `SESSION_TOOL_DEFS` in [`packages/session-tools-core/src/tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/tool-defs.ts).

2. **Centralized Helpers** – Every consumer (frontend, backend, tests) calls the same helper functions defined in the core package.

3. **Feature-Flag Awareness** – The Pi proxy injects the `developerFeedback` flag before converting to JSON-Schema, allowing runtime toggling without altering the core list.

4. **Safety Mode Enforcement** – The `safeMode` field ("allow" vs "block") is baked into each definition; the `getSessionSafe*` helpers compute allowed/blocked sets automatically to prevent accidental exposure.

5. **Prefixing Support** – Optional `prefix` arguments let external SDKs (e.g., Pi) receive namespaced views without duplicating definitions.

## Quick Reference Code Snippets

### Retrieve all registry-executed tool names

```ts
import { getSessionRegistryToolNames } from '@craft-agent/session-tools-core';

const registryNames = getSessionRegistryToolNames(); // Set<string>

```

### Build a name-to-definition map that omits experimental feedback

```ts
import { getSessionToolRegistry } from '@craft-agent/session-tools-core';

const toolMap = getSessionToolRegistry({ includeDeveloperFeedback: false });

```

### Convert the allowed-tool list to JSON-Schema for MCP, with a prefix

```ts
import { getToolDefsAsJsonSchema } from '@craft-agent/session-tools-core';

const jsonDefs = getToolDefsAsJsonSchema({
  prefix: 'mcp__session__',
  includeDeveloperFeedback: false,
});

```

### Determine whether a tool is safe in "Explore" mode

```ts
import { SESSION_SAFE_ALLOWED_TOOL_NAMES } from '@craft-agent/session-tools-core';

function isSafe(toolName: string): boolean {
  return SESSION_SAFE_ALLOWED_TOOL_NAMES.has(toolName);
}

```

## Summary

- **Centralized Definitions**: All session tools are defined in `SESSION_TOOL_DEFS` within [`packages/session-tools-core/src/tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/tool-defs.ts), providing a single source of truth.
- **Comprehensive Filtering**: The filtering mechanism provides helpers like `getSessionToolDefs`, `getSessionSafeAllowedToolNames`, and `getToolDefsAsJsonSchema` to derive subsets by execution mode, safety level, and feature flags.
- **Cross-Platform Consistency**: Consumers ranging from the Pi SDK proxy to the Electron UI rely on the same filtering helpers, ensuring consistent tool visibility across different integration points.
- **Runtime Flexibility**: Optional parameters like `prefix` and `includeDeveloperFeedback` allow external SDKs and feature flags to customize the tool list without modifying the canonical definitions.

## Frequently Asked Questions

### How does the filtering mechanism handle experimental tools?

The filtering mechanism provides the `includeDeveloperFeedback` option in `SessionToolFilterOptions`. When set to `false`, helpers like `getSessionToolDefs` and `getToolDefsAsJsonSchema` exclude the experimental `send_developer_feedback` tool. This defaults to `true`, meaning experimental tools are included unless explicitly filtered out.

### What is the difference between registry and backend execution modes?

According to the source code in [`packages/session-tools-core/src/tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/session-tools-core/src/tool-defs.ts), the `executionMode` field distinguishes between `'registry'` tools that run via concrete handler functions locally, and `'backend'` tools that delegate execution to a backend adapter. The `getSessionRegistryToolNames` and `getSessionBackendToolNames` helpers filter based on this distinction.

### How does the safe mode filtering protect users in "Explore" mode?

The `safeMode` field in each tool definition is set to either `'allow'` or `'block'`. The filtering mechanism uses `getSessionSafeAllowedToolNames` to return tools with `safeMode: 'allow'`, which the Electron UI consumes to hide potentially unsafe tools from casual users. Tools marked as `'block'` require explicit user consent to be enabled.

### Can external SDKs customize the tool names without modifying core definitions?

Yes. The filtering helpers accept an optional `prefix` parameter, which the Pi SDK proxy utilizes in [`packages/shared/src/agent/backend/pi/session-tool-defs.ts`](https://github.com/lukilabs/craft-agents-oss/blob/main/packages/shared/src/agent/backend/pi/session-tool-defs.ts) to add the `mcp__session__` namespace to all tool names. This allows external consumers like the Pi/MCP integration to receive properly namespaced tool definitions while the canonical list in `SESSION_TOOL_DEFS` remains unchanged.