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:
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:
- Go to Integrations from the left navigation menu on your Conductor cluster.
- Select + New integration.
- In the Email section, choose SendGrid Email.
- Select + Add and enter a name for the integration, API key, and a description.
- 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:
- Go to Definitions > User Forms from the left navigation menu on your Conductor cluster.
- Select + New form.
- 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"
}
]
}
}
- Select Save > Confirm.
Your user form looks like this:
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:
- Go to Definitions > Workflow from the left navigation menu on your Conductor cluster.
- Select + Define workflow.
- 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
}
- Select Save > Confirm.
Next, replace all placeholder values with your actual reviewer information and SendGrid configuration details.
- 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.
- Similarly, select the reviewer_2 task and assign the second reviewer.
- Select the sendgrid task and update the following parameters:
- Update the sendgrid_1 and send_approval_email tasks with the same email and integration values.
- Select Save > Confirm.
Step 4: Execute workflow
To test the workflow:
- From your workflow definition, go to the Run tab.
- Set the input parameter. For example:
{
"email": "jane.doe@acme.edu",
"paperUrl": "<DOC-URL-FOR-APPROVAL>",
"title": "<PAPER-TITLE>"
}
- 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.
To complete the Human tasks in the UI:
- Go to Executions > Human Task.
- Select the Task ID to view the form.
- Select Claim.
- Review the document, select approval status, and leave comments.
- Select Complete to submit the form.
The workflow then moves to the second human task, assigned to Reviewer 2. Reviewer 2 follows the same steps to complete their review.
Once Reviewer 2 approves the document, the workflow is completed, and the user receives an approval email via SendGrid.
If either reviewer rejects the document, the user is notified by email with the reviewer’s feedback.
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.