Skip to main content

Prerequisites

Install and initialize the TypeScript SDK. The example uses that client as fw.

AI SDK 6

Install the AI SDK 6 and matching OpenAI provider packages. Set OPENAI_API_KEY in your service environment for the model provider.
Use middleware to check input and generated text. From TypeScript SDK 0.10.0 the middleware classifies generated text by default. This example enforces both checks.
error.hook is user_input for a blocked prompt and llm_output for blocked generated text. Pass scanOutput: false to check input only, and scanToolCalls: true to classify generated tool-call arguments. TypeScript SDK versions before 0.10.0 leave scanOutput off by default, and their AI SDK 5 and 6 middleware does not read generated content. On those versions, pass scanOutput: false, classify response.text yourself, and stop on a blocking verdict before returning it. Direct classify() returns the verdict in every mode and does not throw:

AI SDK 7

TypeScript SDK 0.9.1 adds a separate AI SDK 7 adapter. AI SDK 7 requires Node.js 22 or later and uses its v4 middleware contract. Import the adapter explicitly; fw.asMiddleware() remains the AI SDK 5/6 path.
The qualified adapter contract uses ai@7.0.166 and its internal @ai-sdk/provider@4.0.37 contract. The public OpenAI package in the install command is @ai-sdk/openai@4.0.111; its official package metadata depends on that same internal provider contract.
The adapter checks the latest user input or tool results, generated text, and tool inputs. From TypeScript SDK 0.10.0, scanOutput is on by default, so the generated-text check applies without that option; scanToolCalls stays opt-in. Reasoning parts pass through without classification. In possible Block mode, streaming text and tool-input parts remain buffered in their original interleaved order until each completed sequence has a verdict. The buffer is bounded to 1 MiB and 10,000 parts by default; limits, aborts, classification errors, and invalid stream identities fail without releasing pending content. A byte-identical final tool call can reuse its streamed-input verdict; any changed final input is classified again before emission. Because output is checked by default, a Block-mode or mode-less stream delivers each text block after its verdict instead of token by token. Set an explicit Shadow or Warn mode, or pass scanOutput: false, to stream tokens as they are generated.

Run the input check in parallel

From TypeScript SDK 0.10.0, pass parallel: true to either middleware to start the model call while its input is classified.
The result, or the stream itself, is returned only after the input verdict arrives. A blocked input throws FirewallBlockedException, discards the generation, and cancels a stream that had already started. Output checks are unchanged. The Vercel middleware classifies inline in every mode, including Shadow, and classification errors reach the caller.

Expected result

Allowed input reaches the model, and allowed output is returned only after classification. A blocked input or output throws FirewallBlockedException. Handle it at your application boundary and return a safe response. Let API and network failures follow your error policy. See TypeScript errors.

Coverage

The middleware checks the latest user message or tool responses before each model call, and non-streamed generated text before it is returned. With AI SDK 5 and 6 streaming, output is classified after the stream has been delivered, so a block arrives as an error part following text the caller has already received. Use non-streaming generation or the AI SDK 7 adapter when blocked content must not reach the caller. Set scanToolCalls: true to classify generated tool-call arguments, and classify the arguments again before executing a tool your application runs itself. Every protected call must use the wrapped model. For models routed through Vercel AI Gateway, use the gateway guide. Vercel AI SDK documentation

Next steps

Verify your integration, then review modes and enforcement.