Skip to main content
Version: 1.8.0

Use DVARA from Java

Point an OpenAI-compatible Java client at DVARA when your service 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 source control:

export OPENAI_BASE_URL="http://localhost:8080/v1"
export OPENAI_API_KEY="<your-dvara-api-key>"

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 complete map.

Add the official OpenAI Java client:

<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>4.68.0</version>
</dependency>

The client reads OPENAI_BASE_URL and OPENAI_API_KEY. A raw response keeps DVARA's trace header alongside the parsed Chat Completions body:

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.core.http.HttpResponseFor;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

OpenAIClient client = OpenAIOkHttpClient.fromEnv();

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model("gpt-4o")
.addSystemMessage("Answer in one sentence.")
.addUserMessage("Why should an API key be rotated?")
.maxTokens(80L)
.build();

HttpResponseFor<ChatCompletion> raw = client.chat().completions()
.withRawResponse()
.create(params);
ChatCompletion completion = raw.parse();

System.out.println(completion.choices().get(0).message().content().orElse(""));
System.out.println("DVARA trace: "
+ raw.headers().values("x-trace-id").stream().findFirst().orElse("missing"));

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​

import com.openai.core.http.StreamResponse;
import com.openai.models.chat.completions.ChatCompletionChunk;

ChatCompletionCreateParams streamParams = ChatCompletionCreateParams.builder()
.model("gpt-4o")
.addUserMessage("Write a two-line release note about key rotation.")
.maxTokens(80L)
.build();

try (StreamResponse<ChatCompletionChunk> stream =
client.chat().completions().createStreaming(streamParams)) {
stream.stream()
.flatMap(chunk -> chunk.choices().stream())
.flatMap(choice -> choice.delta().content().stream())
.forEach(System.out::print);
}
System.out.println();

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.

import com.openai.models.responses.Response;
import com.openai.models.responses.ResponseCreateParams;

ResponseCreateParams responseParams = ResponseCreateParams.builder()
.model("gpt-4o")
.instructions("Answer in one sentence.")
.input("Name one practical reason to keep an AI audit trail.")
.build();

Response response = client.responses().create(responseParams);
response.output().stream()
.flatMap(item -> item.message().stream())
.flatMap(message -> message.content().stream())
.flatMap(content -> content.outputText().stream())
.forEach(text -> System.out.println(text.text()));

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.

Call Anthropic, Bedrock, or Gemini models​

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

for (String model : List.of(
"<anthropic-model>", "<bedrock-model>", "<gemini-model>")) {
ChatCompletion result = client.chat().completions().create(
ChatCompletionCreateParams.builder()
.model(model)
.addUserMessage("Reply with the provider name.")
.maxTokens(30L)
.build());
System.out.println(model + ": "
+ result.choices().get(0).message().content().orElse(""));
}

Replace each placeholder with an identifier returned by your deployment. Native Anthropic Messages, Bedrock Converse, and Google GenAI SDK request shapes are not DVARA endpoints.

Connect LangChain4j​

Use LangChain4j's OpenAI-compatible model and the full DVARA /v1 base URL:

<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>1.20.0</version>
</dependency>
import dev.langchain4j.model.openai.OpenAiChatModel;

OpenAiChatModel model = OpenAiChatModel.builder()
.baseUrl(System.getenv("OPENAI_BASE_URL"))
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o")
.build();

String answer = model.chat("Give one reason to retain model-call evidence.");
System.out.println(answer);

LangChain4j agents use Chat Completions function calling through this model. The agent process executes each selected tool, so enforce tool authorization there as well as any configured DVARA governance.

Connect Spring AI​

Use Spring AI's current OpenAI model starter. Manage its version through the Spring AI BOM used by your application:

<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>

Spring AI appends /v1/chat/completions to base-url. Set the DVARA origin, not the /v1 client base used by the official OpenAI SDK:

spring:
ai:
openai:
base-url: http://localhost:8080
api-key: ${DVARA_API_KEY}
chat:
options:
model: gpt-4o
temperature: 0

Call it through ChatClient:

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

@Service
public class GovernedChatService {
private final ChatClient chatClient;

public GovernedChatService(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

public String answer(String question) {
return chatClient.prompt().user(question).call().content();
}

public Flux<String> stream(String question) {
return chatClient.prompt().user(question).stream().content();
}
}

Spring AI retries independently of DVARA. Its OpenAI client currently defaults to three retries. Set spring.ai.openai.max-retries deliberately so one application action does not create more provider attempts than your reliability and cost policy allows.

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. Use the official SDK's client.embeddings() service or the corresponding framework model with the same DVARA base URL and key.

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

Handle a refusal​

DVARA uses one error envelope for authentication, policy, budget, provider, and validation failures. The official Java client raises OpenAIServiceException for a non-success response:

import com.openai.errors.OpenAIServiceException;

try {
ChatCompletion result = client.chat().completions().create(params);
System.out.println(result.choices().get(0).message().content().orElse(""));
} catch (OpenAIServiceException exception) {
System.err.println("DVARA refused the request: HTTP " + exception.statusCode());
System.err.println(exception.body());
}

Parse the returned DVARA error envelope in your service's normal HTTP error layer and retain its trace_id. For example, a valid key scoped only to models:read receives HTTP 403, type: "permission_error", and code: "api_key_scope". See Error handling for the complete contract.

Continue the integration​