Java
The official openai-java SDK builds its client from a builder, so routing through
the firewall means two builder calls — .baseUrl(...) and .apiKey(...). Your
request params, streaming, and response handling are unchanged. The provider key
stays in the vault; this JVM only carries the Vulnetix API key.
Install
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>LATEST</version>
</dependency>
implementation("com.openai:openai-java:LATEST")
Configure
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;
String org = System.getenv("VULNETIX_ORG_UUID");
OpenAIClient client = OpenAIOkHttpClient.builder()
.baseUrl("https://guardrails.vulnetix.com/openai/" + org + "/v1")
.apiKey(System.getenv("VULNETIX_API_KEY")) // Vulnetix key, not an OpenAI key
.build();
ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model(ChatModel.GPT_4O_MINI)
.addUserMessage("Hello")
.build();
ChatCompletion completion = client.chat().completions().create(params);
System.out.println(completion.choices().get(0).message().content().orElse(""));
Model names pass through verbatim, so for a non-OpenAI provider — where ChatModel
has no constant — build one from the string the provider itself uses:
.model(ChatModel.of("llama-3.3-70b-versatile")) // groq
Streaming
Unchanged. The gateway relays the provider’s SSE stream.
import com.openai.core.http.StreamResponse;
import com.openai.models.chat.completions.ChatCompletionChunk;
try (StreamResponse<ChatCompletionChunk> stream =
client.chat().completions().createStreaming(params)) {
stream.stream().forEach(chunk ->
chunk.choices().forEach(choice ->
choice.delta().content().ifPresent(System.out::print)));
}
Handling a guardrail block
A request your policy refuses never reaches the provider. It returns an
OpenAI-shaped 403, which the SDK throws as
com.openai.errors.PermissionDeniedException. Its body() carries the error
object, including the Vulnetix blocked_by field.
import com.openai.errors.PermissionDeniedException;
try {
ChatCompletion completion = client.chat().completions().create(params);
} catch (PermissionDeniedException e) { // HTTP 403
// e.statusCode() == 403
// e.body() carries: code, message, blocked_by, violations
throw new IllegalStateException("AI firewall refused this request: " + e.body(), e);
}
Switch on the code field in the body to tell your organisation refused this
apart from the provider refused this:
code | Meaning |
|---|---|
request_blocked | A content guardrail matched. blocked_by names the rule; violations lists every rule that matched. |
provider_denied | Policy does not allow this provider. |
model_denied / model_not_allowed | Policy does not allow this model. |
provider_key_missing | No provider key in the vault for this provider. |
Every SDK exception extends com.openai.errors.OpenAIServiceException, so catch
that if you want one handler for all HTTP failures and branch on statusCode().
pii_redact rule rewrites the
matched spans in your prompt to the literal [REDACTED] and forwards the request.
You get an ordinary ChatCompletion back, about redacted text.Tool / function calling
Tools are forwarded untouched: the tools you add to the params and the tool calls
you get back are the provider’s own. Guardrails inspect the request you send,
which includes the tool-result messages you add before the next call — so a tool
that returns a secret is something the firewall can still block or redact.
Gotchas
.apiKey(...)takes the Vulnetix key. A provider key here produces a401.- The client reads
OPENAI_API_KEYfrom the environment if you omit.apiKey(...). If that variable still holds a real OpenAI key on your machine, be explicit — otherwise you will authenticate to the gateway with the wrong credential. .baseUrl(...)must include the/v1suffix.- If you are on Spring AI rather than the raw SDK, configure it with properties instead — see Spring AI.