How Session Tool Definitions Are Managed and the Filtering Mechanism in Craft Agents
All session tool definitions are centrally declared in SESSION_TOOL_DEFS within 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. This file exports the SESSION_TOOL_DEFS array, which contains every tool definition used throughout the system.
Anatomy of a Session Tool Definition
Each entry in SESSION_TOOL_DEFS follows the SessionToolDef interface. Here is the structure of a typical definition:
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 file and re-exported through 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 (lines 41-49) |
getSessionToolNames(options?) |
Returns a Set<string> of tool names, respecting the same filter as above. |
tool-defs.ts (lines 60-64) |
getSessionToolRegistry(options?) |
Builds a Map<string, SessionToolDef> for O(1) lookup, filtered the same way. |
tool-defs.ts (lines 55-57) |
getSessionBackendToolNames(options?) |
Subset of names whose executionMode === 'backend'. |
tool-defs.ts (lines 68-71) |
getSessionRegistryToolNames(options?) |
Subset of names whose executionMode === 'registry'. |
tool-defs.ts (lines 74-77) |
getSessionSafeAllowedToolNames(opts?) |
Names whose safeMode === 'allow'. Supports an optional prefix (used by the Pi SDK). |
tool-defs.ts (lines 86-95) |
getSessionSafeBlockedToolNames(opts?) |
Names whose safeMode === 'block'. Also supports a prefix. |
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 (lines 56-75) |
SessionToolFilterOptions Interface
All filtering helpers accept a SessionToolFilterOptions object that controls the filtering mechanism:
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 withexecutionMode: 'registry'that run via concrete handler functions locally.getSessionBackendToolNames()returns tools withexecutionMode: '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:
getSessionSafeAllowedToolNamesreturns tools withsafeMode: 'allow', which the Electron UI consumes to hide potentially unsafe tools from casual users.getSessionSafeBlockedToolNamesreturns tools withsafeMode: '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:
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 adds the mcp__session__ prefix and respects the developerFeedback feature flag:
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”, …
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 ensures the filtering helpers remain synchronized with the canonical list:
How the Filtering Guarantees Consistency
The filtering mechanism ensures architectural consistency across the craft-agents-oss codebase through five key principles:
-
Single Source of Truth – All tool metadata lives in
SESSION_TOOL_DEFSinpackages/session-tools-core/src/tool-defs.ts. -
Centralized Helpers – Every consumer (frontend, backend, tests) calls the same helper functions defined in the core package.
-
Feature-Flag Awareness – The Pi proxy injects the
developerFeedbackflag before converting to JSON-Schema, allowing runtime toggling without altering the core list. -
Safety Mode Enforcement – The
safeModefield ("allow" vs "block") is baked into each definition; thegetSessionSafe*helpers compute allowed/blocked sets automatically to prevent accidental exposure. -
Prefixing Support – Optional
prefixarguments let external SDKs (e.g., Pi) receive namespaced views without duplicating definitions.
Quick Reference Code Snippets
Retrieve all registry-executed tool names
import { getSessionRegistryToolNames } from '@craft-agent/session-tools-core';
const registryNames = getSessionRegistryToolNames(); // Set<string>
Build a name-to-definition map that omits experimental feedback
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
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
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_DEFSwithinpackages/session-tools-core/src/tool-defs.ts, providing a single source of truth. - Comprehensive Filtering: The filtering mechanism provides helpers like
getSessionToolDefs,getSessionSafeAllowedToolNames, andgetToolDefsAsJsonSchemato 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
prefixandincludeDeveloperFeedbackallow 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, 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →