Releases: getaxonflow/axonflow-sdk-java
Release 7.0.0
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 onRegisterRequestwas 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 inGHSA-248h-974q-xrc2. DO_NOT_TRACKopt-out removed in favor ofAXONFLOW_TELEMETRY=off(this release).DO_NOT_TRACKwas unreliable because host CLIs and runtimes commonly injectDO_NOT_TRACK=1regardless 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 localmvn testruns no longer inherit a hostDO_NOT_TRACK=1and emit accidental pings.- Test-harness opt-out hygiene (last cycle, v6.x). Test environments that mutate
DO_NOT_TRACKno 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_keyfor 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.mapTimeoutconfig 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.LLMProvidersource compatibility restored (last cycle, v6.x). The 7-arg primitive constructor and primitivegetPriority()/getWeight()accessors are back; null-safe boxed accessors split off asgetPriorityBoxed()/getWeightBoxed()for callers needing "explicitly 0 vs not set" disambiguation.
BREAKING
DO_NOT_TRACKis no longer honored as an AxonFlow telemetry opt-out. UseAXONFLOW_TELEMETRY=offinstead. Host tools and CLIs commonly injectDO_NOT_TRACK=1regardless of user intent, which makes it unreliable as a signal.- (Test API) Package-private
TelemetryReporter.isEnabledandTelemetryReporter.sendPingoverloads no longer accept aString doNotTrackparameter. The remainingString axonflowTelemetryparameter is the sole opt-out signal accepted by the testability surface.
Security
- TLS verification bypass closed (CWE-295).
HttpClientFactorypreviously honoredinsecureSkipVerify(true)onAxonFlowConfigas a single-flag opt-in to a permissiveX509TrustManagerthat accepted ANY server certificate, including attacker-presented certificates in MITM scenarios. The insecure path is now double-gated: it activates only if bothinsecureSkipVerify(true)is set on the builder AND theAXONFLOW_INSECURE_TLSenvironment variable is set totrue(or1). When the builder flag is set without the env var, the SDK logs a warning and keeps the JVM's defaultTrustManagerin 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.warnis no longer emitted on every telemetry decision whenDO_NOT_TRACK=1is 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 capsFiles.getLastModifiedTimecalls on hot request paths; aReentrantLock-guarded in-flight flag coalesces concurrent threads so only one ping fires under load.AXONFLOW_TELEMETRY=offis re-evaluated on every gate run. Restricted environments where no cache dir is available (e.g. AWS Lambda with noHOME/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 useAXONFLOW_TELEMETRY=offto suppress telemetry during automated runs.
Release 6.2.0
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. CallsGET /api/v1/llm-providers. NewLLMProviderandLLMProviderHealthtypes incom.getaxonflow.sdk.types. Async variantlistLLMProvidersAsync(). Closes the parity gap with the Python SDK'slist_providers()and the Go SDK'sListProviders().examples/basic/— minimal smoke example exercisinghealthCheck(),proxyLLMCall(), andlistConnectors()against a running AxonFlow agent. Uses try-with-resources so OkHttp's dispatcher + connection pool are cleaned up at exit. Run viamvn -q compile exec:javaaftermvn install -DskipTestsat the SDK root.
Fixed
LLMProvidersource compatibility restored. The 7-arg primitive constructorLLMProvider(name, type, enabled:bool, priority:int, weight:int, hasApiKey:bool, health)is back (delegates to the new 13-arg boxed form, marked@Deprecatedso new callers move to the boxed shape).getPriority()/getWeight()return primitiveintagain (null-safe-unbox to 0). Boxed accessors are available asgetPriorityBoxed()/getWeightBoxed()/getEnabledBoxed()/getHasApiKeyBoxed()for callers that need to distinguish "explicitly 0" from "field not present".
Release 6.1.0
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
MCPCheckInputResponsegains 5 optional Plugin Batch 1 fields:decisionId: String— audit correlatorriskLevel: String—low|medium|high|criticalpolicyMatches: List<ExplainPolicy>— per-policy explainability recordsoverrideAvailable: Boolean— whether session override is permitted for the matched policies (boxed so callers can distinguish "unset" fromfalseon older platforms)overrideExistingId: String— already-active override consumed by this decision (if any)
MCPCheckOutputResponsegains 3 optional fields:decisionId: StringpolicyMatches: List<ExplainPolicy>redactedMessage: String— text-redaction counterpart toredactedData(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
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 tomainwherepom.xml's<version>drifts from the first released## [X.Y.Z]section inCHANGELOG.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@JsonPropertyannotations and the OpenAPI specs pinned attests/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 aspec-pin-bumpPR 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 fromcreateWebhook. Required to verify theX-AxonFlow-Signatureheader on inbound webhook deliveries; without it, callers can't validate payload authenticity. Also addstenantIdandorgId(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()redactssecretto avoid log leakage.BudgetAlert.acknowledged— alert dismissal flag. Also adds@JsonPropertyannotations 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@JsonPropertyonly.
Fixed
- Telemetry pings now deliver reliably from short-lived JVMs (CLI, serverless, cold-starts).
AxonFlowconstruction blocks briefly while the ping is sent synchronously (bounded by the telemetry timeout). - Telemetry path is bounded at
TIMEOUT_SECONDS(3s) total; the/healthprobe and checkpoint POST share a single monotonic deadline instead of stacking independent timeouts.
Release 5.7.0
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:decisionresolves to"allow"or
"block",retryContextmirrors the gate response retry state,approvedBy
/approvedAt/rejectedBy/rejectedAtcarry reviewer identity,
approvalIdis the deterministic HITL queue UUID,policiesMatched
reconstructs the governance trail. The legacyworkflowId/stepId/
statusfields remain for back-compat. planIdon 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 constructors —
new ApproveStepResponse(workflowId, stepId, status)
andnew 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
getPendingApprovalsfor the WCP plane. The two-arg form accepts an
optionalplanIdfilter 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 gainsstepIndex,decision,decisionReason, andapprovalStatus
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/getPendingApprovalsendpoint 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/pendingroutes. Customers using these
methods against a live deployment were receiving 404s; this release makes
them work.PendingApprovalsResponsegetters and JSON field names aligned with the
wire shape — the class previously declaredgetApprovals()/getTotal()
over a JSON body with keysapprovals/total, which never matched the
server (pending_approvals/count). Getters renamed to
getPendingApprovals()/getCount()with the correct JSON bindings.
Callers that readresponse.getApprovals()orresponse.getTotal()need
to update to the new getter names.
Deprecated
DO_NOT_TRACK=1as an AxonFlow telemetry opt-out — scheduled for removal after 2026-05-05 in the next major release. UseAXONFLOW_TELEMETRY=offinstead. The SDK emits a one-line migration warning whenDO_NOT_TRACK=1is the active control andAXONFLOW_TELEMETRY=offis not also set.
Unchanged
approveStep(workflowId, stepId)/rejectStep(workflowId, stepId, reason)
method signatures onAxonFloware unchanged — only the response fields grew.
Release 5.6.0
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_contextandidempotency_keysupport on the step gate —
StepGateResponsenow carries aRetryContextobject on every gate call with the
true(workflow_id, step_id)lifecycle:gateCount,completionCount,
priorCompletionStatus(PriorCompletionStatusenum —
NONE/COMPLETED/GATED_NOT_COMPLETED),priorOutputAvailable,
priorOutput,priorCompletionAt,firstAttemptAt,lastAttemptAt,
lastDecision, andidempotencyKey. Prefer these to the legacycached/
decisionSourcefields.stepGate(workflowId, stepId, request, options)overload — new 4-arg overload
takingStepGateOptions. UseStepGateOptions.includePriorOutput()to send
?include_prior_output=truesoretryContext.priorOutputis populated when a prior
/completehas landed. Existing 3-arg overload keeps its signature and delegates
withStepGateOptions.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 typedIdempotencyKeyMismatchException.IdempotencyKeyMismatchException— new typed exception in
com.getaxonflow.sdk.exceptions. Thrown bystepGateandmarkStepCompletedwhen
the platform returns HTTP 409 witherror.code == "IDEMPOTENCY_KEY_MISMATCH".
SurfacesworkflowId,stepId,expectedIdempotencyKey,receivedIdempotencyKey,
plus inheritedstatusCode=409anderrorCode="IDEMPOTENCY_KEY_MISMATCH".RetryContext,PriorCompletionStatus,StepGateOptions— exported in
WorkflowTypes.
Fixed
- 409 dispatch on step gate/complete — previously all 409 responses on
markStepCompletedfell through to a genericAxonFlowException(..., 409, "VERSION_CONFLICT"), conflating step idempotency conflicts with plan version
conflicts. The step gate/complete call sites now inspect the 409 body and dispatch
toIdempotencyKeyMismatchExceptionwhenerror.codematches, falling back to a
genericAxonFlowExceptionotherwise. Plan update paths (which also use 409) are
untouched.
Deprecated
StepGateResponse.isCached()andStepGateResponse.getDecisionSource()—
marked@Deprecated. UsegetRetryContext().getGateCount() > 1and
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
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
mapTimeoutfield onAxonFlowConfig— brings Java to parity with
the TypeScript, Python, and Go SDKs (all three already had a separate
MAP timeout). The sharedtimeout(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 constantDEFAULT_MAP_TIMEOUT = 120s, new
builder methodAxonFlowConfig.builder().mapTimeout(Duration.ofSeconds(300)),
and new environment variableAXONFLOW_MAP_TIMEOUT_SECONDS. All
plan-lifecycle methods (generatePlan,executePlan,getPlanStatus,
updatePlan,cancelPlan,resumePlan,rollbackPlan,
getPlanVersions) now use a plan-specificOkHttpClientclone with
callTimeout/readTimeout/writeTimeoutset tomapTimeout.
Shares connection pool + interceptors + dispatcher with the main
client; only the timeout attributes differ. KeepmapTimeout≤
serverAXONFLOW_MAP_MAX_TIMEOUT_SECONDS(default 300s) ≤
front-door ALBidle_timeout.timeout_seconds(default 300s), or the
connection is killed mid-stream.
Release 5.4.0
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
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
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.