Skip to main content
Version: 1.13.0-dev

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 supports text and image input, instructions, metadata, structured output through text.format, your own function tools with tool_choice (from 1.9.0), 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 endpoint is stateless. It refuses store: true, previous_response_id, reusable prompt objects, background mode, built-in tools such as web search, any include other than reasoning.encrypted_content, and a service_tier other than auto or default, with HTTP 400 and unsupported_capability. When the model returns 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. The Bedrock Converse request shape is not a DVARA endpoint. From 1.9.0 the Google GenAI SDK can keep its own shape: set its base URL to <gateway>/v1/gemini and its API key to a DVARA workspace key. See Govern Gemini CLI, which uses the same endpoint. 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​