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
- Add request context with DVARA headers.
- Review endpoint boundaries in the LLM API overview.
- Integrate Python or Java.
- Plan a client move with the Migration guide.