JavaScript and TypeScript
The OpenAI and Anthropic Node SDKs, LangChain.js and the Vercel AI SDK pointed at the gateway, with streaming and refusal handling.
The examples are ES modules (top-level await): save them as .mjs or .ts and run with Node 20 or later. Each reads VULNETIX_API_KEY and VULNETIX_ORG_ID.
vulnetix ai-firewall snippet --lang ts --sdk openai --provider openai
vulnetix ai-firewall snippet --lang ts --sdk anthropic
vulnetix ai-firewall snippet --lang ts --sdk vercel-ai --provider openai
openai-node reads OPENAI_BASE_URL, so install shell routes it without code changes. The Vercel AI SDK does not read it.
OpenAI SDK
npm install openai
import OpenAI from 'openai'
const client = new OpenAI({
baseURL: `https://guardrails.vulnetix.com/openai/${process.env.VULNETIX_ORG_ID}/v1`,
apiKey: process.env.VULNETIX_API_KEY, // the Vulnetix key, not an OpenAI key
})
const response = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: 'Hello' }],
})
console.log(response.choices[0].message.content)
Streaming:
const stream = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: 'Hello' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? '')
}
Refusals:
try {
await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: 'Hello' }],
})
} catch (err) {
if (err instanceof OpenAI.PermissionDeniedError) {
// err.error is the body's `error` object: code, blocked_by (a string), violations
const detail = err.error as { code?: string; blocked_by?: string } | undefined
console.error(`refused: ${detail?.code} (rule: ${detail?.blocked_by ?? 'n/a'})`)
}
throw err
}
Anthropic SDK
npm install @anthropic-ai/sdk
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({
baseURL: `https://guardrails.vulnetix.com/anthropic/${process.env.VULNETIX_ORG_ID}`, // no /v1
authToken: process.env.VULNETIX_API_KEY,
})
const message = await client.messages.create({
model: 'claude-sonnet-4-5',
max_tokens: 1024,
messages: [{ role: 'user', content: 'Hello' }],
})
console.log(message.content)
authToken sends Authorization: Bearer and apiKey sends x-api-key; the gateway accepts either. Stream with client.messages.stream({...}).on('text', t => process.stdout.write(t)). Refusals throw Anthropic.PermissionDeniedError.
Vercel AI SDK
npm install ai @ai-sdk/openai
import { createOpenAI } from '@ai-sdk/openai'
import { generateText, streamText, APICallError } from 'ai'
const vulnetix = createOpenAI({
baseURL: `https://guardrails.vulnetix.com/openai/${process.env.VULNETIX_ORG_ID}/v1`,
apiKey: process.env.VULNETIX_API_KEY!,
})
try {
const { text } = await generateText({ model: vulnetix('gpt-4o-mini'), prompt: 'Hello' })
console.log(text)
} catch (err) {
if (APICallError.isInstance(err) && err.statusCode === 403) {
const body = JSON.parse(err.responseBody ?? '{}')
console.error(`refused: ${body.error?.code} (rule: ${body.error?.blocked_by ?? 'n/a'})`)
}
throw err
}
const result = streamText({ model: vulnetix('gpt-4o-mini'), prompt: 'Hello' })
for await (const delta of result.textStream) process.stdout.write(delta)
Recent versions of @ai-sdk/openai call the Responses API by default. That works against openai, which serves responses. For any other provider use vulnetix.chat('model') so the request goes to /v1/chat/completions.
LangChain.js
npm install @langchain/openai
import { ChatOpenAI } from '@langchain/openai'
const llm = new ChatOpenAI({
apiKey: process.env.VULNETIX_API_KEY,
model: 'gpt-4o-mini',
configuration: {
baseURL: `https://guardrails.vulnetix.com/openai/${process.env.VULNETIX_ORG_ID}/v1`,
},
})
console.log((await llm.invoke('Hello')).content)
Error codes: see Python, Codes to handle and Errors.