Decisions as a Service
Sign Up Now →Sign Up Now

Java

helixor-sdk-gen 0.1.0 supports two Java outputs: a Java 17 client generated from an OpenAPI contract, and an in-process decision client generated from a pack manifest. The OpenAPI client is independent of the native decision runtime. The embedded client documented below still needs a runtime artifact that has not shipped.

OpenAPI generation availableEmbedded generation availableJava 17Embedded runtime artifact pending

Generated OpenAPI client#

Select java in the SDK configuration to generate typed models, JAX-RS endpoint interfaces, authentication filters, validation, pagination helpers and an operation-contract resource. This target calls an HTTP API and does not depend on HelixorNativeRuntime.

package_name: example-sdk
package_version: 0.1.0
languages: [java]
base_url: https://api.example.test

Generation support does not mean a package has already been published to Maven Central. Check the API's release manifest for package availability. See the language capability matrix.

Embedded decision client#

Embedded status in 0.3.1

The generated Java sources are not published. They were in the demo repository's sdks/java, regenerated for 0.3.0, and were removed from the repository with its 0.3.1 update. Their pom.xml depends on ai.helixor:helixor-runtime:1.0.0, which provides ai.helixor.runtime.HelixorNativeRuntime. That artifact is Planned and is not published, so the client does not build today.

To call the runtime from Java now, run the decision service (helixor-pack serve, or start_server from Python) and call the HTTP API with java.net.http.HttpClient. See Services.

Coordinates#

groupId     ai.helixor
artifactId  regulatorypiiguard-decision-sdk
version     1.0.0
Java        17
depends on  ai.helixor:helixor-runtime:1.0.0   (Planned)

Packages#

PackageContents
ai.helixor.runtime.regulatorypiiguard.clientRegulatoryPiiGuardClient
ai.helixor.runtime.regulatorypiiguard.modelRecords: RegulatoryPiiGuardState, DecisionResult, NecessaryCause, Counterfactual, TrueUpReport
ai.helixor.runtime.regulatorypiiguard.playbookRegulatoryPiiGuardPlaybook, the rules compiled to Java

RegulatoryPiiGuardClient#

Implements AutoCloseable. It decides on a RegulatoryPiiGuardState of six booleans that you have already extracted; it does not scan text.

RegulatoryPiiGuardClient(Path bundlePath) throws IOException

Creates its own runtime. If bundlePath is not null, the bundle is loaded from it. The pack ID is fixed to compliance.regulatory_pii_guard.v1.

RegulatoryPiiGuardClient(HelixorNativeRuntime sharedRuntime, String packId)

Reuses an existing runtime. A null packId means compliance.regulatory_pii_guard.v1.

No builder

The client has no builder() and no nativeLibPath option. Use one of the two constructors above.

DecisionResult decide(RegulatoryPiiGuardState state)

Evaluates one state on the runtime and measures latency with System.nanoTime(). There is no action argument: the first hard rule that fires sets the action, otherwise it is "permit_clean_payload". verdict is "approve" or "refuse". Every firing rule term is a NecessaryCause that names its rule, and counterfactual.changes() has one change per cause. The client checks the runtime's answer against the pack's rules and throws IllegalStateException on a mismatch or an unknown verdict. executionMode is "embedded_bytecode", "graalvm_panama_native" or "embedded_native".

boolean auditAvailable()

true when the native runtime library, which keeps the audit ledger, is loaded.

TrueUpReport getAuditReport()

Returns the runtime's usage report. Throws AuditReportUnavailableException (an IllegalStateException) when auditAvailable() is false.

void close()

Does nothing; the runtime manages its own lifecycle.

Records#

public record RegulatoryPiiGuardState(
    boolean hasSsn, boolean hasCreditCard, boolean hasHealthRecord,
    boolean hasPhone, boolean hasIp, boolean hasEmail) implements Serializable {
    public static Builder builder();   // setters named after each field, then build()
    public String toJson();            // {"has_ssn":true,...}
}

public record DecisionResult(
    String packId, String action, String verdict, double confidence,
    String proofSha256, double latencyUs, String executionMode,
    List<NecessaryCause> necessaryCauses, Counterfactual counterfactual) {
    public boolean isApproved();       // "approve".equals(verdict)
}

public record NecessaryCause(String factor, Object observedValue,
    Double threshold, String direction, Double distanceToBoundary,
    String rule, String ruleVerdict) {}

public record Counterfactual(String remedy, String targetFactor,
    Object requiredValue, Double delta, List<CounterfactualChange> changes) {}

public record CounterfactualChange(String rule, String factor, String relation,
    Object requiredValue, Object observedValue, Double delta) {}

public record TrueUpReport(String licenseId, String tenantId, String tier,
    String enforcementMode, long totalDecisionsExecuted, long decisionsOverQuota,
    long decisionsOverRateLimit, String ledgerMerkleRoot) {}

The state record has a builder; the client does not. counterfactual is null when no rule fires.

Example#

This is how the client is meant to be used once the runtime artifact ships.

import ai.helixor.runtime.regulatorypiiguard.client.RegulatoryPiiGuardClient;
import ai.helixor.runtime.regulatorypiiguard.model.RegulatoryPiiGuardState;
import ai.helixor.runtime.regulatorypiiguard.model.DecisionResult;

// bundlePath: the bundle location defined by the runtime artifact (Planned)
try (var client = new RegulatoryPiiGuardClient(bundlePath)) {
    var state = RegulatoryPiiGuardState.builder()
        .hasSsn(true).hasCreditCard(false).hasHealthRecord(false)
        .hasEmail(true).hasPhone(false).hasIp(false)
        .build();
    DecisionResult result = client.decide(state);
    boolean mustBlock = "refuse".equalsIgnoreCase(result.verdict());
}

Changed in 0.3.0

The sources are regenerated. In 0.2.1 decide(state, action) ignored its action argument, isApproved() was false for clean payloads, every failure was reported as an SSN block, the counterfactual was mostly empty and merkleRoot() was a placeholder. Now isApproved() agrees with verdict, each rule sets its own action, and the playbook's merkleRoot() returns the SHA-256 of the pack's playbook, the manifest's raw_pack_sha256 (see Pack manifest). The runtime artifact is still not published, so the status note at the top of this page still applies.

Calling the HTTP API from Java today#

import java.net.URI;
import java.net.http.*;

var http = HttpClient.newHttpClient();
var body = "{\"text\": \"Employee note: SSN is 123-45-6789.\"}";
var req = HttpRequest.newBuilder(URI.create("http://127.0.0.1:18734/v1/evaluate"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();
var res = http.send(req, HttpResponse.BodyHandlers.ofString());
// res.body() is the DecisionResult JSON; read "action" and "remedy.clean_text"