Skip to main content

Step Backward

Overview

The StepBackwardCommand moves back to the previous task in a process running in Supervised Mode. This allows reviewing previous task results and revisiting earlier steps during debugging or inspection.

Supervised Mode Only

This command only works for processes started with executionMode: "Supervised". Unsupervised processes execute automatically and cannot step backward.

API Endpoint

POST /api/core/cmd

Headers

Content-Type: application/json
Authorization: Bearer {access_token}
X-Tenant-ID: {tenant_id}

Request Structure

{
"cmd": "StepBackwardCommand",
"data": {
"instanceGuid": "abc-123-def-456"
}
}

Request Fields

FieldTypeRequiredDescription
instanceGuidstringYesThe unique identifier of the supervised process instance

When to Use

  • Review Previous Task: Inspect what the previous task did
  • Verify Logic: Check task outputs before proceeding
  • Debug Issues: Go back to see where an error occurred
  • Training: Demonstrate workflow navigation

Sample Requests

1. Step Back to Previous Task

{
"cmd": "StepBackwardCommand",
"data": {
"instanceGuid": "loan-approval-supervised-001"
}
}

2. Review Earlier Task Results

{
"cmd": "StepBackwardCommand",
"data": {
"instanceGuid": "test-workflow-debug-789"
}
}

Response Structure

Stepped Back Successfully

{
"isSuccessful": true,
"message": "Stepped back to previous task successfully",
"statusCode": "00",
"data": {
"instanceGuid": "loan-approval-supervised-001",
"status": "waiting",
"currentActivityId": "Task_ValidateCustomer",
"executionMode": "Supervised",
"movedFrom": {
"taskId": "Task_CreditCheck",
"taskName": "Perform Credit Check"
},
"currentTask": {
"taskId": "Task_ValidateCustomer",
"taskName": "Validate Customer Information",
"taskType": "ServiceTask",
"previousExecution": {
"executedAt": "2024-12-19T10:30:15Z",
"executionTime": "1.2s",
"success": true
}
},
"state": {
"variables": {
"customerId": 123,
"customerName": "John Doe",
"validationStatus": "passed"
},
"completedTasks": ["StartEvent", "Task_ValidateCustomer"],
"currentNode": "Task_ValidateCustomer",
"reviewMode": true
},
"nextActions": [
{
"action": "stepForward",
"label": "Continue Forward",
"command": "StepForwardCommand",
"description": "Execute the next task"
},
{
"action": "stepBackward",
"label": "Go Back Further",
"command": "StepBackwardCommand",
"enabled": true
},
{
"action": "cancel",
"label": "Cancel Process",
"command": "CancelProcessInstanceCommand"
}
]
}
}

At Start of Process (Cannot Go Back)

{
"isSuccessful": false,
"message": "Already at the beginning of the process. Cannot step backward.",
"statusCode": "99",
"data": {
"instanceGuid": "loan-approval-supervised-001",
"status": "waiting",
"currentActivityId": "StartEvent",
"position": "start"
}
}

Error Responses

Process Not in Supervised Mode

{
"isSuccessful": false,
"message": "Process is not running in Supervised mode",
"statusCode": "99",
"data": {
"currentMode": "Unsupervised"
}
}

Process Not Found

{
"isSuccessful": false,
"message": "Process instance 'invalid-guid' not found.",
"statusCode": "99",
"data": null
}

Use Cases

1. Review Task Execution History

// Step through process, then review
await stepForward(instanceGuid); // Execute Task 1
await stepForward(instanceGuid); // Execute Task 2
await stepForward(instanceGuid); // Execute Task 3

// Oops, want to check Task 2 results
const response = await stepBackward(instanceGuid);

console.log("Previous Task:", response.data.currentTask);
console.log("Task Results:", response.data.state.variables);
console.log("Execution Time:", response.data.currentTask.previousExecution.executionTime);

2. Debug Workflow Issues

// Execute until error
let response;
do {
response = await stepForward(instanceGuid);
} while (response.data.status === "waiting");

if (response.data.status === "error") {
console.error("Error at:", response.data.error.taskName);

// Step back to see what led to the error
const previousResponse = await stepBackward(instanceGuid);
console.log("Previous task state:", previousResponse.data.state.variables);

// Step back again to check earlier state
const earlierResponse = await stepBackward(instanceGuid);
console.log("Earlier state:", earlierResponse.data.state.variables);
}

3. Interactive Workflow Navigator

class WorkflowNavigator {
constructor(instanceGuid) {
this.instanceGuid = instanceGuid;
this.history = [];
}

async forward() {
const response = await stepForward(this.instanceGuid);
if (response.isSuccessful && response.data.previousTask) {
this.history.push(response.data.previousTask);
}
return response;
}

async backward() {
const response = await stepBackward(this.instanceGuid);
if (response.isSuccessful && this.history.length > 0) {
this.history.pop();
}
return response;
}

canGoBack() {
return this.history.length > 0;
}

getHistory() {
return this.history;
}
}

// Usage
const navigator = new WorkflowNavigator("test-process-001");
await navigator.forward(); // Execute task 1
await navigator.forward(); // Execute task 2
await navigator.backward(); // Review task 1
await navigator.forward(); // Move forward again

4. Verify Variable Changes

// Capture variables at each step
const variableHistory = [];

// Step forward and capture
let response = await stepForward(instanceGuid);
variableHistory.push({ ...response.data.state.variables });

response = await stepForward(instanceGuid);
variableHistory.push({ ...response.data.state.variables });

// Step back and compare
response = await stepBackward(instanceGuid);
const currentVars = response.data.state.variables;
const previousVars = variableHistory[variableHistory.length - 2];

console.log("Variable changes:");
for (const key in currentVars) {
if (currentVars[key] !== previousVars?.[key]) {
console.log(`${key}: ${previousVars?.[key]}${currentVars[key]}`);
}
}

Important Behaviors

1. Review Mode vs Re-Execution

When you step backward, you are reviewing the previous task, not re-executing it:

// Initial execution
await stepForward(instanceGuid); // Task_CreditCheck executes, adds creditScore

// Step backward
await stepBackward(instanceGuid); // Back to Task_ValidateCustomer (review only)

// Step forward again
await stepForward(instanceGuid); // Moves to Task_CreditCheck (already executed)

Note: Variables set by previously executed tasks remain in the context.

2. Cannot Step Back from Start

const response = await stepBackward(instanceGuid);

if (!response.isSuccessful && response.data?.position === "start") {
console.log("Already at the beginning of the process");
// Disable backward navigation button in UI
}

3. Stepping Backward Multiple Times

// You can step back multiple times
await stepBackward(instanceGuid); // Back one step
await stepBackward(instanceGuid); // Back another step
await stepBackward(instanceGuid); // Back to start (if possible)

Best Practices

1. Track Navigation Position

class ProcessPosition {
constructor() {
this.position = 0;
this.maxPosition = 0;
}

async stepForward(instanceGuid) {
const response = await stepForward(instanceGuid);
if (response.isSuccessful) {
this.position++;
this.maxPosition = Math.max(this.maxPosition, this.position);
}
return response;
}

async stepBackward(instanceGuid) {
const response = await stepBackward(instanceGuid);
if (response.isSuccessful) {
this.position--;
}
return response;
}

canGoBack() {
return this.position > 0;
}

canGoForward() {
return this.position < this.maxPosition;
}
}

2. Disable Navigation When Appropriate

function updateNavigationButtons(response) {
const canGoBack = response.data.nextActions.some(
action => action.action === "stepBackward" && action.enabled !== false
);

document.getElementById("backButton").disabled = !canGoBack;

const atEnd = response.data.status === "completed";
document.getElementById("forwardButton").disabled = atEnd;
}

3. Show Execution History in UI

function displayExecutionHistory(completedTasks) {
return completedTasks.map((task, index) => ({
step: index + 1,
taskName: task.taskName || task,
status: "✓ Completed",
canReview: true
}));
}

// When stepping backward, highlight the current task
function highlightCurrentTask(currentTaskId, history) {
return history.map(task => ({
...task,
current: task.taskId === currentTaskId
}));
}

4. Preserve Context When Navigating

// Even when stepping backward, preserve important context
async function navigateWithContext(direction, instanceGuid, userNotes) {
const metadata = {
userNotes: userNotes,
navigationTime: new Date().toISOString(),
direction: direction
};

// Store metadata for audit
await logNavigation(instanceGuid, metadata);

// Perform navigation
if (direction === "forward") {
return await stepForward(instanceGuid);
} else {
return await stepBackward(instanceGuid);
}
}

Comparison: Step Forward vs Step Backward

AspectStep ForwardStep Backward
DirectionExecutes next taskReviews previous task
ExecutionRuns task logicNo re-execution (review only)
VariablesUpdates contextContext remains unchanged
Use CaseProgress workflowReview/debug previous steps
LimitStops at endStops at start
ModeSupervised onlySupervised only

Notes

  • Only works with processes in Supervised mode
  • Stepping backward does NOT re-execute tasks
  • Variables set by previously executed tasks are preserved
  • Cannot step backward beyond the start of the process
  • Useful for reviewing task execution history
  • Does not affect the process state or variables
  • The reviewMode flag indicates you're reviewing a previous task
  • Multiple backward steps are allowed until reaching the start
  • Step forward after stepping backward continues from where you left off
  • All navigation is logged for audit purposes