Skip to main content

Workflow Patterns

This guide covers common workflow patterns and how to implement them in RocketWave Pulse.

Pattern 1: Linear Pipeline

The simplest pattern - events flow through nodes in sequence.

Event → Prompt → Action

Use Cases:

  • Chatbots
  • Simple content generation
  • Data transformation and posting

workflowData Structure:

{
"nodes": {
"n1": { "entityType": "event", "name": "Entry Point", ... },
"n2": { "entityType": "prompt", "name": "Process", ... },
"n3": { "entityType": "action", "name": "Execute", ... }
},
"connectors": {
"c1": { "source": "n1", "target": "n2", "sourcePort": "out", "targetPort": "in" },
"c2": { "source": "n2", "target": "n3", "sourcePort": "out", "targetPort": "in" }
},
"workflow": {
"ref": "n1",
"children": [
{ "ref": "n2", "children": [
{ "ref": "n3", "children": [] }
]}
]
}
}

Pattern 2: True/False Branching

Route messages based on a condition evaluating to true or false.

        ┌─ [true] → Prompt → Action
Event ──┤
└─ [false] → (ignored or different processing)

Use Cases:

  • Filter valid/invalid messages
  • Premium vs free user handling
  • Feature flag routing

Event Configuration:

  • Set tfCondition to "True/False"
  • The condition evaluation determines which branch executes

workflowData Structure:

{
"nodes": {
"n1": {
"entityId": "uuid",
"name": "Check Premium User",
"entityType": "event",
"tfCondition": "True/False",
"presentation": { "type": "circle", "position": { "x": 100, "y": 200 } }
},
"n2": {
"name": "true",
"entityType": "logic-branch",
"branchValue": "true",
"presentation": { "type": "logic-branch", "position": { "x": 300, "y": 100 } }
},
"n3": {
"name": "false",
"entityType": "logic-branch",
"branchValue": "false",
"presentation": { "type": "logic-branch", "position": { "x": 300, "y": 300 } }
},
"n4": {
"entityId": "uuid",
"name": "Premium Processing",
"entityType": "prompt",
"presentation": { "type": "brain", "position": { "x": 500, "y": 100 } }
}
},
"connectors": {
"c1": { "source": "n1", "target": "n2", "sourcePort": "out", "targetPort": "in" },
"c2": { "source": "n1", "target": "n3", "sourcePort": "out", "targetPort": "in" },
"c3": { "source": "n2", "target": "n4", "sourcePort": "out", "targetPort": "in" }
},
"workflow": {
"ref": "n1",
"children": [
{ "ref": "n2", "value": "true", "children": [
{ "ref": "n4", "children": [...] }
]},
{ "ref": "n3", "value": "false", "children": [] }
]
}
}

Key Points:

  • Logic branch nodes have entityType: "logic-branch" and a branchValue
  • The workflow ref tree must include value properties on branch children
  • Both branches can connect to subsequent nodes or be left empty

Pattern 3: Multi-Value Routing

Route based on a specific field value (like a switch statement).

              ┌─ [admin] → Admin Handler

Event ────────┼─ [user] → User Handler

└─ [guest] → Guest Handler

Use Cases:

  • Role-based processing
  • Event type routing
  • Category-specific handling

Event Configuration:

  • Set tfCondition to "Multi"
  • Set logicField to the field to switch on (e.g., "userRole")

workflowData Structure:

{
"nodes": {
"n1": {
"entityId": "uuid",
"name": "Route by Role",
"entityType": "event",
"tfCondition": "Multi",
"logicField": "userRole",
"presentation": { "type": "circle", "position": { "x": 100, "y": 250 } }
},
"n2": {
"name": "admin",
"entityType": "logic-branch",
"branchValue": "admin",
"presentation": { "type": "logic-branch", "position": { "x": 300, "y": 100 } }
},
"n3": {
"name": "user",
"entityType": "logic-branch",
"branchValue": "user",
"presentation": { "type": "logic-branch", "position": { "x": 300, "y": 250 } }
},
"n4": {
"name": "guest",
"entityType": "logic-branch",
"branchValue": "guest",
"presentation": { "type": "logic-branch", "position": { "x": 300, "y": 400 } }
}
},
"workflow": {
"ref": "n1",
"children": [
{ "ref": "n2", "value": "admin", "children": [...] },
{ "ref": "n3", "value": "user", "children": [...] },
{ "ref": "n4", "value": "guest", "children": [...] }
]
}
}

Pattern 3.5: Iterable Processing (Loop Pattern)

Process each item in an array field separately, repeating the workflow for each element.

                    ┌─ iteration 1 → Prompt → Action

Event ──[array]─────┼─ iteration 2 → Prompt → Action
(Iterable) │
└─ iteration N → Prompt → Action

Use Cases:

  • Batch notifications (send to multiple recipients)
  • Processing list items (multiple products in an order)
  • Multi-target publishing (post to multiple social accounts)
  • Parallel-like execution over array data

Event Configuration:

  • Set tfCondition to "Iterable"
  • Set logicField to the array field path (e.g., "message.recipients")

workflowData Structure:

{
"nodes": {
"n1": {
"entityId": "uuid",
"name": "Process Each Order Item",
"entityType": "event",
"tfCondition": "Iterable",
"logicField": "message.items",
"presentation": { "type": "circle", "position": { "x": 100, "y": 200 } }
},
"n2": {
"entityId": "uuid",
"name": "Generate Item Description",
"entityType": "prompt",
"presentation": { "type": "brain", "position": { "x": 350, "y": 200 } }
},
"n3": {
"entityId": "uuid",
"name": "Store Item Result",
"entityType": "action",
"presentation": { "type": "star", "position": { "x": 600, "y": 200 } }
}
},
"connectors": {
"c1": { "source": "n1", "target": "n2", "sourcePort": "out", "targetPort": "in" },
"c2": { "source": "n2", "target": "n3", "sourcePort": "out", "targetPort": "in" }
},
"workflow": {
"ref": "n1",
"children": [
{ "ref": "n2", "children": [
{ "ref": "n3", "children": [] }
]}
]
}
}

Accessing Iterable Items:

In downstream scripts (Prompts, Actions), access the current item:

// Current iteration item
const currentItem = ___iterableItem___;

// Example: if iterating over message.recipients
const recipientEmail = currentItem.email;
const recipientName = currentItem.name;

print('Processing recipient:', recipientName);

Real-World Example: Multi-Recipient Notification

{
"name": "Send Team Notifications",
"tfCondition": "Iterable",
"logicField": "message.team.members",
"condition": {
"type": "group",
"operator": "AND",
"conditions": [
{ "type": "rule", "field": "message.type", "comparison": "equals", "value": "announcement" }
]
}
}

Given this input message:

{
"type": "announcement",
"content": "Team meeting at 3pm",
"team": {
"members": [
{ "name": "Alice", "email": "alice@example.com" },
{ "name": "Bob", "email": "bob@example.com" },
{ "name": "Charlie", "email": "charlie@example.com" }
]
}
}

The workflow executes 3 times, once for each team member.


Pattern 4: Sequential Processing

Chain multiple AI calls or actions in sequence.

Event → Prompt (Summarize) → Prompt (Translate) → Action (Store)

Use Cases:

  • Multi-step AI processing
  • Data enrichment pipelines
  • Content moderation + generation

Accessing Previous Responses:

// In Action script after multiple prompts
const firstResponse = await getPromptResponse(1); // First prompt result
const secondResponse = await getPromptResponse(2); // Second prompt result
const latestResponse = await latestPromptResponse(); // Same as getPromptResponse(2)

print('Summary:', firstResponse);
print('Translation:', secondResponse);

Pattern 5: Fan-Out / Parallel (via Multiple Connectors)

Process the same event through multiple branches simultaneously.

        ┌─ Action (Post to Twitter)
Event ──┼─ Action (Post to Mastodon)
└─ Action (Store in S3)

Note: In the current architecture, this is achieved by having multiple children in the workflow tree. The consumer processes them in sequence but each branch is independent.


Pattern 6: Conditional Error Handling

Use branching to handle success and error cases differently.

                    ┌─ [true] → Action (Post)
Event → Prompt ─────┤
└─ [false] → Action (Log Error)

Implementation:

  1. After the Prompt, add an Event that checks if the response is valid
  2. Branch based on validation result
  3. Use try/catch in scripts for graceful error handling

Building Workflows via API

When creating workflows programmatically, you need:

1. Create the Entities First

// Create Event entity
const event = await fetch('/api/workflow-entities', {
method: 'POST',
body: JSON.stringify({
organizationId: 'org-uuid',
environmentId: 'env-uuid',
name: 'My Event',
workflowEntityTypeId: 'event-type-uuid',
condition: { type: 'group', operator: 'AND', conditions: [...] }
})
});

2. Create the Workflow with workflowData

const workflow = await fetch('/api/workflows', {
method: 'POST',
body: JSON.stringify({
organizationId: 'org-uuid',
environmentId: 'env-uuid',
name: 'My Workflow',
description: 'Workflow description',
isActive: true,
workflowData: {
nodes: {
n1: { entityId: event.id, name: 'My Event', entityType: 'event', ... }
},
connectors: { ... },
workflow: { ref: 'n1', children: [...] }
}
})
});

Node Types and Shapes

Entity TypePresentation TypeVisual
eventcircle
promptbrain🧠
actionstar
logic-branchlogic-branch

Workflow Outcomes

Workflow outcomes are determined automatically based on execution:

OutcomeWhen it occurs
SuccessAll entities execute without errors
ErrorA script throws an error or times out
IgnoreEvent condition doesn't match

Best Practices

  1. Start Simple - Begin with a linear pipeline, add branching as needed
  2. Name Descriptively - Use clear names like "Check Premium Status" not "Event 1"
  3. One Responsibility - Each node should do one thing well
  4. Handle Both Branches - True/False events should have handlers for both cases
  5. Use Error Handling - Wrap risky operations in try/catch blocks
  6. Test Incrementally - Verify each node works before adding the next