nocobase-workflow

Guide AI to create NocoBase workflows — triggers, conditions, data operations, SQL, scheduling

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "nocobase-workflow" with this command: npx skills add alexander-lq/work-fllows

NocoBase Workflow Building

You are guiding the user to create automated workflows in NocoBase.

Key Concepts

Trigger Types

TypeDescriptionMode
collectionData change trigger1=create, 2=update, 3=create+update, 4=delete
scheduleTime-based trigger0=cron, 1=date field
actionManual button trigger

Node Types

TypeDescription
conditionIf/else branch (basic engine or math.js)
updateUpdate existing records
createCreate new records
queryQuery records for use in downstream nodes
sqlExecute raw SQL
requestHTTP request (webhooks, external APIs)
loopIterate over array data
endTerminate workflow (1=success, 0=failure)

Node Linking Model

  • Nodes form a linked list: upstreamIddownstreamId
  • Branch nodes (condition, loop) use branchIndex:
    • 1 = true branch (condition) or loop body (loop)
    • 0 = false branch (condition)
    • null = main line continuation

Variable System

VariableDescription
{{$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

Workflow Patterns

Pattern 1: Auto-numbering (on create)

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)

Pattern 2: Status Sync (on create)

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)

Pattern 3: Conditional Branch (on create)

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)

Pattern 4: Field Change Trigger (on update)

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)

Pattern 5: Date-based Schedule

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)

Pattern 6: Cron Schedule

# 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"}')

Pattern 7: Multi-node Chain

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)

Workflow

Phase 1: Plan

Before creating workflows, identify:

  1. Trigger: What event starts the workflow? (record created/updated/deleted, schedule, manual)
  2. Collection: Which table triggers it?
  3. Logic: What conditions and actions are needed?
  4. Target: What data gets modified?

Phase 2: Create

  1. Create workflow with trigger config
  2. Add nodes in order (first node auto-links, subsequent need upstream_id)
  3. For branches: add condition node, then true/false branch nodes with branch_index

Phase 3: Enable & Verify

  1. Enable the workflow
  2. List workflows to confirm: nb_list_workflows()
  3. Inspect with: nb_get_workflow(wf_id)

Best Practices

  1. Title convention: Use prefixes for grouping, e.g. "AM-WF01 Auto Number"
  2. One workflow per concern: Don't combine unrelated logic
  3. Idempotent SQL: Write SQL that's safe to run multiple times
  4. Test before enable: Create all nodes first, then enable
  5. Batch cleanup: Use nb_delete_workflows_by_prefix("AM-") to clean up
  6. Duplicate prevention: Check nb_list_workflows() before creating — duplicate titles cause confusion
  7. Variable references: Always use double braces {{$context.data.field}} — single braces won't work

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

Hermes Tweet

Use Xquik from Hermes Agent for X search, posting, replies, likes, retweets, follows, DMs, monitors, extraction jobs, draws, media, and trends.

Registry SourceRecently Updated
Automation

EVK Live Borrow Proof

Prove that a deployed Euler EVK market can really borrow against the intended collateral path with tiny live canaries or dry-run previews. Use when an agent...

Registry SourceRecently Updated
Automation

Agentic Lending Morpho

Plan and execute the Morpho-first agentic lending workflow for Api3-backed markets. Use when a user wants a Morpho market or market set for selected collater...

Registry SourceRecently Updated
Automation

Agentic Lending EVK

Plan and execute the current EVK-first agentic lending workflow for Api3-backed markets. Use when a user wants an agent to resolve the oracle route for selec...

Registry SourceRecently Updated
2320daav3