Chuyển đến nội dung chính

第 6 課:工具註冊 — 註冊與執行工具

建立工具註冊表:註冊工具、驗證、沙盒執行。 ToolHandler 介面、參數模式、逾時和錯誤處理。安全性:沙盒與可信任執行。

🧠 人工智慧與機器學習 — 第 5 課 第 6 課:工具註冊 — 註冊與執行 工具

從零開始搭建AI代理平台-與xClaw實戰

第 2 部分:LLM 引擎和代理核心

亞洲開發網

簡介

人工智慧代理需要與外界互動的工具-網路搜尋、資料庫查詢、程式碼執行。工具註冊表管理所有工具的生命週期:註冊、驗證、執行和安全。


1.ToolHandler介面

// packages/core/src/tools/types.ts
export type ToolHandler = (
  args: Record<string, unknown>,
  context: ToolContext,
) => Promise<unknown>;

export interface ToolContext {
  tenantId: string;
  userId: string;
  sessionId: string;
  abortSignal?: AbortSignal;
}

工具處理程序是接收參數+上下文並傳回任何結果的函數。


2. 工具註冊表實現

// packages/core/src/tools/tool-registry.ts
export class ToolRegistry {
  private tools = new Map<string, {
    definition: ToolDefinition;
    handler: ToolHandler;
  }>();

  register(definition: ToolDefinition, handler: ToolHandler) {
    if (this.tools.has(definition.name)) {
      throw new Error(`Tool "${definition.name}" already registered`);
    }
    this.tools.set(definition.name, { definition, handler });
  }

  unregister(name: string) {
    this.tools.delete(name);
  }

  getDefinitions(): ToolDefinition[] {
    return Array.from(this.tools.values()).map(t => t.definition);
  }

  async execute(
    name: string,
    args: Record<string, unknown>,
    context: ToolContext,
  ): Promise<ToolResult> {
    const tool = this.tools.get(name);
    if (!tool) {
      return {
        toolCallId: '',
        success: false,
        result: null,
        error: `Unknown tool: ${name}`,
        duration: 0,
      };
    }

    const start = performance.now();
    try {
      const result = await tool.handler(args, context);
      return {
        toolCallId: '',
        success: true,
        result,
        duration: performance.now() - start,
      };
    } catch (error) {
      return {
        toolCallId: '',
        success: false,
        result: null,
        error: error instanceof Error ? error.message : String(error),
        duration: performance.now() - start,
      };
    }
  }

  // Execute all tool calls from LLM response
  async executeAll(
    toolCalls: ToolCall[],
    context: ToolContext,
  ): Promise<ToolResult[]> {
    return Promise.all(
      toolCalls.map(async (call) => {
        const result = await this.execute(call.name, call.arguments, context);
        return { ...result, toolCallId: call.id };
      }),
    );
  }
}

3.內建工具

// packages/core/src/tools/builtin/web-search.ts
export const webSearchTool: ToolDefinition = {
  name: 'web_search',
  description: 'Search the web for current information',
  parameters: {
    type: 'object',
    properties: {
      query: { type: 'string', description: 'Search query' },
      maxResults: { type: 'number', description: 'Max results (1-10)' },
    },
    required: ['query'],
  },
};

export const webSearchHandler: ToolHandler = async (args) => {
  const { query, maxResults = 5 } = args as { query: string; maxResults?: number };

  const results = await fetch(`https://api.search.example/search?q=${encodeURIComponent(query)}&limit=${maxResults}`);
  return results.json();
};
// packages/core/src/tools/builtin/code-interpreter.ts
export const codeInterpreterTool: ToolDefinition = {
  name: 'execute_code',
  description: 'Execute JavaScript/TypeScript code in a sandbox',
  parameters: {
    type: 'object',
    properties: {
      code: { type: 'string', description: 'Code to execute' },
      language: { type: 'string', enum: ['javascript', 'typescript', 'python'] },
    },
    required: ['code'],
  },
  sandbox: { required: true },
};

4. 沙盒執行

// packages/core/src/tools/sandbox.ts
import { runInNewContext } from 'node:vm';

export interface SandboxToolExecutor {
  execute(code: string): Promise<unknown>;
}

export class VMSandbox implements SandboxToolExecutor {
  async execute(code: string): Promise<unknown> {
    const context = {
      console: { log: (...args: unknown[]) => args },
      Math,
      JSON,
      Date,
      // NO access to: fs, process, require, import, fetch
    };

    return runInNewContext(code, context, {
      timeout: 5000,          // 5s max
      displayErrors: true,
    });
  }
}

安全原理: 工具標記 sandbox: { required: true } 僅在虛擬機器沙箱中運作 - 無法存取檔案系統、網路或進程。


5. 總結

  • ToolHandler — 簡單的功能介面: (args, context) => Promise<result>
  • ToolRegistry — 用於註冊/取消註冊/執行的註冊表模式
  • 並行執行 — executeAll() 並行運行工具
  • 沙箱 — 針對不可信程式碼的基於虛擬機器的隔離

下一篇: 建築代理類-平台的協調中心。