API reference
iterateOnce() — Workflow Service
Purpose : Administrator only step: advances a workflow instance by exactly one activity and stops, returning the full live instance. When to use : Debug…
@gsb-core/mcp-docs:iterateOnce General Description
The iterateOnce operation advances a workflow instance by exactly one activity and then stops. It is the stepper: the call a workflow builder uses to walk a design activity by activity while debugging.
Detailed Description
iterateOnce posts to /api/workflow/iterateOnce and is administrator-only. It takes the same instance input as startWorkflow and runWorkflow, performs a single activity, and answers with the instance as it now stands.
The three ways a parked run can move differ only in where they stop:
| Operation | Caller | Stops |
|---|---|---|
| iterateOnce | administrator | after one activity |
| iterateTask | integration or server function | when the run finishes or parks again |
| submitWorkflowTask | the task's assignee | when the run finishes or parks again |
iterateOnce is intended to clear a user task and halt on the next activity. The exact
outcome selector remains contract-gated: live dev1 task creation is verified, but result label,
transition id, and configured activity-result id were all rejected by the current engine. Do not
claim successful task completion until the backend publishes and verifies that selector.
Input Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| request | object | Yes | The step request, forwarded to the backend without transformation. |
| token | string | No | Authentication token for the request. Falls back to the configured credentials when omitted. |
| tenantCode | string | No | Tenant whose data to operate on. Falls back to the tenant encoded in the token or the configured tenant. |
Request Object Structure
| Property | Type | Required | Description |
|---|---|---|---|
| instance | object | Yes | The workflow instance to step. |
| instance.workflow_id | string | Yes | Id of the GsbWorkflow. The step resolves the definition from the instance payload, so this must be present on every call — including calls that resume an existing instance. |
| instance.id | string | No | Id of an existing instance. Omit it to step a fresh run from its start activity. |
| instance.entity_id | string | No | Id of the entity the run operates on. |
| instance.entityDefinition_id | string | No | GsbEntityDef id of that entity. |
| instance.entity | object | No | Entity payload for a run that has no stored row yet. |
| instance.parameters | string | No | Instance parameters. This is a string column; sending an object fails the whole call. |
When resuming, send the instance the previous step returned, with workflow_id set. Preserve
the returned currentTask envelope; sending only currentTask_id creates another task instead
of submitting the existing one on the current dev1 engine.
Response
The response body carries the live instance, which is richer than a GsbWorkflowInstance row read back by query:
{
"instance": {
"id": "string",
"workflow_id": "string",
"activity_id": "string",
"parentActivity_id": "string",
"parent_id": "string",
"entity_id": "string",
"entityDefinition_id": "string",
"starter_id": "string",
"lastProcessor_id": "string",
"locker_id": "string",
"name": "string",
"title": "string",
"message": "string",
"result": "string",
"parameters": "string",
"status": 0,
"trigger": {},
"followers": [],
"currentTask": {},
"continiumChecked": false
},
"status": 200
}
| Field | What it answers |
|---|---|
activity_id |
where the run is now |
result |
what was selected on the activity just performed |
currentTask |
the task to submit if the run parked on a person |
lastProcessor_id |
who moved it |
locker_id |
what is holding it |
message |
why it stopped, including failure text a function set |
parent_id, parentActivity_id |
the parent run and activity when this is a sub-flow |
status |
bit field: OnHold 1, Started 2, Completed 4, Cancelled 8, ReAssigned 16, Error 32 |
Administrators receive this same envelope from runWorkflow, startWorkflow, iterateTask and submitWorkflowTask. A non-administrator receives only what their permissions allow, so a client must tolerate a thinner response.
parameters can hold credentials and personal data. Do not log it and do not display it without an explicit reveal.
Example Usage
Step a run one activity at a time
let instance = { workflow_id: workflowId, entity: { employeeId: "emp-42" } };
for (;;) {
const step = await entityService.iterateOnce({ instance }, token, tenantCode);
instance = { ...step.instance, workflow_id: workflowId };
if ((instance.status & (4 | 8 | 32)) !== 0) break; // Completed, Cancelled or Error
if (instance.currentTask) break; // parked on a person
}
Step through a user task
const step = await entityService.iterateOnce(
{ instance: { ...instance, workflow_id: workflowId, /* task outcome */ } },
token,
tenantCode,
);
The run continues to the next activity and halts there, rather than running to completion.
Additional Information
- Omitting
instance.workflow_idis the difference between a step and a rejected call. - Step-by-step traces are also written to
GsbWfLog, but only when the workflow'senableLogflag is on. With it off a healthy run records nothing. - This operation is an external side effect on live data. It is disabled by default and requires explicit approval before it can be invoked through the CLI or an MCP client.