Getting started with Quarkus Flow

Welcome to Quarkus Flow!

Quarkus Flow brings the Serverless Workflow specification natively to Quarkus. It allows you to build durable, event-driven orchestrations and Agentic AI patterns using a highly ergonomic, type-safe Java DSL.

This tutorial shows the shortest path to building, exposing, and visualizing your first Quarkus Flow workflow.

Prerequisites

  • Java 17 or newer.

  • Maven 3.8+ (or the Quarkus CLI).

  • An existing Quarkus project. If you don’t have one, generate it quickly:

    quarkus create app org.acme:flow-quickstart
    cd flow-quickstart

1. Add the dependency

Add the core Quarkus Flow extension to your application.

pom.xml
<dependency>
  <groupId>io.quarkiverse.flow</groupId>
  <artifactId>quarkus-flow</artifactId>
  <version>0.7.1</version>
</dependency>

2. Define your first workflow

Workflows in Quarkus are simply Java classes that extend Flow. At build time, the engine discovers these classes, compiles them into an AST (Abstract Syntax Tree), and registers them as CDI beans.

Create a new Java class. This simple workflow takes an input, sets a greeting message into the global context, and finishes.

package org.acme;

import static io.serverlessworkflow.fluent.func.dsl.FuncDSL.set;

import java.util.Map;

import jakarta.enterprise.context.ApplicationScoped;

import io.quarkiverse.flow.Flow;
import io.serverlessworkflow.api.types.Workflow;
import io.serverlessworkflow.fluent.func.FuncWorkflowBuilder;

@ApplicationScoped
public class HelloWorkflow extends Flow {
    @Override
    public Workflow descriptor() {
        return FuncWorkflowBuilder.workflow("hello")
                // setting the workflow context with a map carrying a message.
                // it can be translated to JSON as { "message": "hello world!" }
                .tasks(set(Map.of("message", "hello world!")))
                .build();
    }
}

3. Expose the workflow via HTTP

Because Quarkus Flow is non-blocking, it integrates perfectly with Quarkus’s reactive REST layer.

You can inject your HelloWorkflow bean directly into a JAX-RS resource and use the .startInstance() method to execute it.

package org.acme;

import java.util.Map;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.jboss.resteasy.reactive.ResponseStatus;

import io.smallrye.mutiny.Uni;

@Path("/hello-flow")
@ApplicationScoped
public class HelloResource {

    @Inject
    HelloWorkflow hello; // inject the Flow subclass

    @GET
    @ResponseStatus(200)
    public Uni<Message> hello() {
        return hello
                .startInstance(Map.of()) // convenience on Flow
                .onItem()
                .transform(w -> w.as(Message.class).orElseThrow());
    }
}

(Note: The HelloResource depends on a simple Message record used to serialize the workflow output as JSON):

package org.acme;

public record Message(String message) {
}

4. Run the application and explore the Dev UI

Start Quarkus in development mode:

./mvnw quarkus:dev

Step 1: Test the endpoint
Open a new terminal and invoke the HTTP endpoint you just created:

curl http://localhost:8080/hello-flow

You should see a JSON response containing the message generated by your workflow tasks.

Step 2: See the Magic (The Dev UI)
One of the most powerful features of Quarkus Flow is its visualizer. Because you defined your workflow using a predictable DSL, the engine automatically generates a visual diagram of your logic.

  1. Press d in the terminal where Quarkus is running to open the Quarkus Dev UI in your browser.

  2. Find the Quarkus Flow card and click the Workflows link.

  3. Click on your hello-workflow to see the auto-generated Mermaid.js diagram showing exactly how your tasks execute!

What’s next?

Now that you have the engine running, you can start building real-world orchestrations. Choose your next path: