Community程式設計與開發github.com

joshi-chinmay-016/AgentProof

在 NitroStack SDK 中實作與應用 Guards、Interceptors、Middleware、Pipes 和 Exception Filters 的最佳實踐。

AgentProof 是什麼?

此技能專注於 NitroStack SDK 中的進階工具方法防護機制。它詳細說明如何實作與應用 Guards(守衛)、Interceptors(攔截器)、Middleware(中介軟體)、Pipes(管道)和 Exception Filters(異常過濾器),以確保請求的安全性、正確性與可觀測性。對於使用 NitroStack 建構 AI Agent 工具的開發者而言,這些模式是必備的基礎功能,能有效處理認證、授權、日誌記錄、輸入驗證、輸出轉換以及優雅的錯誤回應。此技能支援所有 NitroStack 專案,並提供完整的 TypeScript 介面定義與實作範例。開發者可直接複製範例程式碼,並使用 @UseGuards、@UseInterceptors、@UseFilters、@UseMiddleware 和 @UsePipes 等裝飾器,將其無縫整合至任何工具方法中,從而大幅提升程式碼的模組化與可維護性。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/joshi-chinmay-016/AgentProof/tree/HEAD/agentproof/.agents/skills/middleware-pipeline

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

使用時機

在實作 NitroStack 工具方法的請求驗證、授權檢查、回應映射、日誌記錄、錯誤處理或效能追蹤時,請使用此技能。


1. Guards(守衛)(Guard 與 @UseGuards)

Guards 根據驗證、授權或其他條件,決定請求是否應由工具處理器處理。

介面:

import { Guard, ExecutionContext } from '@nitrostack/core';

export interface Guard {
  canActivate(context: ExecutionContext): boolean | Promise<boolean>;
}

範例:

import { Guard, ExecutionContext, Injectable } from '@nitrostack/core';

@Injectable()
export class RolesGuard implements Guard {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const userRoles = context.clientMetadata?.roles || [];
    return userRoles.includes('admin');
  }
}

使用 @UseGuards(...) 套用守衛:

import { Tool, UseGuards, z } from '@nitrostack/core';
import { RolesGuard } from './roles.guard.js';

export class AdminTools {
  @Tool({
    name: 'delete_system_logs',
    description: 'Delete all system logs from the server.',
    inputSchema: z.object({}),
  })
  @UseGuards(RolesGuard)
  async deleteLogs() {
    return { success: true };
  }
}

2. Interceptors(攔截器)(InterceptorInterface 與 @UseInterceptors)

Interceptors 可以轉換/攔截工具方法執行過程中的輸入引數或映射後的輸出。

介面:

import { ExecutionContext } from '@nitrostack/core';

export interface InterceptorInterface {
  intercept(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown>;
}

範例:

import { InterceptorInterface, ExecutionContext, Injectable } from '@nitrostack/core';

@Injectable()
export class TimingInterceptor implements InterceptorInterface {
  async intercept(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown> {
    const start = Date.now();
    const result = await next();
    const duration = Date.now() - start;
    context.logger.info(`Execution took ${duration}ms`);
    return {
      ...result,
      _meta: { durationMs: duration }
    };
  }
}

3. Exception Filters(異常過濾器)(ExceptionFilterInterface 與 @UseFilters)

Exception Filters 會捕捉在 guards、interceptors 或工具處理器本身中拋出的任何錯誤,並將其對應到使用者友善的 JSON 負載。

介面:

import { ExecutionContext } from '@nitrostack/core';

export interface ExceptionFilterInterface {
  catch(exception: unknown, context: ExecutionContext): unknown | Promise<unknown>;
}

範例:

import { ExceptionFilterInterface, ExecutionContext, Injectable } from '@nitrostack/core';

@Injectable()
export class CustomExceptionFilter implements ExceptionFilterInterface {
  catch(exception: unknown, context: ExecutionContext) {
    const message = exception instanceof Error ? exception.message : 'Unknown error';
    return {
      error: true,
      message,
      timestamp: new Date().toISOString()
    };
  }
}

在工具方法上使用 @UseFilters(...) 套用過濾器:

import { Tool, UseFilters, z } from '@nitrostack/core';
import { CustomExceptionFilter } from './custom-exception.filter.js';

export class LoggingTools {
  @Tool({
    name: 'generate_report',
    description: 'Generates system usage reports.',
    inputSchema: z.object({}),
  })
  @UseFilters(CustomExceptionFilter)
  async generateReport() {
    throw new Error('Report generation is not implemented yet.');
  }
}

4. Middleware(中介軟體)(MiddlewareInterface、@Middleware 與 @UseMiddleware)

Middleware 在請求到達工具處理器之前執行,並可透過呼叫 next() 包覆處理器的執行。

介面:

import { ExecutionContext } from '@nitrostack/core';

export interface MiddlewareInterface {
  use(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown>;
}

範例:

import { Middleware, MiddlewareInterface, ExecutionContext } from '@nitrostack/core';

@Middleware()
export class LoggingMiddleware implements MiddlewareInterface {
  async use(context: ExecutionContext, next: () => Promise<unknown>): Promise<unknown> {
    context.logger.info(`Entering tool: ${context.toolName}`);
    try {
      const result = await next();
      context.logger.info(`Exiting tool: ${context.toolName}`);
      return result;
    } catch (error) {
      context.logger.error(`Error in tool: ${error}`);
      throw error;
    }
  }
}

在工具方法上使用 @UseMiddleware(...) 套用中介軟體:

import { Tool, UseMiddleware, z } from '@nitrostack/core';
import { LoggingMiddleware } from './logging.middleware.js';

export class StationTools {
  @Tool({
    name: 'fetch_logs',
    description: 'Fetch station operations logs.',
    inputSchema: z.object({}),
  })
  @UseMiddleware(LoggingMiddleware)
  async fetchLogs() {
    return { status: 'operational' };
  }
}

5. Pipes(管道)(PipeInterface、@Pipe 與 @UsePipes)

Pipes 用於在輸入引數到達工具處理器方法之前對其進行轉換或驗證。

介面:

import { ArgumentMetadata } from '@nitrostack/core';

export interface PipeInterface<T = unknown, R = unknown> {
  transform(value: T, metadata: ArgumentMetadata): R | Promise<R>;
}

範例:

import { Pipe, PipeInterface, ArgumentMetadata } from '@nitrostack/core';

@Pipe()
export class TrimPipe implements PipeInterface<Record<string, unknown>, Record<string, unknown>> {
  transform(value: Record<string, unknown>, metadata: ArgumentMetadata) {
    const trimmed: Record<string, unknown> = {};
    for (const [key, val] of Object.entries(value)) {
      trimmed[key] = typeof val === 'string' ? val.trim() : val;
    }
    return trimmed;
  }
}

在工具方法上使用 @UsePipes(...) 套用管道:

import { Tool, UsePipes, z } from '@nitrostack/core';
import { TrimPipe } from './trim.pipe.js';

export class MessagingTools {
  @Tool({
    name: 'send_message',
    description: 'Send a message to other stations.',
    inputSchema: z.object({ text: z.string() }),
  })
  @UsePipes(TrimPipe)
  async sendMessage(input: { text: string }) {
    return { sentText: input.text };
  }
}

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相關技能