Last updated: Aug 12, 2025, 08:12 AM UTC

Sasha LLxprt Tools Integration Guide

Generated: 2025-08-06 UTC
Purpose: Technical guide for integrating LLxprt tool execution into Sasha's architecture
Audience: Developers implementing the LLxprt-based tool system


Overview

This guide explains how to integrate LLxprt's tool execution capabilities into Sasha, enabling structured tool invocation through JSON schemas and handler scripts while maintaining our markdown documentation approach.

Architecture Overview

Integration Points

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          Sasha Chat Interface               β”‚
β”‚         (User Natural Language)             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Sasha AI Service                   β”‚
β”‚    (Intent Detection & Context)            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         LLxprt Bridge                      β”‚
β”‚    (Tool Orchestration Layer)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Tool Executor                      β”‚
β”‚    (Handler Invocation & Results)          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      Handlers & File System                β”‚
β”‚   (Shell/Python/JS Execution)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Implementation Steps

Step 1: Enhance LLxprt Bridge

Update services/llxprt-bridge.js to support tool execution:

// Add to LLxprtBridge class
class LLxprtBridge {
  // Existing streaming methods...
  
  async executeToolHandler(toolName, parameters) {
    const tool = await this.toolRegistry.getTool(toolName);
    if (!tool) {
      throw new Error(`Tool not found: ${toolName}`);
    }
    
    // Check permissions
    const permitted = await this.permissionService.checkPermission(
      toolName,
      this.currentUser,
      parameters
    );
    
    if (!permitted) {
      throw new Error(`Permission denied for tool: ${toolName}`);
    }
    
    // Log the operation start
    await this.activityLogger.logToolStart(toolName, parameters);
    
    try {
      // Execute handler based on type
      const result = await this.executeHandler(
        tool.handler,
        parameters
      );
      
      // Log success
      await this.activityLogger.logToolComplete(
        toolName,
        parameters,
        result
      );
      
      return result;
    } catch (error) {
      // Log failure
      await this.activityLogger.logToolError(
        toolName,
        parameters,
        error
      );
      throw error;
    }
  }
  
  async executeHandler(handler, parameters) {
    const { type, path } = handler;
    
    switch (type) {
      case 'shell':
        return this.executeShellHandler(path, parameters);
      case 'python':
        return this.executePythonHandler(path, parameters);
      case 'javascript':
        return this.executeJavaScriptHandler(path, parameters);
      default:
        throw new Error(`Unknown handler type: ${type}`);
    }
  }
}

Step 2: Create Tool Registry Service

// services/tool-registry.js
class ToolRegistry {
  constructor() {
    this.tools = new Map();
    this.schemasPath = 'tools/schemas';
    this.handlersPath = 'tools/handlers';
  }
  
  async initialize() {
    // Load all tool schemas
    const schemaFiles = await fs.readdir(this.schemasPath);
    
    for (const file of schemaFiles) {
      if (file.endsWith('.json')) {
        const schema = await this.loadSchema(file);
        this.registerTool(schema);
      }
    }
    
    console.log(`βœ… Loaded ${this.tools.size} tools`);
  }
  
  async loadSchema(filename) {
    const content = await fs.readFile(
      path.join(this.schemasPath, filename),
      'utf-8'
    );
    return JSON.parse(content);
  }
  
  registerTool(schema) {
    this.tools.set(schema.name, {
      ...schema,
      loaded: Date.now()
    });
  }
  
  getTool(name) {
    return this.tools.get(name);
  }
  
  listTools() {
    return Array.from(this.tools.values());
  }
}

Step 3: Implement Handler Executors

// services/handler-executor.js
const { spawn } = require('child_process');
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);

class HandlerExecutor {
  async executeShellHandler(scriptPath, parameters) {
    // Convert parameters to command line arguments
    const args = this.parametersToArgs(parameters);
    
    return new Promise((resolve, reject) => {
      const process = spawn('bash', [scriptPath, ...args]);
      let output = '';
      let error = '';
      
      process.stdout.on('data', (data) => {
        output += data.toString();
      });
      
      process.stderr.on('data', (data) => {
        error += data.toString();
      });
      
      process.on('close', (code) => {
        if (code === 0) {
          resolve({ success: true, output });
        } else {
          reject(new Error(error || `Process exited with code ${code}`));
        }
      });
    });
  }
  
  async executePythonHandler(scriptPath, parameters) {
    const args = JSON.stringify(parameters);
    const { stdout, stderr } = await exec(
      `python3 ${scriptPath} '${args}'`
    );
    
    if (stderr) {
      throw new Error(stderr);
    }
    
    return JSON.parse(stdout);
  }
  
  async executeJavaScriptHandler(scriptPath, parameters) {
    const args = JSON.stringify(parameters);
    const { stdout, stderr } = await exec(
      `node ${scriptPath} '${args}'`
    );
    
    if (stderr) {
      throw new Error(stderr);
    }
    
    return JSON.parse(stdout);
  }
  
  parametersToArgs(parameters) {
    return Object.entries(parameters).flatMap(([key, value]) => {
      return [`--${key}`, String(value)];
    });
  }
}

Tool Definition Examples

Example 1: File Reader Tool

Schema (tools/schemas/read-file.json):

{
  "name": "read_file",
  "description": "Reads and returns file content",
  "parameters": {
    "file_path": {
      "type": "string",
      "description": "Path to the file to read",
      "required": true
    },
    "encoding": {
      "type": "string",
      "description": "File encoding (default: utf-8)",
      "required": false,
      "default": "utf-8"
    }
  },
  "handler": {
    "type": "shell",
    "path": "tools/handlers/read-file.sh"
  },
  "permissions": {
    "riskLevel": "low",
    "requiresConfirmation": false,
    "category": "utility"
  }
}

Handler (tools/handlers/read-file.sh):

#!/bin/bash
FILE_PATH=""
ENCODING="utf-8"

# Parse arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --file_path)
      FILE_PATH="$2"
      shift 2
      ;;
    --encoding)
      ENCODING="$2"
      shift 2
      ;;
    *)
      shift
      ;;
  esac
done

# Validate file exists
if [ ! -f "$FILE_PATH" ]; then
  echo "{\"success\": false, \"error\": \"File not found\"}" >&2
  exit 1
fi

# Read file content
CONTENT=$(cat "$FILE_PATH" 2>/dev/null)
if [ $? -eq 0 ]; then
  # Escape JSON special characters
  CONTENT=$(echo "$CONTENT" | jq -Rs .)
  echo "{\"success\": true, \"content\": $CONTENT}"
else
  echo "{\"success\": false, \"error\": \"Failed to read file\"}" >&2
  exit 1
fi

Example 2: Document Summarizer Tool

Schema (tools/schemas/summarize-document.json):

{
  "name": "summarize_document",
  "description": "Summarizes document into bullet points",
  "parameters": {
    "file_path": {
      "type": "string",
      "description": "Document to summarize",
      "required": true
    },
    "summary_length": {
      "type": "integer",
      "description": "Number of bullet points",
      "required": false,
      "default": 5
    }
  },
  "handler": {
    "type": "python",
    "path": "tools/handlers/summarize.py"
  },
  "permissions": {
    "riskLevel": "low",
    "requiresConfirmation": true,
    "category": "enhancement"
  }
}

Handler (tools/handlers/summarize.py):

#!/usr/bin/env python3
import sys
import json

def summarize_document(params):
    file_path = params['file_path']
    summary_length = params.get('summary_length', 5)
    
    try:
        with open(file_path, 'r') as f:
            content = f.read()
        
        # AI summarization logic here
        # For now, return mock summary
        summary_points = [
            f"Key point {i+1} from the document"
            for i in range(summary_length)
        ]
        
        return {
            'success': True,
            'summary': summary_points,
            'word_count': len(content.split())
        }
    except Exception as e:
        return {
            'success': False,
            'error': str(e)
        }

if __name__ == '__main__':
    params = json.loads(sys.argv[1])
    result = summarize_document(params)
    print(json.dumps(result))

Tool Invocation Flow

1. Natural Language to Tool Detection

// In sasha-ai-service.js
async function detectToolIntent(userMessage) {
  // Use AI to detect tool intent
  const prompt = `
    Analyze this message and determine if it requires a tool:
    "${userMessage}"
    
    Available tools:
    ${toolRegistry.listTools().map(t => 
      `- ${t.name}: ${t.description}`
    ).join('\n')}
    
    Response format:
    {
      "requires_tool": true/false,
      "tool_name": "tool_name_if_applicable",
      "parameters": {}
    }
  `;
  
  const response = await llxprtBridge.streamResponse(prompt);
  return JSON.parse(response);
}

2. Tool Execution with Confirmation

async function executeToolWithConfirmation(toolName, parameters, ws) {
  const tool = toolRegistry.getTool(toolName);
  
  // Check if confirmation required
  if (tool.permissions.requiresConfirmation) {
    // Send confirmation request to client
    ws.send(JSON.stringify({
      type: 'tool_confirmation',
      tool: toolName,
      parameters,
      description: tool.description,
      riskLevel: tool.permissions.riskLevel
    }));
    
    // Wait for user confirmation
    const confirmed = await waitForConfirmation(ws);
    if (!confirmed) {
      return { cancelled: true };
    }
  }
  
  // Execute tool
  return await llxprtBridge.executeToolHandler(toolName, parameters);
}

Security Considerations

Path Validation

function validatePath(path, allowedPaths) {
  const resolved = path.resolve(path);
  return allowedPaths.some(allowed => 
    resolved.startsWith(path.resolve(allowed))
  );
}

Parameter Sanitization

function sanitizeParameters(params, schema) {
  const clean = {};
  
  for (const [key, config] of Object.entries(schema.parameters)) {
    const value = params[key];
    
    // Type validation
    if (config.type === 'string') {
      clean[key] = String(value).replace(/[;<>|&

Sasha LLxprt Tools Integration Guide

Generated: 2025-08-06 UTC
Purpose: Technical guide for integrating LLxprt tool execution into Sasha's architecture
Audience: Developers implementing the LLxprt-based tool system


Overview

This guide explains how to integrate LLxprt's tool execution capabilities into Sasha, enabling structured tool invocation through JSON schemas and handler scripts while maintaining our markdown documentation approach.

Architecture Overview

Integration Points

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          Sasha Chat Interface               β”‚
β”‚         (User Natural Language)             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Sasha AI Service                   β”‚
β”‚    (Intent Detection & Context)            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         LLxprt Bridge                      β”‚
β”‚    (Tool Orchestration Layer)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Tool Executor                      β”‚
β”‚    (Handler Invocation & Results)          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      Handlers & File System                β”‚
β”‚   (Shell/Python/JS Execution)              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Implementation Steps

Step 1: Enhance LLxprt Bridge

Update services/llxprt-bridge.js to support tool execution:

// Add to LLxprtBridge class
class LLxprtBridge {
  // Existing streaming methods...
  
  async executeToolHandler(toolName, parameters) {
    const tool = await this.toolRegistry.getTool(toolName);
    if (!tool) {
      throw new Error(`Tool not found: ${toolName}`);
    }
    
    // Check permissions
    const permitted = await this.permissionService.checkPermission(
      toolName,
      this.currentUser,
      parameters
    );
    
    if (!permitted) {
      throw new Error(`Permission denied for tool: ${toolName}`);
    }
    
    // Log the operation start
    await this.activityLogger.logToolStart(toolName, parameters);
    
    try {
      // Execute handler based on type
      const result = await this.executeHandler(
        tool.handler,
        parameters
      );
      
      // Log success
      await this.activityLogger.logToolComplete(
        toolName,
        parameters,
        result
      );
      
      return result;
    } catch (error) {
      // Log failure
      await this.activityLogger.logToolError(
        toolName,
        parameters,
        error
      );
      throw error;
    }
  }
  
  async executeHandler(handler, parameters) {
    const { type, path } = handler;
    
    switch (type) {
      case 'shell':
        return this.executeShellHandler(path, parameters);
      case 'python':
        return this.executePythonHandler(path, parameters);
      case 'javascript':
        return this.executeJavaScriptHandler(path, parameters);
      default:
        throw new Error(`Unknown handler type: ${type}`);
    }
  }
}

Step 2: Create Tool Registry Service

// services/tool-registry.js
class ToolRegistry {
  constructor() {
    this.tools = new Map();
    this.schemasPath = 'tools/schemas';
    this.handlersPath = 'tools/handlers';
  }
  
  async initialize() {
    // Load all tool schemas
    const schemaFiles = await fs.readdir(this.schemasPath);
    
    for (const file of schemaFiles) {
      if (file.endsWith('.json')) {
        const schema = await this.loadSchema(file);
        this.registerTool(schema);
      }
    }
    
    console.log(`βœ… Loaded ${this.tools.size} tools`);
  }
  
  async loadSchema(filename) {
    const content = await fs.readFile(
      path.join(this.schemasPath, filename),
      'utf-8'
    );
    return JSON.parse(content);
  }
  
  registerTool(schema) {
    this.tools.set(schema.name, {
      ...schema,
      loaded: Date.now()
    });
  }
  
  getTool(name) {
    return this.tools.get(name);
  }
  
  listTools() {
    return Array.from(this.tools.values());
  }
}

Step 3: Implement Handler Executors

// services/handler-executor.js
const { spawn } = require('child_process');
const { promisify } = require('util');
const exec = promisify(require('child_process').exec);

class HandlerExecutor {
  async executeShellHandler(scriptPath, parameters) {
    // Convert parameters to command line arguments
    const args = this.parametersToArgs(parameters);
    
    return new Promise((resolve, reject) => {
      const process = spawn('bash', [scriptPath, ...args]);
      let output = '';
      let error = '';
      
      process.stdout.on('data', (data) => {
        output += data.toString();
      });
      
      process.stderr.on('data', (data) => {
        error += data.toString();
      });
      
      process.on('close', (code) => {
        if (code === 0) {
          resolve({ success: true, output });
        } else {
          reject(new Error(error || `Process exited with code ${code}`));
        }
      });
    });
  }
  
  async executePythonHandler(scriptPath, parameters) {
    const args = JSON.stringify(parameters);
    const { stdout, stderr } = await exec(
      `python3 ${scriptPath} '${args}'`
    );
    
    if (stderr) {
      throw new Error(stderr);
    }
    
    return JSON.parse(stdout);
  }
  
  async executeJavaScriptHandler(scriptPath, parameters) {
    const args = JSON.stringify(parameters);
    const { stdout, stderr } = await exec(
      `node ${scriptPath} '${args}'`
    );
    
    if (stderr) {
      throw new Error(stderr);
    }
    
    return JSON.parse(stdout);
  }
  
  parametersToArgs(parameters) {
    return Object.entries(parameters).flatMap(([key, value]) => {
      return [`--${key}`, String(value)];
    });
  }
}

Tool Definition Examples

Example 1: File Reader Tool

Schema (tools/schemas/read-file.json):

{
  "name": "read_file",
  "description": "Reads and returns file content",
  "parameters": {
    "file_path": {
      "type": "string",
      "description": "Path to the file to read",
      "required": true
    },
    "encoding": {
      "type": "string",
      "description": "File encoding (default: utf-8)",
      "required": false,
      "default": "utf-8"
    }
  },
  "handler": {
    "type": "shell",
    "path": "tools/handlers/read-file.sh"
  },
  "permissions": {
    "riskLevel": "low",
    "requiresConfirmation": false,
    "category": "utility"
  }
}

Handler (tools/handlers/read-file.sh):

#!/bin/bash
FILE_PATH=""
ENCODING="utf-8"

# Parse arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --file_path)
      FILE_PATH="$2"
      shift 2
      ;;
    --encoding)
      ENCODING="$2"
      shift 2
      ;;
    *)
      shift
      ;;
  esac
done

# Validate file exists
if [ ! -f "$FILE_PATH" ]; then
  echo "{\"success\": false, \"error\": \"File not found\"}" >&2
  exit 1
fi

# Read file content
CONTENT=$(cat "$FILE_PATH" 2>/dev/null)
if [ $? -eq 0 ]; then
  # Escape JSON special characters
  CONTENT=$(echo "$CONTENT" | jq -Rs .)
  echo "{\"success\": true, \"content\": $CONTENT}"
else
  echo "{\"success\": false, \"error\": \"Failed to read file\"}" >&2
  exit 1
fi

Example 2: Document Summarizer Tool

Schema (tools/schemas/summarize-document.json):

{
  "name": "summarize_document",
  "description": "Summarizes document into bullet points",
  "parameters": {
    "file_path": {
      "type": "string",
      "description": "Document to summarize",
      "required": true
    },
    "summary_length": {
      "type": "integer",
      "description": "Number of bullet points",
      "required": false,
      "default": 5
    }
  },
  "handler": {
    "type": "python",
    "path": "tools/handlers/summarize.py"
  },
  "permissions": {
    "riskLevel": "low",
    "requiresConfirmation": true,
    "category": "enhancement"
  }
}

Handler (tools/handlers/summarize.py):

#!/usr/bin/env python3
import sys
import json

def summarize_document(params):
    file_path = params['file_path']
    summary_length = params.get('summary_length', 5)
    
    try:
        with open(file_path, 'r') as f:
            content = f.read()
        
        # AI summarization logic here
        # For now, return mock summary
        summary_points = [
            f"Key point {i+1} from the document"
            for i in range(summary_length)
        ]
        
        return {
            'success': True,
            'summary': summary_points,
            'word_count': len(content.split())
        }
    except Exception as e:
        return {
            'success': False,
            'error': str(e)
        }

if __name__ == '__main__':
    params = json.loads(sys.argv[1])
    result = summarize_document(params)
    print(json.dumps(result))

Tool Invocation Flow

1. Natural Language to Tool Detection

// In sasha-ai-service.js
async function detectToolIntent(userMessage) {
  // Use AI to detect tool intent
  const prompt = `
    Analyze this message and determine if it requires a tool:
    "${userMessage}"
    
    Available tools:
    ${toolRegistry.listTools().map(t => 
      `- ${t.name}: ${t.description}`
    ).join('\n')}
    
    Response format:
    {
      "requires_tool": true/false,
      "tool_name": "tool_name_if_applicable",
      "parameters": {}
    }
  `;
  
  const response = await llxprtBridge.streamResponse(prompt);
  return JSON.parse(response);
}

2. Tool Execution with Confirmation

async function executeToolWithConfirmation(toolName, parameters, ws) {
  const tool = toolRegistry.getTool(toolName);
  
  // Check if confirmation required
  if (tool.permissions.requiresConfirmation) {
    // Send confirmation request to client
    ws.send(JSON.stringify({
      type: 'tool_confirmation',
      tool: toolName,
      parameters,
      description: tool.description,
      riskLevel: tool.permissions.riskLevel
    }));
    
    // Wait for user confirmation
    const confirmed = await waitForConfirmation(ws);
    if (!confirmed) {
      return { cancelled: true };
    }
  }
  
  // Execute tool
  return await llxprtBridge.executeToolHandler(toolName, parameters);
}

Security Considerations

Path Validation

function validatePath(path, allowedPaths) {
  const resolved = path.resolve(path);
  return allowedPaths.some(allowed => 
    resolved.startsWith(path.resolve(allowed))
  );
}

Parameter Sanitization

]/g, ''); } else if (config.type === 'integer') { clean[key] = parseInt(value, 10); } else if (config.type === 'boolean') { clean[key] = Boolean(value); } // Required validation if (config.required && !clean[key]) { throw new Error(`Missing required parameter: ${key}`); } // Default values if (!clean[key] && config.default) { clean[key] = config.default; } } return clean; }

Monitoring and Logging

Activity Log Integration

class ActivityLogger {
  async logToolStart(toolName, parameters) {
    await this.log({
      timestamp: new Date().toISOString(),
      action: 'tool_started',
      tool: toolName,
      parameters: this.redactSensitive(parameters),
      user: this.currentUser,
      sessionId: this.sessionId
    });
  }
  
  async logToolComplete(toolName, parameters, result) {
    await this.log({
      timestamp: new Date().toISOString(),
      action: 'tool_completed',
      tool: toolName,
      parameters: this.redactSensitive(parameters),
      result: this.summarizeResult(result),
      user: this.currentUser,
      sessionId: this.sessionId
    });
  }
}

Testing Tools

Tool Test Framework

// test/tool-tester.js
class ToolTester {
  async testTool(toolName, testCases) {
    const tool = toolRegistry.getTool(toolName);
    const results = [];
    
    for (const testCase of testCases) {
      try {
        const result = await llxprtBridge.executeToolHandler(
          toolName,
          testCase.input
        );
        
        results.push({
          name: testCase.name,
          passed: this.validateOutput(result, testCase.expected),
          result
        });
      } catch (error) {
        results.push({
          name: testCase.name,
          passed: false,
          error: error.message
        });
      }
    }
    
    return results;
  }
}

Deployment Checklist

Before Going Live

  • All tool schemas validated against JSON schema
  • Handler scripts tested with various inputs
  • Permission configurations reviewed
  • Activity logging confirmed working
  • Error handling tested for all handlers
  • Rate limiting configured
  • Security paths validated
  • Confirmation flows tested
  • Documentation complete for all tools
  • Performance benchmarks meet requirements

Additional Resources


This guide provides the technical foundation for integrating LLxprt's structured tool execution into Sasha while maintaining our user-friendly markdown documentation approach.