joshichinmay-016/AgentProof

Meilleures pratiques pour implémenter et appliquer les Guards, Intercepteurs, Middleware, Pipes et Filtres d'Exception dans le SDK NitroStack.

Qu'est-ce que AgentProof ?

Cette compétence fournit une documentation structurée et des exemples concrets pour l'implémentation des mécanismes de pipeline (Gardes, Intercepteurs, Middleware, Pipes et Filtres d'Exception) dans le SDK NitroStack. Elle est conçue pour les développeurs construisant des outils sur NitroStack, leur permettant de sécuriser les accès, transformer les entrées/sorties, journaliser les exécutions, gérer les erreurs de manière centralisée, et valider les paramètres de manière déclarative. Compatible avec le SDK @nitrostack/core, la compétence montre comment utiliser les décorateurs comme @UseGuards, @UseInterceptors, @UseFilters, @UseMiddleware et @UsePipes pour appliquer ces comportements de façon propre et réutilisable. En suivant ces modèles, les agents IA (Claude Code, Cursor, Codex) et les développeurs humains écrivent un code plus robuste, maintenable et respectueux des principes de séparation des préoccupations.

Compatible avec~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 Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Quand utiliser

Utilisez cette compétence lorsque vous implémentez la validation des requêtes, les contrôles d'autorisation, le mapping des réponses, la journalisation, la gestion des erreurs ou le suivi des performances sur les méthodes d'outils NitroStack.


1. Guards (Guard et @UseGuards)

Les Guards déterminent si une requête doit être traitée par un gestionnaire d'outil en fonction de l'authentification, de l'autorisation ou d'autres conditions.

Interface :

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

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

Exemple :

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');
  }
}

Appliquez le guard avec @UseGuards(...) :

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

export class AdminTools {
  @Tool({
    name: 'delete_system_logs',
    description: 'Supprime tous les journaux système du serveur.',
    inputSchema: z.object({}),
  })
  @UseGuards(RolesGuard)
  async deleteLogs() {
    return { success: true };
  }
}

2. Intercepteurs (InterceptorInterface et @UseInterceptors)

Les intercepteurs peuvent transformer/intercepter les arguments d'entrée ou la sortie mappée d'une exécution de méthode d'outil.

Interface :

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

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

Exemple :

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(`Exécution terminée en ${duration}ms`);
    return {
      ...result,
      _meta: { durationMs: duration }
    };
  }
}

3. Filtres d'exception (ExceptionFilterInterface et @UseFilters)

Les filtres d'exception attrapent toutes les erreurs levées dans les guards, intercepteurs ou gestionnaires d'outils eux-mêmes, et les transforment en charges utiles JSON compréhensibles par l'utilisateur.

Interface :

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

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

Exemple :

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 : 'Erreur inconnue';
    return {
      error: true,
      message,
      timestamp: new Date().toISOString()
    };
  }
}

Appliquez le filtre avec @UseFilters(...) sur une méthode d'outil :

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

export class LoggingTools {
  @Tool({
    name: 'generate_report',
    description: 'Génère des rapports d'utilisation du système.',
    inputSchema: z.object({}),
  })
  @UseFilters(CustomExceptionFilter)
  async generateReport() {
    throw new Error('La génération de rapport n'est pas encore implémentée.');
  }
}

4. Middleware (MiddlewareInterface, @Middleware et @UseMiddleware)

Le middleware s'exécute avant que la requête n'atteigne le gestionnaire d'outil, et peut encapsuler l'exécution du gestionnaire en invoquant next().

Interface :

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

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

Exemple :

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(`Entrée dans l'outil : ${context.toolName}`);
    try {
      const result = await next();
      context.logger.info(`Sortie de l'outil : ${context.toolName}`);
      return result;
    } catch (error) {
      context.logger.error(`Erreur dans l'outil : ${error}`);
      throw error;
    }
  }
}

Appliquez le middleware avec @UseMiddleware(...) sur une méthode d'outil :

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

export class StationTools {
  @Tool({
    name: 'fetch_logs',
    description: 'Récupère les journaux d'opérations de la station.',
    inputSchema: z.object({}),
  })
  @UseMiddleware(LoggingMiddleware)
  async fetchLogs() {
    return { status: 'operationnel' };
  }
}

5. Pipes (PipeInterface, @Pipe et @UsePipes)

Les pipes sont utilisés pour transformer ou valider les arguments d'entrée avant qu'ils n'atteignent la méthode du gestionnaire d'outil.

Interface :

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

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

Exemple :

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;
  }
}

Appliquez le pipe avec @UsePipes(...) sur une méthode d'outil :

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

export class MessagingTools {
  @Tool({
    name: 'send_message',
    description: 'Envoyer un message aux autres 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.

Skills associés