Skip to main content

Node.js Integration

Use the OpenAI Node client with the documented Verdictan Chat Completions route and a client API token.

Keep the client in a trusted server runtime. Do not expose the token in browser code. Do not infer support for an unlisted OpenAI route.

Prerequisites

  • Complete the Quickstart. Keep the gateway running.

  • Create a client API token for the application.

  • Install the client:

    npm install openai

Set the connection values in the server environment:

export VERDICTAN_GATEWAY_URL="http://127.0.0.1:41002/v1"
export VERDICTAN_REQUEST_TOKEN="vdt_..."
export VERDICTAN_MODEL="replace-with-configured-model"

Send a chat request

import OpenAI from "openai";

function requiredEnv(name: string): string {
const value = process.env[name];
if (!value) throw new Error(`${name} is required`);
return value;
}

const model = requiredEnv("VERDICTAN_MODEL");
const client = new OpenAI({
baseURL: requiredEnv("VERDICTAN_GATEWAY_URL"),
apiKey: requiredEnv("VERDICTAN_REQUEST_TOKEN"),
maxRetries: 0,
timeout: 60_000,
});

const response = await client.chat.completions.create({
model,
messages: [
{ role: "user", content: "Summarize this incident report." },
],
});

console.log(response.choices[0]?.message.content);

The gateway must expose the model name. The environment variable does not create an upstream provider target.

Stream a response

const stream = await client.chat.completions.create({
model,
messages: [{ role: "user", content: "Explain this change." }],
stream: true,
});

for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta.content ?? "");
}

Input policies run before the upstream request. Some policies use the complete output and can buffer a stream.

Validate latency with the actual policy chain. For more information, read Streaming and SSE.

Use the client in a server route

Create one server-side client. Inject the client into each handler that uses model access.

Do not serialize the token into HTML, a client bundle, or a public environment variable.

export async function summarize(input: string): Promise<string> {
const response = await client.chat.completions.create({
model,
messages: [{ role: "user", content: input }],
});

return response.choices[0]?.message.content ?? "";
}

Handle gateway decisions

try {
await summarize("Review this text.");
} catch (error) {
if (error instanceof OpenAI.APIError) {
if (error.status === 400 && error.code === "content_policy_violation") {
console.error("Blocked by policy");
} else if (error.status === 401 || error.status === 403) {
console.error("Client token rejected");
} else if (error.status === 429) {
console.error("Rate limited");
} else {
throw error;
}
} else {
throw error;
}
}

Do not automatically retry a model request. The provider can receive a call before a timeout. The call can create billable usage.

The OpenAI client retries selected failures by default. This example sets maxRetries to 0. Add retries only after you define duplicate-work and cost controls.

Send a request with native fetch

Node.js can call the same route without an SDK:

const response = await fetch(
`${requiredEnv("VERDICTAN_GATEWAY_URL")}/chat/completions`,
{
method: "POST",
headers: {
Authorization: `Bearer ${requiredEnv("VERDICTAN_REQUEST_TOKEN")}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Summarize this incident." }],
}),
signal: AbortSignal.timeout(60_000),
},
);

const body = await response.json().catch(() => null);
if (!response.ok) {
const type = body?.error?.type ?? "unknown_error";
const code = body?.error?.code ?? "no_code";
throw new Error(`Verdictan request failed: ${response.status} ${type} ${code}`);
}

console.log(body);

Do not include the complete error body in logs. It can contain provider or request details.

Verify the governed path

curl -fsS \
-H "Authorization: Bearer ${VERDICTAN_REQUEST_TOKEN}" \
"${VERDICTAN_GATEWAY_URL}/models"

verdictan events tail --since 10m --follow

While the event tail is active, send a representative request. A matching request ID shows that the gateway delivered Event evidence to the control plane.

Next steps