Data Spillover

DataSpilloverInterceptor options, envelope, storage drivers, and previews

DataSpilloverInterceptor

The DataSpilloverInterceptor protects client memory buffers and LLM context windows by intercepting tool outputs exceeding a configured byte size threshold, storing the full payload, and returning a concise preview envelope.

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

new DataSpilloverInterceptor(options?: DataSpilloverOptions)

Configuration Options (DataSpilloverOptions)

Options that control when results spill over and what the preview contains:

OptionTypeDefaultDescription
maxPayloadBytesnumber10240 (10KB)Byte size limit before output is offloaded to storage.
spilloverTtlSecondsnumber3600 (1 hour)Time-to-live before stored payloads are pruned.
previewItemsnumber3Maximum items included in preview arrays or object dictionaries.
previewStringCharsnumber500Maximum character length for string previews before truncation.
resourceUriPrefixstring'resource://data-spillover/'URI scheme and prefix for generated resource links.
storage'memory' | 'filesystem' | SpilloverStore'memory'Storage driver mode or custom store instance.
storagePathstring'./.spillover_cache'Directory path for filesystem driver.

Static Factory Method

Use configure() to get a class with your options baked in, for decorators that expect a class:

DataSpilloverInterceptor.configure(options: DataSpilloverOptions): InterceptorConstructor

Returns a constructor suitable for decorators requiring class types:

@Tool({ name: 'large_query' })
@UseInterceptors(DataSpilloverInterceptor.configure({ maxPayloadBytes: 15360 }))
async largeQuery(input: QueryInput, ctx: ExecutionContext) {
  return await this.service.fetchData(input);
}

Spillover Envelope & Schema

When payload size exceeds maxPayloadBytes, the tool handler returns a standardized SpilloverEnvelope:

export interface SpilloverEnvelope {
  /** Marker flag identifying a spilled payload */
  _spillover: true;

  /** URI where the complete payload can be retrieved via resources/read */
  resourceUri: string;

  /** Content MIME type (e.g., 'application/json' or 'text/plain') */
  mimeType: string;

  /** Total byte size of full dataset */
  sizeBytes: number;

  /** Total item count if payload was an array or map */
  totalItems?: number;

  /** Human-readable summary (e.g., "Query returned 1,250 items (277.8 KB)") */
  summary: string;

  /** Truncated preview sample of the dataset */
  preview: unknown;

  /** Guidance instruction for AI models explaining how to fetch full data */
  hint: string;
}

Zod Validation Schema

NitroStack exports SpilloverEnvelopeSchema for runtime validation:

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

const parsed = SpilloverEnvelopeSchema.safeParse(result);
if (parsed.success && parsed.data._spillover) {
  console.log('Payload spilled to:', parsed.data.resourceUri);
}

Spillover Storage Drivers

Spillover drivers implement the SpilloverStore interface:

export interface SpilloverRecord {
  id: string;
  data: string;
  mimeType: string;
  sizeBytes: number;
  createdAt: number;
  expiresAt: number;
  sessionId?: string;
}

export interface SpilloverStore {
  save(id: string, data: string, mimeType: string, ttlSeconds: number, sessionId?: string): Promise<SpilloverRecord>;
  get(id: string): Promise<SpilloverRecord | undefined>;
  delete(id: string): Promise<boolean>;
  cleanup(): Promise<number>;
  dispose(): Promise<void>;
  getMaxSizeBytes?(): number;
}

Available Drivers

  1. FsSpilloverStore: Persists payloads to disk in atomic temporary files. Recommended for production to prevent Node.js heap exhaustion.
    new FsSpilloverStore({
      storageDir: './.spillover_cache',
      maxSizeBytes: 100 * 1024 * 1024, // 100MB directory quota
    })
  2. MemorySpilloverStore: Stores payloads in an in-memory Map. Recommended for development, testing, and memory-contained environments.
    new MemorySpilloverStore({
      maxSizeBytes: 20 * 1024 * 1024,  // 20MB in-memory buffer
    })

Preview Generator Utility

NitroStack exports generatePreview for inspecting and formatting arbitrary data payloads:

import { generatePreview, PreviewResult } from '@nitrostack/core';

export function generatePreview(
  data: unknown,
  sizeBytes: number,
  previewItems = 3,
  previewChars = 500
): PreviewResult;

Return Shape

What the preview generator returns:

export interface PreviewResult {
  preview: unknown;
  summary: string;
  totalItems?: number;
}

Preview Behavior by Data Type

  • Arrays: Slices the first previewItems elements, truncating string values longer than previewChars. Calculates totalItems = data.length.
  • Strings: Slices first previewChars characters and appends ... [truncated].
  • Objects: Extracts up to previewItems top-level keys, formatting values safely.

On this page