Guide AI to create NocoBase workflows — triggers, conditions, data operations, SQL, scheduling
You are guiding the user to create automated workflows in NocoBase.
| Type | Description | Mode |
|---|---|---|
collection | Data change trigger | 1=create, 2=update, 3=create+update, 4=delete |
schedule | Time-based trigger | 0=cron, 1=date field |
action | Manual button trigger | — |
| Type | Description |
|---|---|
condition | If/else branch (basic engine or math.js) |
update | Update existing records |
create | Create new records |
query | Query records for use in downstream nodes |
sql | Execute raw SQL |
request | HTTP request (webhooks, external APIs) |
loop | Iterate over array data |
end | Terminate workflow (1=success, 0=failure) |
upstreamId → downstreamIdbranchIndex:
1 = true branch (condition) or loop body (loop)0 = false branch (condition)null = main line continuation| Variable | Description |
|---|---|
{{$context.data.field}} | Field from the trigger record |
{{$context.data.id}} | ID of the trigger record |
{{$jobsMapByNodeKey.<key>.field}} | Result from a previous node |
{{$scopes.<key>.item}} | Current item in a loop |
Generate sequential IDs like PR-2026-001:
# Step 1: Create workflow
nb_create_workflow("Auto Purchase Number", "collection",
'{"mode": 1, "collection": "purchase_requests", "appends": [], "condition": {"$and": []}}')
# Step 2: Add SQL node
nb_add_node(wf_id, "sql", "Generate Number",
'{"dataSource": "main", "sql": "UPDATE purchase_requests SET request_no = \'PR-\' || TO_CHAR(NOW(), \'YYYY\') || \'-\' || LPAD((SELECT COALESCE(MAX(CAST(SUBSTRING(request_no FROM \'[0-9]+$\') AS INT)),0)+1 FROM purchase_requests WHERE request_no LIKE \'PR-\' || TO_CHAR(NOW(), \'YYYY\') || \'-%\')::TEXT, 3, \'0\') WHERE id = {{$context.data.id}}"}')
# Step 3: Enable
nb_enable_workflow(wf_id)
Set default status when a record is created:
nb_create_workflow("Default Status", "collection",
'{"mode": 1, "collection": "orders", "appends": [], "condition": {"$and": []}}')
nb_add_node(wf_id, "update", "Set Draft Status",
'{"collection": "orders", "params": {"filter": {"id": "{{$context.data.id}}"}, "values": {"status": "draft"}}}')
nb_enable_workflow(wf_id)
Different actions based on field value:
nb_create_workflow("Transfer Type Handler", "collection",
'{"mode": 1, "collection": "transfers", "appends": [], "condition": {"$and": []}}')
# Condition node
cond = nb_add_node(wf_id, "condition", "Is Transfer?",
'{"rejectOnFalse": false, "engine": "basic", "calculation": {"group": {"type": "and", "calculations": [{"calculator": "equal", "operands": ["{{$context.data.type}}", "transfer"]}]}}}')
# True branch: update status to "transferred"
nb_add_node(wf_id, "update", "Mark Transferred",
'{"collection": "assets", "params": {"filter": {"id": "{{$context.data.asset_id}}"}, "values": {"status": "transferred"}}}',
upstream_id=cond_id, branch_index=1)
# False branch: update status to "borrowed"
nb_add_node(wf_id, "update", "Mark Borrowed",
'{"collection": "assets", "params": {"filter": {"id": "{{$context.data.asset_id}}"}, "values": {"status": "borrowed"}}}',
upstream_id=cond_id, branch_index=0)
nb_enable_workflow(wf_id)
React when specific fields change:
nb_create_workflow("Disposal Complete", "collection",
'{"mode": 2, "collection": "disposals", "changed": ["status"], "condition": {"status": {"$eq": "disposed"}}, "appends": []}')
nb_add_node(wf_id, "update", "Update Asset Status",
'{"collection": "assets", "params": {"filter": {"id": "{{$context.data.asset_id}}"}, "values": {"status": "disposed"}}}')
nb_enable_workflow(wf_id)
Trigger N days before a date field:
# Trigger 30 days before insurance expiry
nb_create_workflow("Insurance Expiry Warning", "schedule",
'{"mode": 1, "collection": "insurance", "startsOn": {"field": "end_date", "offset": -30, "unit": 86400000}, "repeat": null, "appends": []}')
nb_add_node(wf_id, "sql", "Mark Expiring",
'{"dataSource": "main", "sql": "UPDATE insurance SET remark = \'expiring soon\' WHERE id = {{$context.data.id}}"}')
nb_enable_workflow(wf_id)
# Run every weekday at 9 AM
nb_create_workflow("Daily Report", "schedule",
'{"mode": 0, "startsOn": "2026-01-01T00:00:00.000Z", "repeat": "0 9 * * 1-5"}')
Chain multiple nodes on the main line:
nb_create_workflow("Complex Flow", "collection",
'{"mode": 1, "collection": "orders", "appends": [], "condition": {"$and": []}}')
# Node 1 (first node, no upstream_id needed)
n1 = nb_add_node(wf_id, "query", "Get Customer",
'{"collection": "customers", "multiple": false, "params": {"filter": {"id": "{{$context.data.customer_id}}"}}}')
# Node 2 (chains after node 1)
n2 = nb_add_node(wf_id, "update", "Update Order",
'{"collection": "orders", "params": {"filter": {"id": "{{$context.data.id}}"}, "values": {"customer_name": "{{$jobsMapByNodeKey.NODE_KEY.name}}"}}}',
upstream_id=n1_id)
nb_enable_workflow(wf_id)
Before creating workflows, identify:
upstream_id)branch_indexnb_list_workflows()nb_get_workflow(wf_id)nb_delete_workflows_by_prefix("AM-") to clean upnb_list_workflows() before creating — duplicate titles cause confusion{{$context.data.field}} — single braces won't work