CommunityProgramación y desarrollogithub.com

joshi-chinmay-016/AgentProof

Mejores prácticas para implementar Guards, Interceptors, Middleware, Pipes y Exception Filters en el SDK NitroStack.

¿Qué es AgentProof?

Este skill proporciona una guía completa de las mejores prácticas para la implementación de las principales capacidades de canalización (pipeline) en el SDK NitroStack, diseñado para construir agentes de IA robustos. Cubre Guards para control de acceso, Interceptors para transformar entradas/salidas, Exception Filters para manejo de errores, Middleware para envolver la ejecución de herramientas y Pipes para la validación/transformación de argumentos. Es útil para desarrolladores que necesitan aplicar lógica transversal (logging, autorización, validación) en sus herramientas NitroStack, asegurando que sus agentes manejen correctamente autenticación, estados de error y transformaciones de datos. El skill incluye interfaces TypeScript detalladas, ejemplos prácticos con decoradores como @UseGuards, @UseInterceptors, @UseFilters, @UseMiddleware y @UsePipes, y está orientado a plataformas como Claude Code, Cursor y Codex que soportan el ecosistema NitroStack.

Compatible con~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 Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Cuándo usarlo

Usa este skill al implementar validación de solicitudes, comprobaciones de autorización, mapeo de respuestas, logging, manejo de errores o seguimiento de rendimiento en los métodos de herramientas de NitroStack.


1. Guards (Guard y @UseGuards)

Los Guards determinan si una solicitud debe ser procesada por un manejador de herramienta basándose en autenticación, autorización u otras condiciones.

Interfaz:

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

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

Ejemplo:

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

Aplica el guard usando @UseGuards(...):

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

export class AdminTools {
  @Tool({
    name: 'delete_system_logs',
    description: 'Elimina todos los registros del sistema del servidor.',
    inputSchema: z.object({}),
  })
  @UseGuards(RolesGuard)
  async deleteLogs() {
    return { success: true };
  }
}

2. Interceptors (InterceptorInterface y @UseInterceptors)

Los Interceptors pueden transformar/interceptar los argumentos de entrada o la salida mapeada de la ejecución de un método de herramienta.

Interfaz:

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

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

Ejemplo:

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(`Ejecución tomó ${duration}ms`);
    return {
      ...result,
      _meta: { durationMs: duration }
    };
  }
}

3. Exception Filters (ExceptionFilterInterface y @UseFilters)

Los Exception Filters capturan cualquier error lanzado dentro de guards, interceptors o los propios manejadores de herramientas, mapeándolos a cargas JSON amigables para el usuario.

Interfaz:

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

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

Ejemplo:

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

Aplica el filtro usando @UseFilters(...) en un método de herramienta:

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

export class LoggingTools {
  @Tool({
    name: 'generate_report',
    description: 'Genera informes de uso del sistema.',
    inputSchema: z.object({}),
  })
  @UseFilters(CustomExceptionFilter)
  async generateReport() {
    throw new Error('La generación de informes aún no está implementada.');
  }
}

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

El Middleware se ejecuta antes de que la solicitud llegue al manejador de la herramienta, y puede envolver la ejecución del manejador invocando next().

Interfaz:

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

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

Ejemplo:

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(`Entrando a herramienta: ${context.toolName}`);
    try {
      const result = await next();
      context.logger.info(`Saliendo de herramienta: ${context.toolName}`);
      return result;
    } catch (error) {
      context.logger.error(`Error en herramienta: ${error}`);
      throw error;
    }
  }
}

Aplica el middleware usando @UseMiddleware(...) en un método de herramienta:

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

export class StationTools {
  @Tool({
    name: 'fetch_logs',
    description: 'Obtiene registros de operaciones de la estación.',
    inputSchema: z.object({}),
  })
  @UseMiddleware(LoggingMiddleware)
  async fetchLogs() {
    return { status: 'operational' };
  }
}

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

Los Pipes se utilizan para transformar o validar los argumentos de entrada antes de que lleguen al método del manejador de la herramienta.

Interfaz:

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

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

Ejemplo:

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

Aplica el pipe usando @UsePipes(...) en un método de herramienta:

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

export class MessagingTools {
  @Tool({
    name: 'send_message',
    description: 'Envía un mensaje a otras estaciones.',
    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 relacionados