Skip to content

Bug: disableTools and allowedTools ignored during tool initialization in rc168 #302

@buger

Description

@buger

Summary

ProbeAgent rc168 claims to support disableTools and allowedTools options (as documented in TypeScript definitions), but these options are ignored during tool initialization. All tools are created regardless of configuration, though they are correctly filtered later in the system message and parsing logic.

Evidence from Visor Integration

When Visor passes disableTools: true and allowedTools: [] to ProbeAgent:

[2025-11-22T06:58:30.304Z] [debug] 🔧 Setting allowedTools: []
[2025-11-22T06:58:30.304Z] [debug] 🔧 Setting disableTools: true
[DEBUG] ProbeAgent Tools Initialized
[DEBUG] Available tools:
[DEBUG]   - search
[DEBUG]   - query
[DEBUG]   - extract
[DEBUG]   - delegate
[DEBUG]   - listFiles
[DEBUG]   - searchFiles
[DEBUG]   - readImage

All 7 tools are initialized despite disableTools: true being set.

Root Cause Analysis

File: src/agent/ProbeAgent.js

Lines 151-155 - Options are correctly parsed:

// disableTools is a convenience flag that overrides allowedTools to []
const effectiveAllowedTools = options.disableTools ? [] : options.allowedTools;
this.allowedTools = this._parseAllowedTools(effectiveAllowedTools);

Lines 424-434 - THE BUG: Tool initialization doesn't check allowedTools:

const configOptions = {
  sessionId: this.sessionId,
  debug: this.debug,
  defaultPath: this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd(),
  allowedFolders: this.allowedFolders,
  outline: this.outline,
  enableBash: this.enableBash,
  bashConfig: this.bashConfig
  // ❌ Missing: allowedTools and disableTools are NOT passed!
};

// Create base tools
const baseTools = createTools(configOptions);

File: src/agent/tools.js

Lines 33-53 - createTools() always creates all core tools:

export function createTools(configOptions) {
  const tools = {
    searchTool: searchTool(configOptions),
    queryTool: queryTool(configOptions),
    extractTool: extractTool(configOptions),
    delegateTool: delegateTool(configOptions)
  };
  // ❌ No check for allowedTools/disableTools before creating tools!

  // Only checks enableBash and allowEdit:
  if (configOptions.enableBash) {
    tools.bashTool = bashTool(configOptions);
  }
  if (configOptions.allowEdit) {
    tools.editTool = editTool(configOptions);
    tools.createTool = createTool(configOptions);
  }

  return tools;
}

Impact

  1. Misleading debug output - Shows tools as "available" when they're actually disabled
  2. Resource waste - Creates tool instances that will never be used
  3. Architectural inconsistency - Options are parsed but not enforced during initialization

Note: Tools ARE correctly filtered in:

  • System message generation (lines 1611-1622 in ProbeAgent.js)
  • Tool response parsing (lines 2314-2322 in ProbeAgent.js)

So the tools can't actually be used, but they're still created and logged.

Proposed Fix

Option 1: Pass allowedTools to createTools()

In ProbeAgent.js, line 424:

const configOptions = {
  sessionId: this.sessionId,
  debug: this.debug,
  defaultPath: this.allowedFolders.length > 0 ? this.allowedFolders[0] : process.cwd(),
  allowedFolders: this.allowedFolders,
  outline: this.outline,
  enableBash: this.enableBash,
  bashConfig: this.bashConfig,
  allowedTools: this.allowedTools  // ADD THIS
};

In tools.js, lines 33-53:

export function createTools(configOptions) {
  const tools = {};

  // Helper to check if a tool is allowed
  const isToolAllowed = (toolName) => {
    if (!configOptions.allowedTools) return true;
    return configOptions.allowedTools.isEnabled(toolName);
  };

  // Only create allowed tools
  if (isToolAllowed('search')) {
    tools.searchTool = searchTool(configOptions);
  }
  if (isToolAllowed('query')) {
    tools.queryTool = queryTool(configOptions);
  }
  if (isToolAllowed('extract')) {
    tools.extractTool = extractTool(configOptions);
  }
  if (isToolAllowed('delegate')) {
    tools.delegateTool = delegateTool(configOptions);
  }

  // Add bash tool if enabled AND allowed
  if (configOptions.enableBash && isToolAllowed('bash')) {
    tools.bashTool = bashTool(configOptions);
  }

  // Add edit and create tools if enabled AND allowed
  if (configOptions.allowEdit && isToolAllowed('edit')) {
    tools.editTool = editTool(configOptions);
  }
  if (configOptions.allowEdit && isToolAllowed('create')) {
    tools.createTool = createTool(configOptions);
  }

  return tools;
}

Option 2: Filter tools after creation

In ProbeAgent.js, after line 434:

const baseTools = createTools(configOptions);

// Filter tools based on allowedTools configuration
const filteredTools = {};
for (const [key, value] of Object.entries(baseTools)) {
  const toolName = key.replace('Tool', ''); // searchTool -> search
  if (this.allowedTools.isEnabled(toolName)) {
    filteredTools[key] = value;
  }
}

// Create wrapped tools with event emission
const wrappedTools = createWrappedTools(filteredTools);

Reproduction

  1. Install ProbeAgent 0.6.0-rc168
  2. Create a ProbeAgent instance with disableTools: true:
    const agent = new ProbeAgent({
      debug: true,
      disableTools: true
    });
    await agent.initialize();
  3. Observe debug output shows all tools initialized
  4. Expected: No tools should be initialized

Test Case

describe('ProbeAgent tool filtering', () => {
  it('should not initialize tools when disableTools is true', async () => {
    const agent = new ProbeAgent({
      disableTools: true
    });
    await agent.initialize();

    // toolImplementations should be empty or only contain MCP tools
    expect(agent.toolImplementations.search).toBeUndefined();
    expect(agent.toolImplementations.query).toBeUndefined();
  });

  it('should only initialize allowed tools', async () => {
    const agent = new ProbeAgent({
      allowedTools: ['search', 'query']
    });
    await agent.initialize();

    expect(agent.toolImplementations.search).toBeDefined();
    expect(agent.toolImplementations.query).toBeDefined();
    expect(agent.toolImplementations.extract).toBeUndefined();
    expect(agent.toolImplementations.delegate).toBeUndefined();
  });
});

Related Code

  • ProbeAgent.js:151-155 - Options parsing (works correctly)
  • ProbeAgent.js:243-281 - _parseAllowedTools() method (works correctly)
  • ProbeAgent.js:424-434 - Tool initialization (BUG HERE)
  • ProbeAgent.js:1611-1622 - System message filtering (works correctly)
  • ProbeAgent.js:2314-2322 - Tool parsing filtering (works correctly)
  • tools.js:33-53 - createTools() function (BUG HERE)

Additional Context

This bug was discovered while integrating ProbeAgent rc168 into Visor (https://github.com/probelabs/visor), a workflow orchestration tool. Visor added support for the new disableTools option but observed that all tools were still being initialized and logged in debug output, despite the tools being correctly filtered from the AI's system message and tool execution.

Environment

  • ProbeAgent version: 0.6.0-rc168
  • Node.js version: 14.16.0+
  • Integration: Visor workflow orchestration tool

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingexternal

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions