A programmatic, type‑safe Java API for building and running Serverless Workflows (and agentic workflows) without writing YAML.
| Module | Purpose |
|---|---|
| spec | Core DSL implementing the Serverless Workflow Specification. Purely compliant fluent API. |
| func | Java‑centric “functional” DSL on top of spec: adds Function<>/Predicate<> support, callFn for Java method calls, and richer flow controls. |
| agentic | Experimental proof‑of‑concept DSL built on func for LangChain4j agentic workflows: agent, sequence, loop, parallel, etc. |
Add the modules you need to your Maven pom.xml (replace versions as appropriate):
<!--
Replace ${version.io.serverlessworkflow} with the actual released version:
https://github.com/serverlessworkflow/sdk-java/releases
-->
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-fluent-spec</artifactId>
<version>${version.io.serverlessworkflow}</version>
</dependency>
<dependency>
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-fluent-func</artifactId>
<version>${version.io.serverlessworkflow}</version>
</dependency>
<dependency> <!-- optional, experimental -->
<groupId>io.serverlessworkflow</groupId>
<artifactId>serverlessworkflow-fluent-agentic</artifactId>
<version>${version.io.serverlessworkflow}</version>
</dependency>Fully compliant with the CNCF Serverless Workflow spec.
Use it when you want a 1:1 mapping of the YAML DSL in Java.
import io.serverlessworkflow.api.types.Workflow;
import io.serverlessworkflow.fluent.spec.WorkflowBuilder;
Workflow wf = WorkflowBuilder
.workflow("flowDo")
.tasks(tasks ->
tasks
.set("initCtx", "$.foo = 'bar'")
.forEach("item", f -> f
.each("item")
.at("$.list")
)
)
.build();Note
We rename reserved keywords (for, do, if, while, switch, try) to safe identifiers (forEach, tasks, when, etc.).
A Java‑first DSL that builds on spec, adding:
callFn: invoke arbitrary JavaFunction<>handlersPredicate<>guards viawhen(Predicate)- Built‑in
Function/Predicatesupport instead of JQ expressions
import io.serverlessworkflow.api.types.Workflow;
import io.serverlessworkflow.fluent.func.FuncWorkflowBuilder;
Workflow wf = FuncWorkflowBuilder
.workflow("callJavaFlow")
.tasks(tasks ->
tasks.callFn("invokeHandler", call -> call
// e.g. call.className("com.acme.Handler")
// .method("handle")
// .arg("key", "value")
.function(ctx -> {
// your code here
})
)
)
.build();Warning
The func DSL is not spec‑compliant. It adds Java‑specific tasks and control‑flow extensions for in‑JVM execution.
Built on func for LangChain4j agentic workflows. Adds:
agent(instance): invoke a LangChain4j agentsequence(...): run agents in orderloop(cfg): retry or repeated agent callsparallel(...): fork agent calls concurrently
import io.serverlessworkflow.api.types.Workflow;
import io.serverlessworkflow.fluent.agentic.AgentWorkflowBuilder;
var scorer = AgentsUtils.newMovieExpert();
var editor = AgentsUtils.newMovieExpert();
Workflow wf = AgentWorkflowBuilder
.workflow("retryFlow")
.tasks(tasks -> tasks.loop(
"reviewLoop",
loop -> loop
.maxIterations(5)
.exitCondition(c -> c.readState("score", 0).doubleValue() > 0.75)
.subAgents("reviewer", scorer, editor)
))
.build();import io.serverlessworkflow.api.types.Workflow;
import io.serverlessworkflow.fluent.agentic.AgentWorkflowBuilder;
import java.util.function.Predicate;
public class OrderFulfillment {
static class InventoryAgent { /* … */ }
static class NotificationAgent { /* … */ }
static class ShippingAgent { /* … */ }
public Workflow buildWorkflow() {
Predicate<Object> inventoryOk = state ->
Boolean.TRUE.equals(((java.util.Map<?,?>) state).get("inventoryAvailable"));
return AgentWorkflowBuilder
.workflow("OrderFulfillment")
.tasks(tasks -> tasks
// 1. initialize state
.set("init", s -> s.expr("$.orderId = '.input.oriderId'"))
// 2. check inventory
.agent("checkInventory", new InventoryAgent())
// 3. pull result into a flag
.set("inventoryAvailable", s -> s.expr("$.checkInventory.available"))
// 4. retry until in stock (max 3 attempts)
.loop("retryIfOutOfStock", loop -> loop
.maxIterations(3)
.exitCondition(inventoryOk)
.subAgents("inventoryChecker", new InventoryAgent())
)
// 5. notify systems in parallel
.parallel("notifyAll",
new NotificationAgent(),
new ShippingAgent()
)
// 6. mark order complete
.set("complete", s -> s.expr("$.status = 'COMPLETED'"))
)
.build();
}
}- Error handling: retries, back‑off,
onErrorhandlers - Timers & delays:
wait, per‑tasktimeout - Sub‑workflows & composition: call one workflow from another
- Event tasks:
onEvent,sendEvent - Human‑in‑the‑Loop: approval/notification steps
Contributions welcome! Check out our CONTRIBUTING.md and join the CNCF Slack channel for Serverless Workflow.
Apache 2.0 © Serverless Workflow Authors