Limited Access Notice

Due to increased demand, yWorkflow access is currently limited to existing customers. If you're an existing customer or have a business inquiry, please contact us.

How it works

Installation

Add yWorkflow to your Java project using Maven or Gradle.

implementation(platform("com.yworkflow:yworkflow-bom:1.0.0"))
implementation("com.yworkflow:yworkflow-engine")

// if you want to use YAML
implementation("com.yworkflow:definition-factory-yaml")
<dependencyManagement>
    <dependencies>
         <dependency>
             <groupId>com.yworkflow</groupId>
             <artifactId>yworkflow-bom</artifactId>
             <version>1.0.0</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
    </dependencies>
</dependencyManagement>
                     
<dependency>
    <groupId>com.yworkflow</groupId>
    <artifactId>yworkflow-engine</artifactId>
</dependency>

<dependency>
    <groupId>com.yworkflow</groupId>
    <artifactId>definition-factory-yaml</artifactId>
</dependency>

Quick Start

Get started with yworkflow in just a few lines of code.

// 1. Initialize the main Workflows object.
var workflows = new DefaultWorkflowsBuilder()
    .withInstanceStore(new MemoryWorkflowInstanceStore())
    .build();

// 2. Define a minimal workflow in a YAML string.
// `initial-transitions` define how a workflow can be started.
// `states` are the steps the workflow can be in.
var yamlDefinitionString =
    """
workflow:
  id: "leave_request"
  initial-transitions:
    - id: "create_request"
      default-result:
        state: "draft_leave_request"
  states:
    - id: "draft_leave_request"
""";

// 3. Parse the YAML string into a formal Workflow object.
var workflow = WorkflowYaml.fromString(yamlDefinitionString).toWorkflow();
workflows.definitions().save(workflow);

// 4. Create an instance of the workflow.
// This simulates a user starting a new leave request.
var workflowInstance =
    workflows
        .instances()
        .init(
            workflowId("leave_request"),
            transitionId("create_request"));

// 5. Assert the final state of the instance.
assertEquals(WorkflowInstanceState.COMPLETED, workflowInstance.getState());

Workflow Definition

Define workflows using Java API or declarative formats like YAML, XML, and JSON.

Workflow Tutorial Diagram
var workflow = new Workflow("Access Request Workflow");

workflow.transitions().addInitialTransition(
      transition(transitionId("start").name("Create Access Request"))
        .defaultResult(result(stateId("initial"))
          .enterStatus(resultStatus("pending"))));

workflow.addState(state(stateId("initial").name("Access Request Draft"))
        .transitions(
                transition(transitionId("submit").name("Submit Access Reques"))
                        .defaultResult(result(forkId("fork"))
                                .enterStatus(resultStatus("pending")))));

workflow.addState(state(stateId("approval_1").name("Manager Approval"))
    .transitions(
        transition(transitionId("deny_1").name("Manager Reject Request"))
            .defaultResult(result(stateId("initial"))
              .exitStatus(resultStatus("rejected"))
              .enterStatus(resultStatus("pending"))),
        transition(transitionId("approve_1").name("Manager Approve Request"))
            .defaultResult(result(joinId("join"))
              .enterStatus(resultStatus("pending")))));

workflow.addState(state(stateId("approval_2").name("Administrator Approval"))
    .transitions(
      transition(transitionId("deny_2").name("Administrator Reject Request"))
          .defaultResult(result(stateId("initial"))
              .exitStatus(resultStatus("rejected"))
              .enterStatus(resultStatus("pending"))),
      transition(transitionId("approve_2").name("Administrator approve request"))
          .defaultResult(result(joinId("join"))
              .enterStatus(resultStatus("pending")))));

workflow.addState(state(stateId("approved").name("Access Request Approved")));

workflow.addFork(fork(forkId("fork"))
            .results(
                result(stateId("approval_1"))
                  .enterStatus(resultStatus("pending")),
              result(stateId("approval_2"))
                .enterStatus(resultStatus("pending"))));

workflow.addJoin(join(joinId("join"))
            .defaultResult(result(stateId("approved"))
                .enterStatus(resultStatus("completed")))
            .conditions(
                conditions(Conditions.Operator.AND,
                    scriptCondition("join.states.approval_1.status.completed"),
                    scriptCondition("join.states.approval_2.status.completed")
                )
            ));
{
  "id": "Access Request Workflow",
  "initial_transitions": [
    {
      "id": "start", "name": "Create Access Request",
      "default_result": { "state": "initial", "enter_status": "pending" }
    }
  ],
  "states": [
    {
      "id": "initial", "name": "Access Request Draft",
      "transitions": [
        {
          "id": "submit", "name": "Submit Access Request",
          "default_result": { "fork": "fork", "enter_status": "pending" }
        }
      ]
    },
    {
      "id": "approval_1", "name": "Manager Approval",
      "transitions": [
        {
          "id": "deny_1", "name": "Manager Reject Request",
          "default_result": { "state": "initial", "enter_status": "pending", "exit_status": "rejected" }
        },
        {
          "id": "approve_1", "name": "Manager Approve Request",
          "default_result": { "join": "join", "enter_status": "pending" }
        }
     ]
    },
     {
       "id": "approval_2", "name": "Administrator Approval",
       "transitions": [
         {
           "id": "deny_2", "name": "Administrator Reject Request",
           "default_result": { "state": "initial", "enter_status": "pending", "exit_status": "rejected" }
         },
         {
           "id": "approve_2", "name": "Administrator approve request",
           "default_result": { "join": "join", "enter_status": "pending" }
         }
      ]
     },
     {
        "id": "approved", "name": "Access Request Approved"
     }
  ],
   "forks": [
    {
      "id": "fork",
      "default_results": [
        {"state":"approval_1", "enter_status":  "pending"},
        {"state":"approval_2", "enter_status":  "pending"}
      ]
    }
   ],
   "joins": [
    {
      "id": "join",
      "join_conditions": {
        "operator": "AND",
        "conditions": [
          {
            "type": "script", "value": "groovy",
            "args": [
              {
                "name": "script",
                "content": "join.approval_1.status.completed"
              }
            ]
          },
          {
            "type": "script", "value": "groovy",
            "args": [
              {
                "name": "script",
                "content": "join.approval_2.status.completed"
              }
            ]
          }
        ]
      },
      "default_result": { "state": "approved", "enter_status": "completed" }
    }
   ]
}
<?xml version="1.0"?>
<workflow xmlns="https://www.yworkflow.com/yworkflow/1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="https://www.yworkflow.com/yworkflow/1.0 
          https://www.yworkflow.com/yworkflow/yworkflow_1_0_0.xsd">

    <id>Access Request Worfklow</id>

    <initial-transitions>
        <transition id="start" name="Create Access Request">
            <results>
                <default-result enter-status="pending" state="initial"/>
            </results>
        </transition>
    </initial-transitions>

    <states>
        <state id="initial" name="Access Request Draft">
            <transitions>
                <transition id="submit" name="Submit Access Request">
                    <results>
                        <default-result enter-status="pending" fork="fork"/>
                    </results>
                </transition>
            </transitions>
        </state>
        <state id="approval_1" name="Manager Approval">
            <transitions>
                <transition id="deny_1" name="Manager Reject Request">
                    <results>
                        <default-result exit-status="rejected" enter-status="pending" state="initial"/>
                    </results>
                </transition>
                <transition id="approve_1" name="Manager Approve Request">
                    <results>
                        <default-result enter-status="pending" join="join"/>
                    </results>
                </transition>
            </transitions>
        </state>
        <state id="approval_2" name="Administrator Approval">
            <transitions>
                <transition id="deny_2" name="Administrator Reject Request">
                    <results>
                        <default-result exit-status="rejected" enter-status="pending" state="initial"/>
                    </results>
                </transition>
                <transition id="approve_2" name="Administrator approve request">
                    <results>
                        <default-result enter-status="pending" join="join"/>
                    </results>
                </transition>
            </transitions>
        </state>
        <state id="approved" name="Access Request Approved"/>
    </states>

    <forks>
        <fork id="fork">
            <default-result enter-status="pending" state="approval_1"/>
            <default-result enter-status="pending" state="approval_2"/>
        </fork>
    </forks>

    <joins>
        <join id="join">
            <conditions operator="AND">
                <condition type="script" value="groovy">
                    <arg name="script">join.approval_1.status.completed</arg>
                </condition>
                <condition type="script" value="groovy">
                    <arg name="script">join.approval_2.status.completed</arg>
                </condition>
            </conditions>
            <default-result enter-status="completed" state="approved"/>
        </join>
    </joins>
</workflow>
workflow:
  id: "Access Request Worfklow"
  initial-transitions:
    - id: "start"
      name: "Create Access Request"
      default-result:
        state: "initial"
        enter-status: "pending"
  states:
    - id: "initial"
      name: "Access Request Draft"
      transitions:
        - id: "submit"
          name: "Submit Access Request"
          default-result:
            fork: "fork"
            enter-status: "pending"
    - id: "approval_1"
      name: "Manager Approval"
      transitions:
        - id: "deny_1"
          name: "Manager Reject Request"
          default-result:
            state: "initial"
            exit-status: "rejected"
            enter-status: "pending"
        - id: "approve_1"
          name: "Manager Approve Request"
          default-result:
            join: "join"
            enter-status: "pending"
    - id: "approval_2"
      name: "Administrator Approval"
      transitions:
        - id: "deny_2"
          name: "Administrator Reject Request"
          default-result:
            state: "initial"
            exit-status: "rejected"
            enter-status: "pending"
        - id: "approve_2"
          name: "Administrator Approve Request"
          default-result:
            join: "join"
            enter-status: "pending"
    - id: "approved"
      name: "Access Request Approved"
  forks:
    - id: "fork"
      default-results:
        - state: "approval_1"
          enter-status: "pending"
        - state: "approval_2"
          enter-status: "pending"
  joins:
    - id: "join"
      condition:
        and:
          - script: "groovy"
            args:
              - script: |
                  join.approval_1.status.completed
          - script: "groovy"
            args:
              - script: |
                  join.approval_2.status.completed
      default-result:
        state: "approved"
        enter-status: "completed"

AI Integration

Leverage AI capabilities for intelligent workflow decisions and validation.

AI-Powered Features

  • AI Validation: Use AI to validate document content, images, or data
  • Smart Transitions: Let AI decide the optimal workflow path
  • Content Analysis: Analyze and categorize workflow data
  • Predictive Routing: Predict the best next steps based on historical data
workflow:
  id: "access-request-with-policy-check"
  initial-transitions:
    - id: "create_request"
      name: "Create Access Request"
      default-result:
        state: "draft"
        enter-status: "pending"
  
  states:
    - id: "draft"
      name: "Draft Access Request"
      transitions:
        - id: "submit"
          name: "Submit for Policy Check"
          default-result:
            state: "policy_check"
            post-functions:
              - alias: "ai"
                args:
                  - prompt: |
                      You are a corporate policy enforcement AI. Analyze this access request:
                      
                      Request Reason: ${inputs.reason}
                      Requested Access: ${inputs.access_level}
                      User Role: ${inputs.user_role}
                      Department: ${inputs.department}
                      Requested Systems: ${inputs.systems}
                      
                      Company Policies:
                      - Financial data access requires VP approval
                      - Customer data access requires manager approval
                      - Admin access requires dual approval
                      - Temporary access limited to 30 days
                      - Sensitive systems require background check
                      
                      Return JSON response:
                      {
                        "compliant": true/false,
                        "policy_violations": ["list of violations"],
                        "required_approvals": ["list of required approvers"],
                        "risk_level": "LOW/MEDIUM/HIGH",
                        "recommendation": "explanation"
                      }
                  - inputs:
                      - name: "reason"
                      - name: "access_level"
                      - name: "user_role"
                      - name: "department"
                      - name: "systems"
    
    - id: "policy_check"
      name: "Policy Compliance Check"
      transitions:
        - id: "resolution"
          name: "Policy Resolution"
          results:
            - state: "manager_approval"
              condition:
                - script: "groovy"
                  args:
                    - script: "transients.compliant"
          default-result:
            state: "rejected"
            enter-status: "rejected"
    
    - id: "manager_approval"
      name: "Manager Approval"
      transitions:
        - id: "approve"
          name: "Approve"
          default-result:
            state: "approved"
            enter-status: "completed"
        
        - id: "reject"
          name: "Reject"
          default-result:
            state: "rejected"
            enter-status: "rejected"
    
    - id: "approved"
      name: "Access Granted"
    
    - id: "rejected"
      name: "Request Rejected"
workflow:
  id: "risk-based-routing"
  states:
    - id: "access_request"
      name: "Access Request"
      transitions:
        - id: "assess_risk"
          name: "Assess Risk Level"
          default-result:
            state: "risk_assessment"
            post-functions:
              - alias: "ai"
                args:
                  - prompt: |
                      You are a security risk assessment AI. Evaluate this access request:
                      
                      User: ${inputs.user_name}
                      Role: ${inputs.user_role}
                      Department: ${inputs.department}
                      Requested Access: ${inputs.access_level}
                      Target Systems: ${inputs.target_systems}
                      User History: ${inputs.user_history}
                      Request Reason: ${inputs.reason}
                      
                      Risk Factors:
                      - High-privilege access (admin, root, financial)
                      - Sensitive data access (PII, customer data, financial)
                      - Unusual access patterns
                      - User with previous violations
                      - Access outside normal hours
                      - Large scope of access
                      
                      Return JSON:
                      {
                        "risk_level": "LOW/MEDIUM/HIGH",
                        "risk_factors": ["list of risk factors"],
                        "recommended_path": "auto_approve/manager_only/dual_approval/security_review",
                        "confidence": 0.85,
                        "explanation": "detailed explanation"
                      }
                  - inputs:
                      - name: "user_name"
                      - name: "user_role"
                      - name: "department"
                      - name: "access_level"
                      - name: "target_systems"
                      - name: "user_history"
                      - name: "reason"
    
    - id: "risk_assessment"
      name: "Risk Assessment"
      transitions:
        - id: "risk_resolution"
          name: "Risk Resolution"
          results:
            - state: "auto_approved"
              condition:
                - script: "groovy"
                  args:
                    - script: "transients.risk_level == 'LOW'"
            - state: "manager_approval"
              condition:
                - script: "groovy"
                  args:
                    - script: "transients.risk_level == 'MEDIUM'"
            - state: "security_review"
              condition:
                - script: "groovy"
                  args:
                    - script: "transients.risk_level == 'HIGH'"
          default-result:
            state: "manager_approval"
            enter-status: "pending"
workflow:
  id: "document-approval-with-ai"
  states:
    - id: "draft"
      name: "Document Draft"
      transitions:
        - id: "submit"
          name: "Submit for AI Review"
          default-result:
            state: "ai_validation"
            post-functions:
              - alias: "ai"
                args:
                  - prompt: |
                      You are a document validation AI. Review this document:
                      
                      Document Type: ${inputs.document_type}
                      Content: ${inputs.content}
                      Author: ${inputs.author}
                      Department: ${inputs.department}
                      
                      Validation Criteria:
                      - Grammar and spelling accuracy
                      - Compliance with company style guide
                      - Technical accuracy for technical documents
                      - Legal compliance for contracts
                      - Data privacy for sensitive documents
                      
                      Return JSON:
                      {
                        "valid": true/false,
                        "score": 0.85,
                        "issues": ["list of issues found"],
                        "suggestions": ["list of improvements"],
                        "compliance_status": "COMPLIANT/NON_COMPLIANT"
                      }
                  - inputs:
                      - name: "document_type"
                      - name: "content"
                      - name: "author"
                      - name: "department"
    
    - id: "ai_validation"
      name: "AI Content Validation"
      transitions:
        - id: "validation_resolution"
          name: "Validation Resolution"
          results:
            - state: "human_review"
              condition:
                - script: "groovy"
                  args:
                    - script: "transients.valid"
          default-result:
            state: "revision_required"
            enter-status: "pending"
    
    - id: "human_review"
      name: "Human Review"
      transitions:
        - id: "approve"
          name: "Approve"
          default-result:
            state: "approved"
            enter-status: "completed"
        
        - id: "reject"
          name: "Reject"
          default-result:
            state: "revision_required"
            enter-status: "pending"
    
    - id: "revision_required"
      name: "Revision Required"
    
    - id: "approved"
      name: "Document Approved"

Persistence Options

Flexible persistence for both workflow definitions and instances with multiple backend options.

Workflow Definitions

Store workflow definitions in your preferred storage:

// Built-in, no dependency needed
// Perfect for testing and development
implementation(platform("com.yworkflow:yworkflow-bom:1.0.0"))
implementation("com.yworkflow:yworkflow-engine")

// Usage example:
var workflows = new DefaultWorkflowsBuilder()
    .withInstanceStore(new MemoryWorkflowInstanceStore())
    .build(); // Uses in-memory by default
implementation(platform("com.yworkflow:yworkflow-bom:1.0.0"))
implementation("com.yworkflow:yworkflow-engine")
implementation("com.yworkflow:instance-store-repository-mongodb")

<!-- Usage example: -->
var mongoClient = MongoClients.create("mongodb://localhost:27017");
var jsonWorkflowConverter = new JsonWorkflowConverter();
var workflowInstanceRepository = new MongoWorkflowInstanceRepository(mongoClient);
var workflowDefinitionRepository new MongoWorkflowDefinitionRepository(mongoClient, 
     jsonWorkflowConverter);
var workflows = new DefaultWorkflowsBuilder()
      .withInstanceRepository(workflowInstanceRepository)
      .withDefinitionRepository(workflowDefinitionRepository)
      .build();

Workflow Instances

Store workflow instances in your preferred database:

// Built-in, no dependency needed
// Perfect for testing and development
implementation(platform("com.yworkflow:yworkflow-bom:1.0.0"))
implementation("com.yworkflow:yworkflow-engine")

// Usage example:
var workflows = new DefaultWorkflowsBuilder()
    .withInstanceStore(new MemoryWorkflowInstanceStore())
    .build();
implementation(platform("com.yworkflow:yworkflow-bom:1.0.0"))
implementation("com.yworkflow:yworkflow-engine")
implementation("com.yworkflow:instance-store-jdbc-sqlite")

<!-- Usage example: -->
var connectionProvider = JdbcConnectionProvider.from(dataSource);
var store = new SqliteJdbcWorkflowInstanceStore(connectionProvider);
var workflows = new DefaultWorkflowsBuilder()
    .withInstanceStore(store)
    .build();
implementation(platform("com.yworkflow:yworkflow-bom:1.0.0"))
implementation("com.yworkflow:yworkflow-engine")
implementation("com.yworkflow:instance-store-jdbc-postgresql")

<!-- Usage example: -->
var connectionProvider = JdbcConnectionProvider.from(dataSource);
var store = new PostgreSqlJdbcWorkflowInstanceStore(connectionProvider);
var workflows = new DefaultWorkflowsBuilder()
    .withInstanceStore(store)
    .build();
implementation(platform("com.yworkflow:yworkflow-bom:1.0.0"))
implementation("com.yworkflow:yworkflow-engine")
implementation("com.yworkflow:instance-store-repository-mongodb")

<!-- Usage example: -->
var mongoClient = MongoClients.create("mongodb://localhost:27017");
var jsonWorkflowConverter = new JsonWorkflowConverter();
var workflowInstanceRepository = new MongoWorkflowInstanceRepository(mongoClient);
var workflowDefinitionRepository new MongoWorkflowDefinitionRepository(mongoClient, 
     jsonWorkflowConverter);
var workflows = new DefaultWorkflowsBuilder()
      .withInstanceRepository(workflowInstanceRepository)
      .withDefinitionRepository(workflowDefinitionRepository)
      .build();