Skip to main content
Version: 1.8.0

Use DVARA from JavaScript and TypeScript

Point an OpenAI-compatible JavaScript client at DVARA when your application needs policy, PII controls, audit evidence, and cost attribution around model calls. The client API stays familiar; DVARA governs each request before it reaches a configured provider.

Send your first governed request​

You need a running DVARA deployment, a registered provider that serves the model in your request, and a workspace API key. Follow the Quickstart if you do not have them yet.

Set the connection outside your source code:

export DVARA_BASE_URL="http://localhost:8080/v1"
export DVARA_API_KEY="<your-dvara-api-key>"
npm install openai

Use a key with completions:write. A key with no scopes is unrestricted, but a key with any scopes can call only the endpoint families named by those scopes. See Authenticate data-plane calls for the full map.

The OpenAI JavaScript client can return the parsed body and the HTTP headers together, which lets you keep DVARA's trace ID:

import OpenAI from "openai";

const client = new OpenAI({
baseURL: process.env.DVARA_BASE_URL,
apiKey: process.env.DVARA_API_KEY,
});

const { data, response } = await client.chat.completions
.create({
model: "gpt-4o",
messages: [
{ role: "system", content: "Answer in one sentence." },
{ role: "user", content: "Why should an API key be rotated?" },
],
max_tokens: 80,
})
.withResponse();

console.log(data.choices[0].message.content);
console.log("DVARA trace:", response.headers.get("x-trace-id"));

Example output:

Regular rotation limits the time a leaked API key can be used.
DVARA trace: 043793a6ac754c9c9d1bc5d4f525f827

The wording and token counts vary by model. When audit storage is configured, search for the trace ID in Flightdeck or your audit output. The completed call has a GATEWAY_RESPONSE event with its model, provider, outcome, and available usage data.

The model must be served by a provider registered in your DVARA deployment. Use GET /v1/models to inspect the current provider result, then use the exact identifier your deployment exposes.

Stream a Chat Completions response​

const stream = await client.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "user",
content: "Write a two-line release note about key rotation.",
},
],
max_tokens: 80,
stream: true,
});

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

Streaming response enforcement follows the workspace's configured streaming posture. It is not the same as buffering and scanning a complete non-streaming response. See Streaming before using a stream for regulated content.

Use the Responses API​

DVARA 1.8 supports basic text and image input, instructions, metadata, structured output through text.format, and synchronous or streaming Responses API calls. The same completions:write scope covers this endpoint.

const { data, response } = await client.responses
.create({
model: "gpt-4o",
instructions: "Answer in one sentence.",
input: "Name one practical reason to keep an AI audit trail.",
})
.withResponse();

console.log(data.output_text);
console.log("DVARA trace:", response.headers.get("x-trace-id"));

The 1.8 endpoint is stateless. It refuses store: true, previous_response_id, reusable prompt objects, reasoning items, background mode, include, tools, and tool_choice with HTTP 400 and unsupported_capability. Use Chat Completions when the model must return a function call; your application or agent framework still executes the function.

Request structured JSON​

Use a JSON Schema on Chat Completions when the configured provider supports it:

const result = await client.chat.completions.create({
model: "gpt-4o",
messages: [
{
role: "user",
content: "Return two controls for protecting API keys.",
},
],
response_format: {
type: "json_schema",
json_schema: {
name: "api_key_controls",
strict: true,
schema: {
type: "object",
properties: {
controls: {
type: "array",
items: {
type: "object",
properties: {
name: { type: "string" },
reason: { type: "string" },
},
required: ["name", "reason"],
additionalProperties: false,
},
},
},
required: ["controls"],
additionalProperties: false,
},
},
},
});

console.log(JSON.parse(result.choices[0].message.content ?? "{}"));

DVARA validates the request shape and passes the schema to the selected provider. Provider support still determines whether that model can produce a strict structured response. See Structured outputs for the provider matrix and failure behavior.

Receive a function call​

Chat Completions accepts OpenAI-style function definitions. DVARA governs the model call and, when configured, scans tool-call arguments. It does not execute the JavaScript function.

const result = await client.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Multiply 42 by 17." }],
tools: [
{
type: "function",
function: {
name: "multiply",
description: "Multiply two integers.",
parameters: {
type: "object",
properties: {
a: { type: "integer" },
b: { type: "integer" },
},
required: ["a", "b"],
additionalProperties: false,
},
},
},
],
tool_choice: "auto",
});

const call = result.choices[0].message.tool_calls?.[0];
if (call?.type === "function") {
console.log(call.function.name, JSON.parse(call.function.arguments));
}

Expected shape:

multiply { a: 42, b: 17 }

Validate the arguments and authorize the action before executing a tool. A model-generated function call is a proposal, not a trusted instruction.

Create embeddings​

An embeddings call needs embeddings:write when the key has a nonempty scope list. The embedding model must be available through a configured provider.

const response = await client.embeddings.create({
model: "text-embedding-3-small",
input: [
"Rotate provider credentials every 90 days.",
"Review failed authentication events each day.",
],
});

console.log(response.data.length, "vectors");
console.log(response.data[0].embedding.length, "dimensions");

The vector dimension is controlled by the model. DVARA applies configured request-side controls and records available usage, but it does not run model-text response scans over numeric vectors.

Call Anthropic, Bedrock, or Gemini models​

DVARA exposes an OpenAI-compatible client surface. Keep using the OpenAI JavaScript client and change the model identifier to one served by your configured Anthropic, Amazon Bedrock, or Google provider:

for (const model of [
"<anthropic-model>",
"<bedrock-model>",
"<gemini-model>",
]) {
const result = await client.chat.completions.create({
model,
messages: [{ role: "user", content: "Reply with the provider name." }],
max_tokens: 30,
});
console.log(model, result.choices[0].message.content);
}

Replace each placeholder with an identifier returned by your deployment. Bedrock Converse and Google GenAI SDK request shapes are not DVARA endpoints. From 1.8.5 the Anthropic SDK can keep its own shape: DVARA serves the Anthropic Messages API at /v1/messages. Set the SDK's baseURL to the Gateway, with no /v1, and its API key to a DVARA workspace key. See Govern Claude Code, which uses the same endpoint.

Connect the AI SDK​

Use the AI SDK's OpenAI-compatible provider so the transport targets Chat Completions explicitly. This avoids assuming that DVARA implements every provider-specific OpenAI Responses feature.

npm install ai @ai-sdk/openai-compatible
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { generateText, streamText } from "ai";

const dvara = createOpenAICompatible({
name: "dvara",
baseURL: process.env.DVARA_BASE_URL!,
apiKey: process.env.DVARA_API_KEY!,
includeUsage: true,
});

const { text } = await generateText({
model: dvara("gpt-4o"),
prompt: "Give one reason to retain model-call evidence.",
});
console.log(text);

const result = streamText({
model: dvara("gpt-4o"),
prompt: "Write a two-line release note about key rotation.",
});

for await (const chunk of result.textStream) {
process.stdout.write(chunk);
}

Handle a refusal​

DVARA uses one error envelope for authentication, policy, budget, provider, and validation failures. Keep the trace_id; it connects the application failure to DVARA logs and, when configured, audit evidence.

import OpenAI from "openai";

try {
const result = await client.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Summarize this contract." }],
});
console.log(result.choices[0].message.content);
} catch (error) {
if (!(error instanceof OpenAI.APIError)) throw error;

const body = (error.error ?? {}) as {
code?: string;
message?: string;
trace_id?: string;
};
console.error(`HTTP ${error.status}: ${body.code} — ${body.message}`);
console.error("DVARA trace:", body.trace_id);
}

For example, a valid key scoped only to models:read receives HTTP 403 with type: "permission_error" and code: "api_key_scope". See Error handling for the complete status and error-code contract.

Continue the integration​