Interceptors
Interceptor interface and decorators for TypeScript and Python
Interceptors wrap tool execution handlers to implement cross-cutting concerns, transform input/output payloads, inject metadata, and protect against payload overflow. They execute after guards and pipes, directly surrounding the tool handler.
Core Interfaces & Types
An interceptor wraps the handler: it calls next() to run it and can change the result.
InterceptorInterface
All interceptors implement the InterceptorInterface contract:
import { ExecutionContext } from '@nitrostack/core';
export interface InterceptorInterface {
/**
* Intercepts tool execution before and after handler invocation.
*
* @param context Execution context containing auth, logger, request metadata
* @param next Invocation trigger calling the next interceptor or tool handler
* @returns Transformed or validated result
*/
intercept(
context: ExecutionContext,
next: () => Promise<unknown>
): Promise<unknown>;
}async def intercept(self, context: ExecutionContext, next_fn)from nitrostack import use_interceptors
@use_interceptors(TimingInterceptor)
async def handler(...):
...Scaffold: nitrostack-py generate interceptor Transform.
Type Definitions
Types used when you attach interceptors:
export type InterceptorConstructor = new (...args: unknown[]) => InterceptorInterface;
/**
* Union permitting either an uninstantiated class constructor
* or a pre-configured instance.
*/
export type InterceptorType = InterceptorConstructor | InterceptorInterface;Interceptor Decorators
Mark interceptor classes, and attach them to handlers.
@Interceptor()
Marks a class as an interceptor, making it discoverable and registrable within the NitroStack DI container.
import { Interceptor, InterceptorInterface, ExecutionContext } from '@nitrostack/core';
@Interceptor()
export class TimingInterceptor implements InterceptorInterface {
async intercept(context: ExecutionContext, next: () => Promise<unknown>) {
const start = Date.now();
const result = await next();
context.logger.info(`Execution took ${Date.now() - start}ms`, {
tool: context.toolName,
});
return result;
}
}@UseInterceptors()
Binds one or more interceptors to a specific tool method or entire controller class.
@UseInterceptors(...interceptors: InterceptorType[])- Method-level: Evaluated specifically for that method.
- Class-level: Applied across all tool methods declared within the class.
- Accepts: Both class constructors (
@UseInterceptors(TimingInterceptor)) and pre-configured instances (@UseInterceptors(new DataSpilloverInterceptor({ maxPayloadBytes: 20480 }))).
Data spillover
The built-in DataSpilloverInterceptor moves large tool results out of the model's context. Its options, envelope schema, storage drivers, and preview generator are on a separate page.
