Vercel AI SDK
Add Checkrd policy enforcement to the Vercel AI SDK via LanguageModelV2Middleware.
Vercel AI SDK
Checkrd ships a LanguageModelV2Middleware that hooks into every generateText, streamText, generateObject, and streamObject call. The middleware policy-evaluates the call before the model runs and emits structured telemetry on completion (including streaming token counts).
Install
npm install checkrd ai @ai-sdk/openaiQuickstart
import { initAsync, getEngine, getSink } from "checkrd";
import { checkrdMiddleware } from "checkrd/ai-sdk";
import { generateText, wrapLanguageModel } from "ai";
import { openai } from "@ai-sdk/openai";
await initAsync({
agentId: "01234567-89ab-cdef-0123-456789abcdef",
apiKey: process.env.CHECKRD_API_KEY!,
});
const model = wrapLanguageModel({
model: openai("gpt-4o"),
middleware: checkrdMiddleware({
engine: getEngine(),
enforce: true,
agentId: "01234567-89ab-cdef-0123-456789abcdef",
sink: getSink(),
}),
});
const result = await generateText({
model,
prompt: "Tell me a joke",
});Where does the policy come from?
initAsync fetches your agent's currently-published DSSE-signed bundle from the control plane and installs it before resolving — your dashboard is the source of truth for what checkrdMiddleware enforces. Edit the policy in the dashboard; updates stream to the process over SSE.
Streaming
The middleware wraps the model's stream with a TransformStream that accumulates token usage as chunks flow through. The completion telemetry event fires when the stream's flush runs:
const { textStream } = await streamText({
model,
prompt: "...",
});
for await (const chunk of textStream) {
process.stdout.write(chunk);
}
// Telemetry event with input_tokens / output_tokens emits here.What gets enforced
| AI SDK call | Synthetic URL | Operation |
|---|---|---|
generateText | ai-sdk://{provider}/{modelId} | generate |
streamText | ai-sdk://{provider}/{modelId} | stream |
generateObject | ai-sdk://{provider}/{modelId} | generate |
streamObject | ai-sdk://{provider}/{modelId} | stream |
Body fields exposed for matchers: messages, prompt, mode, temperature, topP, maxTokens.
default: allow
rules:
- name: deny-gpt4-for-cheap-tier
deny:
url: "ai-sdk://openai/gpt-4**"
headers:
- name: x-tenant-tier
exact: free
- name: only-approved-models
allow:
url: "ai-sdk://**"
body:
- jsonpath: "$.model"
in: ["gpt-4o-mini", "gpt-4o"]Edge runtimes
The Vercel AI SDK runs in Edge Runtime, Cloudflare Workers, and Deno. Use initAsync (not init) so the WASM core loads via fetch + WebAssembly.compile instead of node:fs.readFileSync. The middleware itself is runtime-agnostic.
// Cloudflare Workers entry
import { initAsync, getEngine, getSink } from "checkrd";
import { checkrdMiddleware } from "checkrd/ai-sdk";
export default {
async fetch(req, env) {
await initAsync({
apiKey: env.CHECKRD_API_KEY,
agentId: "01234567-89ab-cdef-0123-456789abcdef",
});
const middleware = checkrdMiddleware({
engine: getEngine(),
enforce: true,
agentId: "01234567-89ab-cdef-0123-456789abcdef",
sink: getSink(),
});
// ... use middleware in wrapLanguageModel(...) ...
},
};Observation mode
Set enforce: false to log denies without aborting:
checkrdMiddleware({
engine: getEngine(),
enforce: false, // observation mode
agentId: "01234567-89ab-cdef-0123-456789abcdef",
sink: getSink(),
});Caveats
- The AI SDK passes streaming chunks through
flush. Token counts are only available at end-of-stream; they're not in the gate event, only the completion event. - Only the v2 middleware shape is supported. AI SDK 4.x uses
LanguageModelV2Middleware. The legacy v1 middleware shape is not supported. - Provider name detection. The middleware reads
providerfrom the model spec. Custom providers (createOpenAICompatible) report their configured name.