Repeat workflow steps deterministically over arrays or counts
Looping tools allow you to repeat the same sequence of actions multiple times over a collection of items or a fixed count. The system learns the pattern once during the first iteration, then deterministically replays it for all remaining iterations.
Iterate over a collection of items.Example - Loop over names:
Copy
Ask AI
1. Use start_loop with text='["Alice", "Bob", "Carol"]'2. Click on user {{loop_item}} in the list3. Extract their email and save as {{user_email}}4. Use end_loop_iteration with text="Processed {{loop_item}}: {{user_email}}"
Result: System executes the pattern for Alice, then automatically replays for Bob and Carol.
Repeat actions a fixed number of times. The {{loop_item}} variable will be 0, 1, 2, etc.Example - Download 5 reports:
Copy
Ask AI
1. Navigate to reports page2. Use start_loop with text="5"3. Click on report number {{loop_item}}4. Download the report5. Use end_loop_iteration with text="Downloaded report {{loop_item}}"
Loop over data collected during the workflow using runtime or input variables.Example - Loop over runtime variable:
Copy
Ask AI
1. Use focused_action to extract all order IDs from the screen. Save as {{order_ids}} as a JSON array2. Use start_loop with text="{{order_ids}}"3. Navigate to order {{loop_item}}4. Extract order details5. Use end_loop_iteration with text="Processed order {{loop_item}}"
Example - Loop over input variable:
Copy
Ask AI
Input variables: {patient_ids: ["P001", "P002", "P003"]}1. Use start_loop with text="{patient_ids}"2. Search for patient {{loop_item}}3. Extract medical records4. Use end_loop_iteration with text="Extracted data for {{loop_item}}"
When creating a run programmatically, you can pass arrays of complex objects as input variables. The workflow can then loop over these objects and access nested fields.Workflow Prompt:
Copy
Ask AI
1. Use start_loop with text="{patients}"2. Search for patient {{loop_item.mrn}}3. Verify name matches {{loop_item.first_name}} {{loop_item.last_name}}4. Navigate to the {{loop_item.department}} department5. Extract the latest lab results6. Use end_loop_iteration with text="Processed {{loop_item.first_name}} {{loop_item.last_name}}"
SDK Code to Create the Run:
TypeScript
Python
Copy
Ask AI
import { createCyberdeskClient } from 'cyberdesk';const client = createCyberdeskClient('YOUR_API_KEY');// Define your complex array of objectsconst patients = [ { mrn: 'MRN-001', first_name: 'Alice', last_name: 'Smith', department: 'Cardiology' }, { mrn: 'MRN-002', first_name: 'Bob', last_name: 'Johnson', department: 'Neurology' }, { mrn: 'MRN-003', first_name: 'Carol', last_name: 'Williams', department: 'Oncology' }];// Create the run with the array as an input variableconst { data: run } = await client.runs.create({ workflow_id: 'your-workflow-id', machine_id: 'your-machine-id', input_values: { patients: patients // Pass the array directly - SDK handles JSON serialization }});console.log('Run created:', run.id);
Accessing Nested Fields: Inside your loop, use dot notation to access object properties:
{{loop_item.mrn}} → "MRN-001"
{{loop_item.first_name}} → "Alice"
{{loop_item.department}} → "Cardiology"
For deeply nested data, chain the accessors: {{loop_item.address.city}} or {{loop_item.contacts[0].email}}
When looping over objects or arrays, access nested fields:Example:
Copy
Ask AI
// Input: [{"name": "Alice", "dept": "Sales"}, {"name": "Bob", "dept": "Engineering"}]1. Use start_loop with text="{employees}"2. Search for employee {{loop_item.name}}3. Navigate to {{loop_item.dept}} department4. Use end_loop_iteration with text="Processed {{loop_item.name}} from {{loop_item.dept}}"
Extract data asynchronously while looping for maximum efficiency:Example:
Copy
Ask AI
1. Use start_loop with text='["Form1", "Form2", "Form3"]'2. Navigate to {{loop_item}}3. Take screenshot with extract_prompt="Extract all form data as JSON" and process_async="run"4. Use end_loop_iteration with text="Queued extraction for {{loop_item}}"5. All extractions complete at end of run before generating final output
Loops exit early if errors occur, returning partial results:Example:
Copy
Ask AI
1. Use start_loop with text="{document_names}"2. Open document {{loop_item}}3. If document fails to open, use declare_task_failed with message "Cannot open {{loop_item}}"4. Process the document5. Use end_loop_iteration with text="Completed {{loop_item}}"
If iteration 2 fails: Loop returns summary with iterations 0-1 successful, iteration 2 failed, and early_exit: true.
Limited Cache Detection Inside Loops: Currently, cache detection (trajectory matching) is only performed at start_loop. Steps inside a loop iteration do not benefit from cache detection—they are always executed fresh during the first iteration, then deterministically replayed for subsequent iterations.If you need cache detection on individual steps, we recommend:
Don’t use the loop feature for that workflow
Create a separate Cyberdesk workflow just for the loop iteration logic
Handle looping in your application code, creating a new Cyberdesk run for each iteration
This way, each run benefits from full trajectory caching and cache detection.We are actively working on seamless cache detection during Cyberdesk loops. Stay tuned for updates!
Nested Loops Not Supported: You cannot call start_loop while already in a loop. Complete the current loop first before starting a new one.If you attempt nested loops, the system will return an error: "Cannot start_loop while already in a loop. Call end_loop_iteration first."
Unclosed Loop Reminder: If you haven’t called end_loop_iteration after 20 steps, the system will append a reminder to your tool results. This prevents accidentally leaving loops open.
Example 1: Discover and Process Patients (Runtime Variable Loop)
This example demonstrates a common pattern where the loop items are discovered during the run rather than passed as input. The agent extracts a list of patients from the screen and then loops over them.Workflow Prompt:
Copy
Ask AI
1. Navigate to patient management system2. Login with {username} and {$password}3. Navigate to "Today's Appointments" page4. Use focused_action with instruction "Extract all patient IDs visible in the appointments table. Return them as a JSON array of objects with fields: id, name, appointment_time. Save the result as {{todays_patients}}"5. Use start_loop with text="{{todays_patients}}"6. Click on patient {{loop_item.name}} (ID: {{loop_item.id}})7. Use focused_action to verify the patient record loaded successfully8. Navigate to "Demographics" tab9. Use screenshot with extract_prompt="Extract patient demographics as JSON with fields: name, dob, address, phone" and process_async="batch"10. Navigate to "Insurance" tab11. Use copy_to_clipboard with text="insurance_id" to copy the insurance ID12. Use end_loop_iteration with text="Completed {{loop_item.name}} ({{loop_item.id}}) - Appointment: {{loop_item.appointment_time}}, Insurance: {{insurance_id}}"13. System will automatically process remaining patients14. Export final report with all patient data
Input Variables:
Copy
Ask AI
{ "username": "admin"}
What Happens:
Agent logs in and navigates to the appointments page
focused_action analyzes the screen and extracts patient data, saving it as {{todays_patients}}:
System automatically replays iterations 1-2 for Bob and Carol
Each iteration accesses nested fields: {{loop_item.id}}, {{loop_item.name}}, {{loop_item.appointment_time}}
Key Pattern: The loop items aren’t known ahead of time—they’re discovered by focused_action during execution and stored as a runtime variable. This is powerful for workflows where you need to “find what’s on the screen, then process each item.”
1. Navigate to forms portal2. Use start_loop with text="10"3. Click on form row {{loop_item}}4. Click "Download PDF" button5. Wait 2 seconds for download6. Use end_loop_iteration with text="Downloaded form {{loop_item}}"7. Use execute_terminal_command to run "Get-ChildItem $env:USERPROFILE\Downloads\*.pdf | Select-Object -First 10 | ConvertTo-Json" to list downloaded files
Execution Flow:
Iteration 0: Agent downloads form 0
Iterations 1-9: System automatically downloads forms 1-9
Terminal command lists all downloaded files
Total time: ~10 seconds (cached) vs ~5 minutes (uncached)
1. Use execute_terminal_command to run "Import-Csv {csv_file_path} | ConvertTo-Json" to load spreadsheet data2. Use focused_action to parse the JSON output and save the array as {{records}}3. Navigate to data entry form4. Use start_loop with text="{{records}}"5. Click "New Record" button6. Type {{loop_item.name}} in the Name field7. Type {{loop_item.email}} in the Email field8. Type {{loop_item.phone}} in the Phone field9. Click "Save" button10. Use focused_action to verify "Record saved successfully" message appears11. Use end_loop_iteration with text="Entered record for {{loop_item.name}}"12. Click "Close" to exit data entry
Result: Efficiently processes entire spreadsheet with validation at each step.
Add focused_action steps within your loop to verify each iteration succeeded:
Copy
Ask AI
1. Use start_loop with text="{items}"2. Process {{loop_item}}3. Use focused_action to verify processing succeeded4. Use end_loop_iteration with text="Verified {{loop_item}}"
This ensures errors are caught immediately per iteration.
Parameterize summaries with runtime variables
Make iteration summaries dynamic by using runtime variables:
Copy
Ask AI
Use end_loop_iteration with text="Processed {{loop_item}}: found {{count}} results, status={{status}}"
This creates rich per-iteration results you can analyze later.
Prefer small, focused loop bodies
Keep loop iterations concise (5-15 steps). For complex processing:
Copy
Ask AI
1. Use start_loop with text="{orders}"2. Use focused_action to process order {{loop_item}} completely3. Use end_loop_iteration with text="Completed {{loop_item}}"
Let focused_action handle complex logic per iteration.
Use runtime variables for conditional logic
Set flags during iterations for later decision-making:
Copy
Ask AI
1. Use start_loop with text="{invoices}"2. Check invoice {{loop_item}} status3. If unpaid, save unpaid_count via upsert_runtime_values4. Use end_loop_iteration with text="Checked {{loop_item}}"5. After loop: If {{unpaid_count}} > 0, send notification email
Cause: An error occurred in one of the iterations.Solution: Check the loop summary’s iteration_results array to see which iteration failed and why. Add focused_action validation steps to catch errors early.
{{loop_item}} shows as literal text
Cause: Runtime variable replacement failed or loop wasn’t started.Solution: Ensure start_loop was called before using {{loop_item}}. Check that the loop items array is valid JSON.
Nested loop error
Cause: Attempted to call start_loop while already in a loop.Solution: Complete the current loop with end_loop_iteration before starting a new loop. Nested loops are not supported in the current version.
Loop reminder appears repeatedly
Cause: You haven’t called end_loop_iteration after 20+ steps.Solution: Call end_loop_iteration when the iteration is complete. The reminder appears every 20 steps to prevent accidental unclosed loops.