diff --git a/apps/docs/content/docs/en/blocks/index.mdx b/apps/docs/content/docs/en/blocks/index.mdx index a2cfce6028..8feeb95d35 100644 --- a/apps/docs/content/docs/en/blocks/index.mdx +++ b/apps/docs/content/docs/en/blocks/index.mdx @@ -16,7 +16,7 @@ Blocks are the building components you connect together to create AI workflows. ## Core Block Types -Sim provides seven core block types that handle the essential functions of AI workflows: +Sim provides essential block types that handle the core functions of AI workflows: ### Processing Blocks - **[Agent](/blocks/agent)** - Chat with AI models (OpenAI, Anthropic, Google, local models) @@ -28,6 +28,10 @@ Sim provides seven core block types that handle the essential functions of AI wo - **[Router](/blocks/router)** - Use AI to intelligently route requests to different paths - **[Evaluator](/blocks/evaluator)** - Score and assess content quality using AI +### Control Flow Blocks +- **[Variables](/blocks/variables)** - Set and manage workflow-scoped variables +- **[Wait](/blocks/wait)** - Pause workflow execution for a specified time delay + ### Output Blocks - **[Response](/blocks/response)** - Format and return final results from your workflow @@ -123,4 +127,10 @@ Each block type has specific configuration options: Create branching logic based on data evaluation + + Set and manage workflow-scoped variables + + + Pause workflow execution for specified time delays + diff --git a/apps/docs/content/docs/en/blocks/loop.mdx b/apps/docs/content/docs/en/blocks/loop.mdx index 7d5a47c0bd..eae2423a9b 100644 --- a/apps/docs/content/docs/en/blocks/loop.mdx +++ b/apps/docs/content/docs/en/blocks/loop.mdx @@ -9,7 +9,7 @@ import { Image } from '@/components/ui/image' The Loop block is a container block in Sim that allows you to create iterative workflows by executing a group of blocks repeatedly. Loops enable iterative processing in your workflows. -The Loop block supports two types of iteration: +The Loop block supports four types of iteration: Loop blocks are container nodes that can hold other blocks inside them. The blocks inside a loop will execute multiple times based on your configuration. @@ -27,7 +27,7 @@ The Loop block enables you to: Repeat operations: Execute blocks a fixed number of times - Sequential processing: Handle data transformation in ordered iterations + Loop on conditions: Continue executing while or until a condition is met Aggregate results: Collect outputs from all loop iterations @@ -47,9 +47,9 @@ The Loop block executes contained blocks through sequential iteration: ### Loop Type -Choose between two types of loops: +Choose between four types of loops: - + **For Loop (Iterations)** - A numeric loop that executes a fixed number of times: @@ -96,6 +96,54 @@ Choose between two types of loops: - Iteration 3: Process "orange" ``` + + **While Loop (Condition-based)** - Continues executing while a condition evaluates to true: + +
+ While Loop with condition +
+ + Use this when you need to loop until a specific condition is met. The condition is checked **before** each iteration. + + ``` + Example: While < 10 + - Check condition → Execute if true + - Inside loop: Increment + - Inside loop: Variables assigns i = + 1 + - Check condition → Execute if true + - Check condition → Exit if false + ``` +
+ + **Do-While Loop (Condition-based)** - Executes at least once, then continues while a condition is true: + +
+ Do-While Loop with condition +
+ + Use this when you need to execute at least once, then loop until a condition is met. The condition is checked **after** each iteration. + + ``` + Example: Do-while < 10 + - Execute blocks + - Inside loop: Increment + - Inside loop: Variables assigns i = + 1 + - Check condition → Continue if true + - Check condition → Exit if false + ``` +
## How to Use Loops @@ -139,6 +187,19 @@ After a loop completes, you can access aggregated results: +### Counter with While Loop + +
+

Scenario: Process items with counter-based loop

+
    +
  1. Initialize workflow variable: `i = 0`
  2. +
  3. While loop with condition: `` \< 10
  4. +
  5. Inside loop: Agent processes item at index ``
  6. +
  7. Inside loop: Variables increments `i = + 1`
  8. +
  9. Loop continues while i is less than 10
  10. +
+
+ ## Advanced Features ### Limitations @@ -162,7 +223,7 @@ After a loop completes, you can access aggregated results:
  • - Loop Type: Choose between 'for' or 'forEach' + Loop Type: Choose between 'for', 'forEach', 'while', or 'doWhile'
  • Iterations: Number of times to execute (for loops) @@ -170,6 +231,9 @@ After a loop completes, you can access aggregated results:
  • Collection: Array or object to iterate over (forEach loops)
  • +
  • + Condition: Boolean expression to evaluate (while/do-while loops) +
diff --git a/apps/docs/content/docs/en/blocks/meta.json b/apps/docs/content/docs/en/blocks/meta.json index f0079ce068..d20f2d81ad 100644 --- a/apps/docs/content/docs/en/blocks/meta.json +++ b/apps/docs/content/docs/en/blocks/meta.json @@ -11,6 +11,8 @@ "parallel", "response", "router", + "variables", + "wait", "workflow" ] } diff --git a/apps/docs/content/docs/en/blocks/variables.mdx b/apps/docs/content/docs/en/blocks/variables.mdx new file mode 100644 index 0000000000..a74000e851 --- /dev/null +++ b/apps/docs/content/docs/en/blocks/variables.mdx @@ -0,0 +1,123 @@ +--- +title: Variables +--- + +import { Callout } from 'fumadocs-ui/components/callout' +import { Step, Steps } from 'fumadocs-ui/components/steps' +import { Image } from '@/components/ui/image' + +The Variables block updates workflow variables during execution. Variables must first be initialized in your workflow's Variables section, then you can use this block to update their values as your workflow runs. + +
+ Variables Block +
+ + + Access variables anywhere in your workflow using `` syntax. + + +## Overview + +The Variables block enables you to: + + + + Update workflow variables: Change variable values during execution + + + Store dynamic data: Capture block outputs into variables + + + Maintain state: Track counters, flags, and intermediate results + + + +## How to Use Variables + +### 1. Initialize in Workflow Variables + +First, create your variables in the workflow's Variables section (accessible from the workflow settings): + +``` +customerEmail = "" +retryCount = 0 +currentStatus = "pending" +``` + +### 2. Update with Variables Block + +Use the Variables block to update these values during execution: + +``` +customerEmail = +retryCount = + 1 +currentStatus = "processing" +``` + +### 3. Access Anywhere + +Reference variables in any block: + +``` +Agent prompt: "Send email to " +Condition: < 5 +API body: {"status": ""} +``` + +## Example Use Cases + +### Loop Counter and State + +
+

Scenario: Track progress through loop iterations

+
    +
  1. Initialize in workflow: `itemsProcessed = 0`, `lastResult = ""`
  2. +
  3. Loop iterates over items
  4. +
  5. Inside loop: Agent processes current item
  6. +
  7. Inside loop: Variables updates `itemsProcessed = + 1`
  8. +
  9. Inside loop: Variables updates `lastResult = `
  10. +
  11. Next iteration: Access `` to compare with current result
  12. +
+
+ +### Retry Logic + +
+

Scenario: Track API retry attempts

+
    +
  1. Initialize in workflow: `retryCount = 0`
  2. +
  3. API block attempts request
  4. +
  5. If failed, Variables increments: `retryCount = + 1`
  6. +
  7. Condition checks if `` \< 3 to retry or fail
  8. +
+
+ +### Dynamic Configuration + +
+

Scenario: Store user context for workflow

+
    +
  1. Initialize in workflow: `userId = ""`, `userTier = ""`
  2. +
  3. API fetches user profile
  4. +
  5. Variables stores: `userId = `, `userTier = `
  6. +
  7. Agent personalizes response using ``
  8. +
  9. API uses `` for logging
  10. +
+
+ +## Outputs + +- **``**: JSON object with all variable assignments from this block + +## Best Practices + +- **Initialize in workflow settings**: Always create variables in the workflow Variables section before using them +- **Update dynamically**: Use Variables blocks to update values based on block outputs or calculations +- **Use in loops**: Perfect for tracking state across iterations +- **Name descriptively**: Use clear names like `currentIndex`, `totalProcessed`, or `lastError` diff --git a/apps/docs/content/docs/en/blocks/wait.mdx b/apps/docs/content/docs/en/blocks/wait.mdx new file mode 100644 index 0000000000..4858d64b0a --- /dev/null +++ b/apps/docs/content/docs/en/blocks/wait.mdx @@ -0,0 +1,99 @@ +--- +title: Wait +--- + +import { Callout } from 'fumadocs-ui/components/callout' +import { Step, Steps } from 'fumadocs-ui/components/steps' +import { Image } from '@/components/ui/image' + +The Wait block pauses your workflow for a specified amount of time before continuing to the next block. Use it to add delays between actions, respect API rate limits, or space out operations. + +
+ Wait Block +
+ +## Overview + +The Wait block enables you to: + + + + Add time delays: Pause execution between workflow steps + + + Respect rate limits: Space out API calls to stay within limits + + + Schedule sequences: Create timed workflows with delays between actions + + + +## Configuration + +### Wait Amount + +Enter the duration to pause execution: +- **Input**: Positive number +- **Maximum**: 600 seconds (10 minutes) or 10 minutes + +### Unit + +Choose the time unit: +- **Seconds**: For short, precise delays +- **Minutes**: For longer pauses + + + Wait blocks can be cancelled by stopping the workflow. The maximum wait time is 10 minutes. + + +## Outputs + +- **``**: The wait duration in milliseconds +- **``**: Status of the wait ('waiting', 'completed', or 'cancelled') + +## Example Use Cases + +### API Rate Limiting + +
+

Scenario: Stay within API rate limits

+
    +
  1. API block makes first request
  2. +
  3. Wait block pauses for 2 seconds
  4. +
  5. API block makes second request
  6. +
  7. Process continues without hitting rate limits
  8. +
+
+ +### Timed Notifications + +
+

Scenario: Send follow-up messages

+
    +
  1. Function sends initial email
  2. +
  3. Wait block pauses for 5 minutes
  4. +
  5. Function sends follow-up email
  6. +
+
+ +### Processing Delays + +
+

Scenario: Wait for external system

+
    +
  1. API block triggers job in external system
  2. +
  3. Wait block pauses for 30 seconds
  4. +
  5. API block checks job completion status
  6. +
+
+ +## Best Practices + +- **Keep waits reasonable**: Use Wait for delays up to 10 minutes. For longer delays, consider scheduled workflows +- **Monitor execution time**: Remember that waits extend total workflow duration diff --git a/apps/docs/public/static/blocks/loop-3.png b/apps/docs/public/static/blocks/loop-3.png new file mode 100644 index 0000000000..2717ff4037 Binary files /dev/null and b/apps/docs/public/static/blocks/loop-3.png differ diff --git a/apps/docs/public/static/blocks/loop-4.png b/apps/docs/public/static/blocks/loop-4.png new file mode 100644 index 0000000000..35d184e6b7 Binary files /dev/null and b/apps/docs/public/static/blocks/loop-4.png differ diff --git a/apps/docs/public/static/blocks/variables.png b/apps/docs/public/static/blocks/variables.png new file mode 100644 index 0000000000..2ad86da531 Binary files /dev/null and b/apps/docs/public/static/blocks/variables.png differ diff --git a/apps/docs/public/static/blocks/wait.png b/apps/docs/public/static/blocks/wait.png new file mode 100644 index 0000000000..298ef1760d Binary files /dev/null and b/apps/docs/public/static/blocks/wait.png differ diff --git a/apps/sim/app/api/workflows/[id]/state/route.ts b/apps/sim/app/api/workflows/[id]/state/route.ts index e197246730..0553d1d62e 100644 --- a/apps/sim/app/api/workflows/[id]/state/route.ts +++ b/apps/sim/app/api/workflows/[id]/state/route.ts @@ -25,7 +25,8 @@ const BlockDataSchema = z.object({ height: z.number().optional(), collection: z.unknown().optional(), count: z.number().optional(), - loopType: z.enum(['for', 'forEach']).optional(), + loopType: z.enum(['for', 'forEach', 'while', 'doWhile']).optional(), + whileCondition: z.string().optional(), parallelType: z.enum(['collection', 'count']).optional(), type: z.string().optional(), }) @@ -78,8 +79,9 @@ const LoopSchema = z.object({ id: z.string(), nodes: z.array(z.string()), iterations: z.number(), - loopType: z.enum(['for', 'forEach']), + loopType: z.enum(['for', 'forEach', 'while', 'doWhile']), forEachItems: z.union([z.array(z.any()), z.record(z.any()), z.string()]).optional(), + whileCondition: z.string().optional(), }) const ParallelSchema = z.object({ diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/frozen-canvas/frozen-canvas.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/frozen-canvas/frozen-canvas.tsx index 897e956c16..6b98701a54 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/frozen-canvas/frozen-canvas.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/frozen-canvas/frozen-canvas.tsx @@ -266,7 +266,9 @@ function PinnedLogs({ - {currentIterationIndex + 1} / {iterationInfo.totalIterations} + {iterationInfo.totalIterations !== undefined + ? `${currentIterationIndex + 1} / ${iterationInfo.totalIterations}` + : `${currentIterationIndex + 1}`} + )} + +
+
+ + +
+ +
+ + +
+ +
+ + {assignment.type === 'object' || assignment.type === 'array' ? ( +