Skip to main content

Build a Document Approval Workflow with Orkes Conductor

In this tutorial, you’ll build a document approval workflow using Orkes Conductor. This workflow is common for review and sign-off processes in academia, publishing, legal approvals, and similar domains.

The workflow allows two reviewers to approve or reject a submitted document. Based on their decisions, the user will either receive an approval email or be asked to revise and resubmit the paper.

The document approval workflow

In this tutorial, you’ll build a workflow where:

  • A user submits a paper along with their email and the paper’s title.
  • Reviewer 1 receives a human task to approve or reject within 24 hours.
    • If approved, it proceeds to Reviewer 2.
    • If rejected, the user is notified by email to revise and resubmit based on the feedback.
  • If Reviewer 2 approves, the user receives an approval email.
  • If Reviewer 2 rejects, the user gets an email with reviewer feedback.

The workflow is configured so that if the assigned reviewer does not act on the task within the SLA period of 24 hours, the task automatically becomes available for anyone to claim and complete. Learn more about how assignment policies work for Human tasks.

Here’s how the workflow looks like:

Doc approval workflow in Orkes Conductor

Follow along using the free Developer Edition. If you don’t have an account yet, sign up to get started.

Step 1: Create a SendGrid integration in Orkes Conductor

In this tutorial, we’ll use SendGrid to send emails. To do that, you must set up a SendGrid integration in your Orkes Conductor cluster.

To create a SendGrid integration:

  1. Go to Integrations from the left navigation menu on your Conductor cluster.
  2. Select + New integration.
  3. In the Email section, choose SendGrid Email.
  4. Select + Add and enter a name for the integration, API key, and a description.
  5. Select Save.

Step 2: Create a user form in Orkes Conductor

The workflow uses a Human task in Orkes Conductor to route documents for manual approval. Reviewers can complete approvals either through the Conductor UI or an external interface, such as an internal website or document approval portal.

In this tutorial, you’ll use the Conductor UI to complete approvals. For this, a user form is to be created in Conductor.

To create a user form:

  1. Go to Definitions > User Forms from the left navigation menu on your Conductor cluster.
  2. Select + New form.
  3. In the Code tab, paste the following code:
{
"name": "Approval",
"version": 1,
"jsonSchema": {
"$schema": "http://json-schema.org/draft-07/schema",
"properties": {
"paperUrl": {
"type": "string"
},
"approve": {
"type": "string",
"enum": [
"Yes",
" No"
]
},
"comments": {
"type": "string"
}
},
"required": [
"approve",
"comments"
]
},
"templateUI": {
"type": "VerticalLayout",
"elements": [
{
"type": "VerticalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/paperUrl",
"label": "Review doc",
"options": {
"readonly": true
}
}
]
},
{
"type": "Control",
"scope": "#/properties/approve",
"label": "Approve document",
"options": {}
},
{
"type": "Control",
"scope": "#/properties/comments",
"label": "Comments"
}
]
}
}
  1. Select Save > Confirm.

Your user form looks like this:

Doc approval user form in Orkes Conductor

Step 3: Create a workflow in Orkes Conductor

Orkes Conductor lets you define workflows as JSON, through SDKs, APIs, or the UI.

To create a workflow using Conductor UI:

  1. Go to Definitions > Workflow from the left navigation menu on your Conductor cluster.
  2. Select + Define workflow.
  3. In the Code tab, paste the following code:
{
"name": "document_approval",
"description": "Workflow for document approval.",
"version": 1,
"tasks": [
{
"name": "reviewer_1",
"taskReferenceName": "reviewer_1",
"inputParameters": {
"__humanTaskDefinition": {
"assignments": [
{
"assignee": {
"user": "<REVIEWER-1>",
"userType": "CONDUCTOR_USER"
},
"slaMinutes": 1440
}
],
"assignmentCompletionStrategy": "LEAVE_OPEN",
"taskTriggers": [],
"displayName": "Reviewer 1",
"userFormTemplate": {
"name": "Approval",
"version": 1
}
},
"approve": "",
"comments": "",
"paperUrl": "${workflow.input.paperUrl}"
},
"type": "HUMAN"
},
{
"name": "reviewer_1_switch",
"taskReferenceName": "reviewer_1_switch",
"inputParameters": {
"switchCaseValue": "${reviewer_1.output.approve}"
},
"type": "SWITCH",
"decisionCases": {
"Yes": [
{
"name": "reviewer_2",
"taskReferenceName": "reviewer_2",
"inputParameters": {
"__humanTaskDefinition": {
"assignments": [
{
"assignee": {
"user": "<REVIEWER-2>",
"userType": "CONDUCTOR_USER"
},
"slaMinutes": 1440
}
],
"assignmentCompletionStrategy": "LEAVE_OPEN",
"displayName": "Reviewer2",
"userFormTemplate": {
"name": "Approval",
"version": 1
}
},
"approve": "",
"comments": "",
"paperUrl": "${workflow.input.paperUrl}"
},
"type": "HUMAN"
},
{
"name": "reviewer_2_switch",
"taskReferenceName": "reviewer_2_switch",
"inputParameters": {
"switchCaseValue": "${reviewer_2.output.approve}"
},
"type": "SWITCH",
"decisionCases": {
"Yes": [
{
"name": "send_approval_email",
"taskReferenceName": "send_approval_email",
"inputParameters": {
"from": "<SENDGRID-VERIFIED-EMAIL>",
"to": "${workflow.input.email}",
"subject": "Research Paper Approved",
"contentType": "text/plain",
"content": "Congratulations! Your Research Paper is approved.",
"sendgridConfiguration": "<SENDGRID-INTEGRATION-NAME>"
},
"type": "SENDGRID"
}
]
},
"defaultCase": [
{
"name": "sendgrid_1",
"taskReferenceName": "sendgrid_ref_1",
"inputParameters": {
"from": "<SENDGRID-VERIFIED-EMAIL>",
"to": "${workflow.input.email}",
"subject": "Research Paper Rejected",
"contentType": "text/plain",
"content": "Please revise your paper titled '${workflow.input.title}' based on the comment `${reviewer_2.output.comments}`.",
"sendgridConfiguration": "<SENDGRID-INTEGRATION-NAME>"
},
"type": "SENDGRID"
}
],
"evaluatorType": "value-param",
"expression": "switchCaseValue"
}
],
"defaultCase": [
{
"name": "send_resubmission_email_r1",
"taskReferenceName": "resubmission_email_r1",
"inputParameters": {
"from": "<SENDGRID-VERIFIED-EMAIL>",
"to": "${workflow.input.email}",
"subject": "Research Paper Rejected",
"contentType": "text/plain",
"content": "Please revise your paper titled '${workflow.input.title}' based on ${reviewer_1_output}.",
"sendgridConfiguration": "<SENDGRID-INTEGRATION-NAME>"
},
"type": "SENDGRID"
}
]
},
"defaultCase": [
{
"name": "sendgrid",
"taskReferenceName": "sendgrid_ref",
"inputParameters": {
"from": "<SENDGRID-VERIFIED-EMAIL>",
"to": "${workflow.input.email}",
"subject": "Research Paper Rejected",
"contentType": "text/plain",
"content": "Please revise your paper titled '${workflow.input.title}' based on the comment `${reviewer_1.output.comments}`.",
"sendgridConfiguration": "<SENDGRID-INTEGRATION-NAME>"
},
"type": "SENDGRID"
}
],
"evaluatorType": "value-param",
"expression": "switchCaseValue"
}
],
"inputParameters": [
"email",
"paperUrl",
"title"
],
"schemaVersion": 2
}
  1. Select Save > Confirm.

Next, replace all placeholder values with your actual reviewer information and SendGrid configuration details.

  1. Select reviewer_1 task and update the assignee to a valid Conductor user. In the Developer Edition, you’re the only available user, so assign the task to yourself. In other clusters, you can assign it to any user who has already been added to the Conductor cluster.

Updating Human task with reviewer details

  1. Similarly, select the reviewer_2 task and assign the second reviewer.
  2. Select the sendgrid task and update the following parameters:
    • Set the From email to the verified sender address configured in Step 1.
    • Set the SendGrid Configuration to the integration name created in Step 1.

Updating SendGrid task with email and integration details

  1. Update the sendgrid_1 and send_approval_email tasks with the same email and integration values.
  2. Select Save > Confirm.

Step 4: Execute workflow

To test the workflow:

  1. From your workflow definition, go to the Run tab.
  2. Set the input parameter. For example:
{
"email": "jane.doe@acme.edu",
"paperUrl": "<DOC-URL-FOR-APPROVAL>",
"title": "<PAPER-TITLE>"
}

Executing doc approval workflow

  1. Select Execute.

This initiates the workflow and takes you to the workflow execution page.

Completing the Human task

The workflow is running, and the first Human task is assigned to Reviewer 1.

Document approval workflow execution

To complete the Human tasks in the UI:

  1. Go to Executions > Human Task.
  2. Select the Task ID to view the form.
  3. Select Claim.
  4. Review the document, select approval status, and leave comments.
  5. Select Complete to submit the form.

Reviewer approving a human task

The workflow then moves to the second human task, assigned to Reviewer 2. Reviewer 2 follows the same steps to complete their review.

Workflow execution at second human task

Once Reviewer 2 approves the document, the workflow is completed, and the user receives an approval email via SendGrid.

Doc approval email received via SendGrid

If either reviewer rejects the document, the user is notified by email with the reviewer’s feedback.

Reviewer rejecting a human task

Doc rejection email received via SendGrid

Reviewer comments are passed dynamically to the email content using the Human task outputs.

//SendGrid task definition
{
"name": "sendgrid_1",
"taskReferenceName": "sendgrid_ref_1",
"inputParameters": {
"from": "<SENDGRID-VERIFIED-EMAIL>",
"to": "${workflow.input.email}",
"subject": "Research Paper Rejected",
"contentType": "text/plain",
"content": "Please revise your paper titled '${workflow.input.title}' based on the comment `${reviewer_2.output.comments}`.",
"sendgridConfiguration": "SendGrid"
},
"type": "SENDGRID",
}

This dynamic substitution ensures each user receives personalized feedback based on the reviewer’s input.

Workflow modifications

This is a basic document approval workflow with a two-step review process. You can extend it to suit your needs by:

  • Adding additional review stages.
  • Integrating any LLM for an AI-based review before human approval.
  • Adjusting the review SLA (currently set to 24 hours) to meet your specific timing requirements.
  • Configure the Human task definition with a timeoutSeconds value to enforce a task-level timeout. Additionally, set up a trigger policy in Human task so that a notification workflow is automatically started if the task times out.
  • Configuring escalations at each review level based on SLA breaches, allowing reassignment to alternate reviewers.