LittleHorse: Command Center for Business-as-Code

Orchestrate and govern processes across agents, microservices, and external integrations using Business-as-Code.

littlehorse.io littlehorse.io/docs/server/concepts littlehorse.io/docs slack

java go python js dotnet

About LittleHorse

LittleHorse is a high-throughput, low-latency orchestration engine that allows developers to codify processes spanning across agents, microservices, integrations, and workflows. LittleHorse's Business-as-Code approach allows you to write code that closely mirrors your business processes, creating better alignment between product & engineering while providing a robust durable execution platform.

Let LittleHorse take the reins and ditch the headaches of:

LittleHorse is built on Apache Kafka and Kafka Streams, and has two-way rich integrations with the Kafka Ecosystem. Workflows can be triggered by Kafka events and emit state changes back to Kafka in real time, enabling tight integration with event-driven architectures.

Business-as-Code

LH

:point_up: This picture shows a running instance (WfRun) for the process (WfSpec) defined by this code :point_down:

public void quickstartWf(WorkflowThread wf) {
    WfRunVariable fullName = wf.declareStr("full-name").searchable().required();
    WfRunVariable email = wf.declareStr("email").searchable().required();

    // Social Security Numbers are sensitive, so we mask the variable with `.masked()`.
    WfRunVariable ssn = wf.declareInt("ssn").masked().required();

    WfRunVariable identityVerified = wf.declareBool("identity-verified").searchable();

    wf.execute(VERIFY_IDENTITY_TASK, fullName, email, ssn).withRetries(3);

    NodeOutput identityVerificationResult = wf.waitForEvent(IDENTITY_VERIFIED_EVENT)
            .timeout(60 * 5) // 5 minute timeout
            .withCorrelationId(email)
            .registeredAs(Boolean.class);

    wf.handleError(identityVerificationResult, LHErrorType.TIMEOUT, handler -> {
        handler.execute(NOTIFY_CUSTOMER_NOT_VERIFIED_TASK, fullName, email);
        handler.fail("customer-not-verified", "Unable to verify customer identity in time.");
    });

    identityVerified.assign(identityVerificationResult);

    wf.doIf(identityVerified.isEqualTo(true), ifBody -> {
        ifBody.execute(NOTIFY_CUSTOMER_VERIFIED_TASK, fullName, email);
    })
    .doElse(elseBody -> {
        elseBody.execute(NOTIFY_CUSTOMER_NOT_VERIFIED_TASK, fullName, email);
    });
}

As you can see, the code above closely mirrors our example KYC business process. LittleHorse handles retries, timeouts, and orchestration across services for you, allowing your WfSpec to focus just on what matters to the business. Task workers handle integrations with external systems and databases.

Getting Started

In this section, we'll run the "Know-your-Customer" quickstart shown above in a language of your choice. You should be able to run your first WfRun in minutes!

Start the LittleHorse Server

Run the LittleHorse Server and Dashboard using our standalone docker image:

docker run --rm --pull=always --name littlehorse -d -p 9092:9092 -p 2023:2023 -p 8080:8080 ghcr.io/littlehorse-enterprises/littlehorse/lh-standalone:latest

Note: if you want to play with the output topic, which sends workflow updates to Kafka in real time, this also exposes a Kafka broker on localhost:9092.

Install the LittleHorse CLI

brew install littlehorse-enterprises/lh/lhctl

Alternatively, you can install it from our GitHub Releases page

Once you have lhctl ready, let's use the whoami command to verify that the LittleHorse Server is up and running:

lhctl whoami
{
  "id": {
    "id": "anonymous"
  },
  // ...
}

Run the Quickstart App

In this section, we'll start a program (in a language of your choice) which does four things:

  1. Register a couple TaskDefs (task definitions), which we'll compose into a workflow.
  2. Register an ExternalEventDef to keep track of callbacks from an external system.
  3. Register a WfSpec (workflow specification) to model the KYC proocess.
  4. Starts a few Task Workers which poll task queues in LittleHorse, waiting to be told to exxecute their tasks.

Java

./gradlew quickstart:run

Python

cd examples/python
poetry run python -m quickstart.quickstart

GoLang

go run ./examples/go/quickstart

C#

cd examples/dotnet/QuickstartExample
DOTNET_ROLL_FORWARD=Major dotnet run

JavaScript

First, install dependencies and start the task workers (this registers the required TaskDefs):

cd examples/js/quickstart
npm install && npm start

Then in another terminal, register the ExternalEventDef and WfSpec (note that our JS SDK does not yet support creation of WfSpecs, so we use lhctl here):

cd examples/js/quickstart
lhctl deploy externalEventDef identity-verified-external-event-def.json
lhctl deploy wfSpec quickstart-wfspec.json

Run a WfRun (Workflow Run)

In another terminal, run the quickstart workflow:

lhctl run quickstart full-name 'Obi-Wan Kenobi' email obiwan@jedi.temple ssn 123456789

Now, navigate to the dashboard at http://localhost:8080 and inspect your first WfRun. You'll notice that the WfRun is stuck waiting at the ExternalEventNode: this is because we're waiting for the callback from the "identity check" service that the workflow called in the first step!

You can post a correlated event that unblocks the workflow, simulating a repsonse from the external service:

lhctl put correlatedEvent obiwan@jedi.temple identity-verified BOOL true

See the per-language quickstarts for the full walkthrough:

You can also use lhctl to investigate! For starters:

Learn More

Architecture

To run a workflow with LittleHorse, you need to:

To get started quickly with a basic workflow, try our quickstarts in Java, Go, Python, C#, and JavaScript. For more detailed examples, you can check out:

For documentation, visit littlehorse.io/docs/server.

About the Project

LittleHorse is developed with love by engineers, for engineers.

Lifecycle and Release Plan

The LittleHorse Server follows Semantic Versioning after the release of version 1.0. You can find our (non-binding) project guidelines regarding our release schedule and deprecation strategy in our project lifecycle document.

Developing

For information about developing LittleHorse, see the guide in our local-dev README.

License

AGPLv3 License

All code in the ./server and ./dashboard directories in this repository is licensed by the GNU Affero General Public License, Version 3 and is copyright of LittleHorse Enterprises LLC.

All docker images from this repository are licensed by the GNU Affero General Public License, Version 3 and are copyright of LittleHorse Enterprises LLC.

All other code and packages, including our SDK's, lhctl, examples, and the corresponding packages is licensed by the Apache License 2.0.