Skip to main content

Pony ID

The open-source LittleHorse Kernel natively supports User Tasks. However, the LittleHorse Kernel does not support the concept of user identity as it would require adding significant amounts of complexity and external dependencies to the open-source project.

The User Tasks Bridge solves this problem by allowing you to connect your own Identity Provider (IdP) to LittleHorse.

Note

While the LittleHorse Kernel is open-source, the User Tasks Bridge is a paid product of LittleHorse Enterprises. The docker image present in this quickstart is suitable for local development but you should contact sales@littlehorse.io for production deployment of the User Tasks Bridge.

You can use open-source User Tasks in production without the User Tasks Bridge. To do so, we recommend checking out the open-source User Tasks Documentation to understand how to use User Tasks in your workflows.

Quickstart

This guide will walk you through using the User Tasks Bridge in a complete local development setup.

You will do the following:

  • Spin up a local LittleHorse + User Tasks Bridge environment using Docker

  • Define a userTaskDef for approving an IT rental

  • Register supporting taskDefs for handling the workflow

  • Create a wfSpec that includes a human approval step

  • Use the User Tasks Bridge Console to view and complete assigned tasks

Step 1: Running Locally with Docker

Start the standalone container:

Linux:

docker run --pull always --name lh-user-tasks-bridge-standalone --rm -d --net=host \
ghcr.io/littlehorse-enterprises/lh-user-tasks-bridge-backend/lh-user-tasks-bridge-standalone:latest

Windows/Mac:

docker run --pull always --name lh-user-tasks-bridge-standalone --rm -d \
-p 8080:8080 \
-p 8888:8888 \
-p 8089:8089 \
-p 3000:3000 \
-p 2023:2023 \
ghcr.io/littlehorse-enterprises/lh-user-tasks-bridge-backend/lh-user-tasks-bridge-standalone:latest

The standalone container starts the following components:

Step 2: Defining a Workflow with the LH Kernel

Creating the userTaskDef

Before we can define our wfSpec, we first need to register the it-approval userTaskDef that will be used within our workflow.

To register a userTaskDef, we will:

  • Define the fields that will be used in the userTask form
  • Construct the userTaskDefRequest object
  • Register the userTaskDef with the LH Kernel

import io.littlehorse.sdk.common.config.LHConfig;
import io.littlehorse.sdk.common.proto.PutUserTaskDefRequest;
import io.littlehorse.sdk.usertask.UserTaskSchema;
import io.littlehorse.sdk.usertask.annotations.UserTaskField;

class ApprovalForm{
// Define the fields that will be used in the user task form
@UserTaskField(displayName = "approve it rental" , required = true)
public boolean isApproved;
}

public class ApprovalTask{
public static void main(String[] args) {
LHConfig config = new LHConfig();
// Create the user task schema and compile it into a `PutUserTaskDefRequest`
UserTaskSchema schema = new UserTaskSchema(new ApprovalForm(), "approve-it-rental");
PutUserTaskDefRequest userTask = schema.compile();

// Register the `userTaskDef` with the LH Kernel
config.getBlockingStub().putUserTaskDef(userTask);
}
}

Creating the TaskDefs

Now that the userTaskDef is registered with the LH Kernel, we need to create, register, and start our taskWorkers.

We will create two different taskDefs:

One task for shipping the IT item when the rental is approved

One task to notify the employee that the rental was not approved


import io.littlehorse.sdk.common.config.LHConfig;
import io.littlehorse.sdk.worker.LHTaskMethod;
import io.littlehorse.sdk.worker.LHTaskWorker;

class TaskWorker {
@LHTaskMethod("ship-item")
public void shipItem(String item){
System.out.println(item + " shipped");
}

@LHTaskMethod("decline-order")
public void cancelOrder(String employee, String item ){
System.out.println("Sorry "+ employee + " you have not been approved for " + item);
}

}

public class RegisterWorkers{

public static void main(String[] args){
LHConfig config = new LHConfig();

//Create and register TaskDefs
LHTaskWorker shipItemTask = new LHTaskWorker(new TaskWorker(), "ship-item" ,config );
shipItemTask.registerTaskDef();

LHTaskWorker notApprovedTask = new LHTaskWorker(new TaskWorker(), "decline-order", config);
notApprovedTask.registerTaskDef();

// Start the TaskWorkers
shipItemTask.start();
notApprovedTask.start();
}
}

Creating the wfSpec

With both the userTaskDef and taskDef registered, it is time to create the wfSpec

The wfSpec below does the following:

  • Declares the variables that will be used in the workflow
  • Assigns the userTaskDef to the someemailaddress@somedomain.com, the email of my-user
  • Uses the doIf to handle the approval logic
  • Executes the ship-item task if the rental is approved, or the decline-order task if the rental is not approved

import io.littlehorse.sdk.common.config.LHConfig;
import io.littlehorse.sdk.wfsdk.NodeOutput;
import io.littlehorse.sdk.wfsdk.WfRunVariable;
import io.littlehorse.sdk.wfsdk.Workflow;
import io.littlehorse.sdk.wfsdk.WorkflowThread;

public class UTBWorkflow {


public static void wfLogic(WorkflowThread wfThread){
WfRunVariable item = wfThread.declareStr("item").required();
WfRunVariable employee = wfThread.declareStr("employee").required();
WfRunVariable isApproved = wfThread.declareBool("is-approved");

NodeOutput result = wfThread.assignUserTask("approve-it-rental", "someemailaddress@somedomain.com", users);
isApproved.assign(result.jsonPath("$.isApproved"));

wfThread.doIf(isApproved.isEqualTo(false), ifHandler ->{
ifHandler.execute("decline-order", item, employee);
ifHandler.complete();
});

wfThread.execute("ship-item", item);
}

public static void main(String[] args){
LHConfig config = new LHConfig();
Workflow wfGenerator = Workflow.newWorkflow("it-request", UTBWorkflow::wfLogic);
wfGenerator.registerWfSpec(config.getBlockingStub());
}
}

Step 3: Run the Workflow

Now that our wfSpec is registered, we can run the workflow using the LittleHorse CLI.

Run the following lhctl command to start the workflow:

lhctl run it-request item laptop employee obi-wan

Step 4: Logging into the User Tasks Bridge Console and Completing the Task

User Task Bridge Console

Now that the workflow is running, we can log into the User Task Bridge Console to view and complete the UserTaskRun

Credentials:

UserPassRealm
my-user1234default
my-admin-user1234default
adminadminmaster

User Tasks Bridge Console (http://localhost:3000)

  • Sign in as my-admin-user to view and manage all userTasks.

When you log in as my-admin-user, you will see the userTaskRun that was created by the workflow.

Do not complete the task yet! We will complete the task as my-user in the next step.

User Tasks Bridge Console with an assigned User Task Run for the It-request workflow
User Tasks Bridge Console with an assigned User Task Run for the It-request workflow

if you navigate to the users tab, you will notice that the my-admin-user is able to manage all users and groups in the default realm.

User Tasks Bridge Console with the users tab
User Tasks Bridge Console with the users tab

If you navigate back to userTaskDefs, you will see the userTaskDef that was registered for the approve-it-rental task and assigned to the user my-user.

If you click on the approve-it-rental userTask, as the admin, you will be able to view the details of the userTask, as well as complete the userTask or assign it to another user.

User Tasks Bridge Console with the user task definition for the approve-it-rental task
User Tasks Bridge Console with the user task definition for the approve-it-rental task

Keycloak Identity Provider (http://localhost:8888)

  • Sign in as admin with realm master to view and manage all users and groups. As well as create new users, userGroups, and realms.
Keycloak Admin Console
Keycloak Admin Console

Viewing and Completing userTasks

User Tasks Bridge Console (http://localhost:3000)

Log back into the User Tasks Bridge Console as my-user.

Once logged in, you will see the userTaskRun that was created by the workflow. You can click on the task to view the details and complete the task.

The User Task Bridge Console also allows filtering of userTasks by userTaskRun status, userGroups, and date range.

User Tasks Bridge Console with an assigned User Task Run for the It-request workflow
User Tasks Bridge Console with an assigned User Task Run for the It-request workflow

You can complete the task by filling out the form and clicking the "Complete Task" button. Once you complete the task, the workflow will continue.

User Tasks Bridge Console with the form for the It-request workflow
User Tasks Bridge Console with the form for the It-request workflow

To view the completed workflow, you can navigate to the LittleHorse Dashboard (http://localhost:8080) and view the workflow run.

LittleHorse Dashboard with the completed It-request workflow
LittleHorse Dashboard with the completed It-request workflow

To view the userTaskRun details with lchtl you can run the following command:

lhctl get userTaskRun <wfRunId> <userTaskGuid> 
{
"id": {
"wfRunId": {
"id": "b82c06f0c34f4966941d8c016ac9b88a"
},
"userTaskGuid": "2230d990106f475c9d4c6ac8dc471614"
},
"userTaskDefId": {
"name": "approve-it-rental",
"version": 0
},
"userId": "someemailaddress@somedomain.com",
"results": {
"isApproved": {
"bool": true
}
},
"status": "DONE",
"events": [
{
"time": "2025-06-23T01:06:52.921Z",
"assigned": {
"newUserId": "someemailaddress@somedomain.com"
}
}
],
"scheduledTime": "2025-06-23T01:06:52.941Z",
"nodeRunId": {
"wfRunId": {
"id": "b82c06f0c34f4966941d8c016ac9b88a"
},
"threadRunNumber": 0,
"position": 1
},
"epoch": 1
}

Ready to Use Your Own IdP?

If you're interested in integrating the User Tasks Bridge with your organization's Identity Provider, we're here to help! Contact us at sales@littlehorse.io to learn more about our offerings and how we can support your production deployment needs.

warning

This quickstart is intended for demonstration and testing purposes only. It uses a pre-configured Keycloak instance with default credentials and is not suitable for production environments.

The container automatically registers and runs a demo workflow called user-tasks-bridge-demo to demonstrate the capabilities of using an Identity Provider (IdP) to manage UserTasks in LittleHorse. You'll be able to interact with these demo tasks through the User Tasks UI immediately after logging in.

Keep in mind that you can still register and run your own workflows and not limited to the demo workflow.