Skip to content

Releases: getaxonflow/axonflow-sdk-java

Release 7.0.0

29 Apr 23:26
53c049a

Choose a tag to compare

AxonFlow Java SDK v7.0.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>7.0.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:7.0.0'

Upgrade strongly recommended. Over the past month we've shipped substantial production, quality, and security hardening across the AxonFlow SDKs and platform — upgrade to the latest major for a more secure, reliable, and bug-free experience.

Security highlights from this release cycle:

  • Webhook signing-key now exposed by SDK request type (this release). The webhookSigningKey (HMAC-SHA256) field on RegisterRequest was missing from the SDK type, so callers had no way to retrieve the signing key and webhook signature verification was effectively un-implementable. The field is now wired through end-to-end. Documented in GHSA-248h-974q-xrc2.
  • DO_NOT_TRACK opt-out removed in favor of AXONFLOW_TELEMETRY=off (this release). DO_NOT_TRACK was unreliable because host CLIs and runtimes commonly inject DO_NOT_TRACK=1 regardless of user intent; an explicit AxonFlow-scoped opt-out is the only signal we honor now. Maven Surefire and Failsafe environment blocks were tightened so local mvn test runs no longer inherit a host DO_NOT_TRACK=1 and emit accidental pings.
  • Test-harness opt-out hygiene (last cycle, v6.x). Test environments that mutate DO_NOT_TRACK no longer silently leak real pings from CI; transport is mocked at the test boundary.

Major release across the AxonFlow SDK family. Companion releases ship the same day: TypeScript v7.0.0 / Python v7.0.0 / Go v7.0.0 (with /v7 module path migration) / Java v7.0.0. The full set of platform-side security fixes shipped alongside this release is documented in the consolidated platform advisory GHSA-9h64-2846-7x7f.

Reliability and bug-fix highlights:

  • retry_context + idempotency_key for cross-step de-duplication (last cycle, v6.x). Workflow steps that retry across pod restarts no longer record duplicate audit entries; idempotency_key flows end-to-end through MAP HITL approve/reject responses.
  • mapTimeout config field — SDK parity with Go / Python / TypeScript (last cycle, v6.x). MAP plan generation has its own timeout knob distinct from the per-request timeout, so multi-LLM-call decompositions no longer cancel the wrong path under load.
  • LLMProvider source compatibility restored (last cycle, v6.x). The 7-arg primitive constructor and primitive getPriority() / getWeight() accessors are back; null-safe boxed accessors split off as getPriorityBoxed() / getWeightBoxed() for callers needing "explicitly 0 vs not set" disambiguation.

BREAKING

  • DO_NOT_TRACK is no longer honored as an AxonFlow telemetry opt-out. Use AXONFLOW_TELEMETRY=off instead. Host tools and CLIs commonly inject DO_NOT_TRACK=1 regardless of user intent, which makes it unreliable as a signal.
  • (Test API) Package-private TelemetryReporter.isEnabled and TelemetryReporter.sendPing overloads no longer accept a String doNotTrack parameter. The remaining String axonflowTelemetry parameter is the sole opt-out signal accepted by the testability surface.

Security

  • TLS verification bypass closed (CWE-295). HttpClientFactory previously honored insecureSkipVerify(true) on AxonFlowConfig as a single-flag opt-in to a permissive X509TrustManager that accepted ANY server certificate, including attacker-presented certificates in MITM scenarios. The insecure path is now double-gated: it activates only if both insecureSkipVerify(true) is set on the builder AND the AXONFLOW_INSECURE_TLS environment variable is set to true (or 1). When the builder flag is set without the env var, the SDK logs a warning and keeps the JVM's default TrustManager in place. A loud *** SECURITY WARNING *** is logged whenever the insecure path actually activates. Default behavior — and behavior in production environments without the env var — uses standard JDK + system trust-store validation. Resolves code-scanning alert #8.

Fixed

  • The DO_NOT_TRACK=1 is deprecated... logger.warn is no longer emitted on every telemetry decision when DO_NOT_TRACK=1 is set.

Changed

  • Telemetry now follows the 7-day delivered-heartbeat contract instead of firing on every new AxonFlow() construction. The SDK emits at most one anonymous heartbeat per environment every 7 days during SDK activity. A stamp file at the OS-native user cache dir tracks last successful delivery; mtime is the source of truth across process restarts. Failed POSTs do NOT advance the stamp — a transient network error does not silence telemetry for 7 days. An in-memory 1-hour cache caps Files.getLastModifiedTime calls on hot request paths; a ReentrantLock-guarded in-flight flag coalesces concurrent threads so only one ping fires under load. AXONFLOW_TELEMETRY=off is re-evaluated on every gate run. Restricted environments where no cache dir is available (e.g. AWS Lambda with no HOME/LOCALAPPDATA) fall back transparently to the previous "one ping per construction" behavior.

CI / development

  • CI workflows (ci.yml, integration.yml, release.yml, wire-shape-contract.yml, validate-version-alignment.yml) now use AXONFLOW_TELEMETRY=off to suppress telemetry during automated runs.

Release 6.2.0

28 Apr 18:54
ec69105

Choose a tag to compare

AxonFlow Java SDK v6.2.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>6.2.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:6.2.0'

Minor release. New LLM-provider listing API closes the parity gap with the Python + Go SDKs; the rest of the cycle restores LLMProvider source-compatibility for callers using the 7-arg primitive shape. Coordinated cycle: TypeScript v6.2.0 / Python v6.9.0 / Go v6.0.0 (major: see SDKCompatibility breaking type change in that release) ship same day.

Added

  • axonflow.listLLMProviders() + listLLMProviders(String type, Boolean enabled) — list configured LLM providers and their per-provider health snapshot. Calls GET /api/v1/llm-providers. New LLMProvider and LLMProviderHealth types in com.getaxonflow.sdk.types. Async variant listLLMProvidersAsync(). Closes the parity gap with the Python SDK's list_providers() and the Go SDK's ListProviders().
  • examples/basic/ — minimal smoke example exercising healthCheck(), proxyLLMCall(), and listConnectors() against a running AxonFlow agent. Uses try-with-resources so OkHttp's dispatcher + connection pool are cleaned up at exit. Run via mvn -q compile exec:java after mvn install -DskipTests at the SDK root.

Fixed

  • LLMProvider source compatibility restored. The 7-arg primitive constructor LLMProvider(name, type, enabled:bool, priority:int, weight:int, hasApiKey:bool, health) is back (delegates to the new 13-arg boxed form, marked @Deprecated so new callers move to the boxed shape). getPriority() / getWeight() return primitive int again (null-safe-unbox to 0). Boxed accessors are available as getPriorityBoxed() / getWeightBoxed() / getEnabledBoxed() / getHasApiKeyBoxed() for callers that need to distinguish "explicitly 0" from "field not present".

Release 6.1.0

25 Apr 20:44
6886caf

Choose a tag to compare

AxonFlow Java SDK v6.1.0

Installation (Maven)

<dependency>
  <groupId>com.axonflow</groupId>
  <artifactId>axonflow-java-sdk</artifactId>
  <version>6.1.0</version>
</dependency>

Minor release. Surfaces fields the AxonFlow agent has emitted since v7.1.0 (Plugin Batch 1) but the SDK didn't declare. Pure field-additions on existing methods — additive only, no breaking changes. The pre-existing constructors are preserved as source-compat overloads. Documented in OpenAPI via platform v7.4.3.

Coordinated cycle: TypeScript v6.1.0 / Python v6.8.0 / Go v5.8.0 ship same day with the same field set.

Added

  • MCPCheckInputResponse gains 5 optional Plugin Batch 1 fields:
    • decisionId: String — audit correlator
    • riskLevel: Stringlow | medium | high | critical
    • policyMatches: List<ExplainPolicy> — per-policy explainability records
    • overrideAvailable: Boolean — whether session override is permitted for the matched policies (boxed so callers can distinguish "unset" from false on older platforms)
    • overrideExistingId: String — already-active override consumed by this decision (if any)
  • MCPCheckOutputResponse gains 3 optional fields:
    • decisionId: String
    • policyMatches: List<ExplainPolicy>
    • redactedMessage: String — text-redaction counterpart to redactedData (used when the connector returned a string message rather than tabular rows; e.g. execute-style responses)

ExplainPolicy already shipped — same Jackson-annotated record now reused on the MCP response types. Pre-v7.1.0 platforms leave all new fields as null; callers should treat null as "context not available" rather than an error.

Source compatibility

Both MCPCheckInputResponse and MCPCheckOutputResponse retain their v6.0.0 constructor signatures as overloads that delegate to the new @JsonCreator constructors with null for the new fields. Existing callers that build response instances locally compile unchanged. equals() / hashCode() / toString() updated to include the new fields.

Deferred

client.explainDecision(decisionId) and the full ExplainRule / DecisionExplanation type surface are tracked separately as feature work. This release ships only field-surfacing on existing methods.

Release 6.0.0

25 Apr 14:37
7314dea

Choose a tag to compare

AxonFlow Java SDK v6.0.0

Installation (Maven)

<dependency>
  <groupId>com.axonflow</groupId>
  <artifactId>axonflow-java-sdk</artifactId>
  <version>6.0.0</version>
</dependency>

This is a major release. The bump is driven by a single observable-contract change: WebhookSubscription.equals() and .hashCode() now compare on id only, not every field. Coordinated with the TypeScript SDK v6.0.0 release (PolicyInfo rename) as a v6 alignment cycle for the SDKs that needed breaking changes; Python (v6.7.0) and Go (v5.7.0) ship as minor on the same day because their changes are purely additive.

BREAKING — WebhookSubscription equality is now identity-based on id

WebhookSubscription is an entity, not a value object. Two instances with the same id represent the same logical webhook regardless of whether one view has loaded secret (only returned by createWebhook) and another has not, or whether updatedAt / active have moved between fetches.

Previously equals() / hashCode() compared every field. That meant a webhook constructed locally with the legacy 6-arg constructor compared unequal to the same logical webhook deserialized from a server response that included secret / tenantId / orgId. Set<WebhookSubscription>, Map keying, and identity-tracking caches all broke under those semantics.

Identity-based equality is the canonical entity semantics; the prior value-based equality was a bug. Because equals() / hashCode() are part of the observable Java contract that callers depend on for set deduplication, map lookup, and identity caches, the fix is a breaking change per strict semver — even though the new behaviour corrects incorrect semantics rather than introducing them.

If you need content-equality (e.g. to detect a rotated secret), compare the relevant getters directly. The 6-arg constructor is preserved as a source-compat overload for callers building local instances; only equals() / hashCode() semantics changed. toString() is unchanged (still emits full state with secret redacted).

Added

  • Version alignment check (.github/workflows/validate-version-alignment.yml). CI now fails any PR or push to main where pom.xml's <version> drifts from the first released ## [X.Y.Z] section in CHANGELOG.md. Matches the pattern in the platform repo and the Go SDK.
  • Wire-shape contract gate (.github/workflows/wire-shape-contract.yml). CI fails any PR that introduces drift between Java @JsonProperty annotations and the OpenAPI specs pinned at tests/fixtures/wire-shape-baseline.json::openapi_specs_sha. Four gates: cross-spec schema divergence, intra-file schema duplicates, per-type SDK-vs-spec drift, and registered-type rename-escape. The pinned spec SHA is itself guarded by a spec-pin-bump PR label so a single PR can't both move the SHA and silence drift. Source-discovery walks brace depth so nested classes (e.g. WorkflowTypes.CreateWorkflowRequest) and inner enums are attributed to the correct type rather than the file's outer class. Mirrors the Python, Go, and TypeScript gates.
  • WebhookSubscription.secret — HMAC-SHA256 signing key now exposed on the response from createWebhook. Required to verify the X-AxonFlow-Signature header on inbound webhook deliveries; without it, callers can't validate payload authenticity. Also adds tenantId and orgId (ownership scoping). The 6-arg constructor is preserved as a source-compat overload that delegates to the 9-arg with nulls for the new fields. toString() redacts secret to avoid log leakage.
  • BudgetAlert.acknowledged — alert dismissal flag. Also adds @JsonProperty annotations on previously-unannotated fields (id, threshold, message) so the wire-shape gate can see them; Jackson's default name mapping was correct, but the validator's discovery walks @JsonProperty only.

Fixed

  • Telemetry pings now deliver reliably from short-lived JVMs (CLI, serverless, cold-starts). AxonFlow construction blocks briefly while the ping is sent synchronously (bounded by the telemetry timeout).
  • Telemetry path is bounded at TIMEOUT_SECONDS (3s) total; the /health probe and checkpoint POST share a single monotonic deadline instead of stacking independent timeouts.

Release 5.7.0

22 Apr 13:30
5720c3d

Choose a tag to compare

AxonFlow Java SDK v5.7.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>5.7.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:5.7.0'

Added

  • Rich ApproveStepResponse / RejectStepResponse — both classes now carry
    the same shape as the step-gate response: decision resolves to "allow" or
    "block", retryContext mirrors the gate response retry state, approvedBy
    / approvedAt / rejectedBy / rejectedAt carry reviewer identity,
    approvalId is the deterministic HITL queue UUID, policiesMatched
    reconstructs the governance trail. The legacy workflowId / stepId /
    status fields remain for back-compat.
  • planId on approve/reject responses — populated when the response comes
    from the MAP plan-scoped endpoint; empty on WCP plane responses. Same types
    work across both endpoints.
  • Back-compat 3-arg constructorsnew ApproveStepResponse(workflowId, stepId, status)
    and new RejectStepResponse(workflowId, stepId, status) still compile, so
    existing test fixtures and SDK consumers keep working without changes.
  • getPendingPlanApprovals / getPendingPlanApprovalsAsync — new client
    methods that list MAP-plane pending approvals
    (GET /api/v1/plans/approvals/pending), the counterpart of
    getPendingApprovals for the WCP plane. The two-arg form accepts an
    optional planId filter so reviewer tools can scope the listing to one
    plan. Available on Evaluation+ licenses (same tier gate as the MAP step
    approve/reject endpoints).
  • PendingApproval.planId — populated on MAP-plane entries, null on
    WCP-plane entries. Mirrors the approve/reject asymmetry. PendingApproval
    also gains stepIndex, decision, decisionReason, and approvalStatus
    so reviewer tools can render the full approval context without a second
    request. The existing 6-arg back-compat constructor still works; new
    fields default to null / 0 for callers that don't pass them.

Fixed

  • approveStep / rejectStep / getPendingApprovals endpoint URLs
    all three previously targeted non-existent paths under
    /api/v1/workflow-control/ and would fail against a real AxonFlow server.
    Corrected to the canonical /api/v1/workflows/{id}/steps/{step_id}/(approve|reject)
    and /api/v1/workflows/approvals/pending routes. Customers using these
    methods against a live deployment were receiving 404s; this release makes
    them work.
  • PendingApprovalsResponse getters and JSON field names aligned with the
    wire shape
    — the class previously declared getApprovals() / getTotal()
    over a JSON body with keys approvals / total, which never matched the
    server (pending_approvals / count). Getters renamed to
    getPendingApprovals() / getCount() with the correct JSON bindings.
    Callers that read response.getApprovals() or response.getTotal() need
    to update to the new getter names.

Deprecated

  • DO_NOT_TRACK=1 as an AxonFlow telemetry opt-out — scheduled for removal after 2026-05-05 in the next major release. Use AXONFLOW_TELEMETRY=off instead. The SDK emits a one-line migration warning when DO_NOT_TRACK=1 is the active control and AXONFLOW_TELEMETRY=off is not also set.

Unchanged

  • approveStep(workflowId, stepId) / rejectStep(workflowId, stepId, reason)
    method signatures on AxonFlow are unchanged — only the response fields grew.

Release 5.6.0

21 Apr 22:10
3dc7ae5

Choose a tag to compare

AxonFlow Java SDK v5.6.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>5.6.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:5.6.0'

Added

  • retry_context and idempotency_key support on the step gate
    StepGateResponse now carries a RetryContext object on every gate call with the
    true (workflow_id, step_id) lifecycle: gateCount, completionCount,
    priorCompletionStatus (PriorCompletionStatus enum —
    NONE / COMPLETED / GATED_NOT_COMPLETED), priorOutputAvailable,
    priorOutput, priorCompletionAt, firstAttemptAt, lastAttemptAt,
    lastDecision, and idempotencyKey. Prefer these to the legacy cached /
    decisionSource fields.
  • stepGate(workflowId, stepId, request, options) overload — new 4-arg overload
    taking StepGateOptions. Use StepGateOptions.includePriorOutput() to send
    ?include_prior_output=true so retryContext.priorOutput is populated when a prior
    /complete has landed. Existing 3-arg overload keeps its signature and delegates
    with StepGateOptions.defaults().
  • StepGateRequest.idempotencyKey — caller-supplied opaque business-level key
    (max 255 chars; validated at construction). Immutable once recorded on the first gate
    call for a (workflow, step); subsequent gate/complete calls must pass the same key.
  • MarkStepCompletedRequest.idempotencyKey — must match the key set on the
    corresponding gate call, if any. Mismatch (including missing-vs-set on either side)
    surfaces as a typed IdempotencyKeyMismatchException.
  • IdempotencyKeyMismatchException — new typed exception in
    com.getaxonflow.sdk.exceptions. Thrown by stepGate and markStepCompleted when
    the platform returns HTTP 409 with error.code == "IDEMPOTENCY_KEY_MISMATCH".
    Surfaces workflowId, stepId, expectedIdempotencyKey, receivedIdempotencyKey,
    plus inherited statusCode=409 and errorCode="IDEMPOTENCY_KEY_MISMATCH".
  • RetryContext, PriorCompletionStatus, StepGateOptions — exported in
    WorkflowTypes.

Fixed

  • 409 dispatch on step gate/complete — previously all 409 responses on
    markStepCompleted fell through to a generic AxonFlowException(..., 409, "VERSION_CONFLICT"), conflating step idempotency conflicts with plan version
    conflicts. The step gate/complete call sites now inspect the 409 body and dispatch
    to IdempotencyKeyMismatchException when error.code matches, falling back to a
    generic AxonFlowException otherwise. Plan update paths (which also use 409) are
    untouched.

Deprecated

  • StepGateResponse.isCached() and StepGateResponse.getDecisionSource()
    marked @Deprecated. Use getRetryContext().getGateCount() > 1 and
    getRetryContext().getPriorCompletionStatus() instead. Planned for removal in a
    future major version.

Compatibility

Companion to the platform change that introduces retry_context on
POST /api/v1/workflows/{workflow_id}/steps/{step_id}/gate. Additive only — existing
callers that never set idempotencyKey or pass StepGateOptions see no behavior
change. Binary-compatibility preserved: old StepGateRequest, StepGateResponse, and
MarkStepCompletedRequest constructors kept alongside new ones.

Release 5.5.0

20 Apr 22:25
ae0825e

Choose a tag to compare

AxonFlow Java SDK v5.5.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>5.5.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:5.5.0'

Added

  • mapTimeout field on AxonFlowConfig — brings Java to parity with
    the TypeScript, Python, and Go SDKs (all three already had a separate
    MAP timeout). The shared timeout (default 60s) only covered single-
    request endpoints; MAP plans routinely take 60-120s because they
    chain multiple LLM calls end-to-end, and the global timeout was
    cutting them off. New constant DEFAULT_MAP_TIMEOUT = 120s, new
    builder method AxonFlowConfig.builder().mapTimeout(Duration.ofSeconds(300)),
    and new environment variable AXONFLOW_MAP_TIMEOUT_SECONDS. All
    plan-lifecycle methods (generatePlan, executePlan, getPlanStatus,
    updatePlan, cancelPlan, resumePlan, rollbackPlan,
    getPlanVersions) now use a plan-specific OkHttpClient clone with
    callTimeout / readTimeout / writeTimeout set to mapTimeout.
    Shares connection pool + interceptors + dispatcher with the main
    client; only the timeout attributes differ. Keep mapTimeout
    server AXONFLOW_MAP_MAX_TIMEOUT_SECONDS (default 300s) ≤
    front-door ALB idle_timeout.timeout_seconds (default 300s), or the
    connection is killed mid-stream.

Release 5.4.0

18 Apr 12:21
08b18cb

Choose a tag to compare

AxonFlow Java SDK v5.4.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>5.4.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:5.4.0'

Changes

See CHANGELOG.md for details.

Release 5.3.0

09 Apr 23:48
127a781

Choose a tag to compare

AxonFlow Java SDK v5.3.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>5.3.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:5.3.0'

Changes

See CHANGELOG.md for details.

Release 5.2.0

08 Apr 21:11
06e8b90

Choose a tag to compare

AxonFlow Java SDK v5.2.0

Installation

Maven:

<dependency>
    <groupId>com.getaxonflow</groupId>
    <artifactId>axonflow-sdk</artifactId>
    <version>5.2.0</version>
</dependency>

Gradle:

implementation 'com.getaxonflow:axonflow-sdk:5.2.0'

Changes

See CHANGELOG.md for details.