Post

Here's how to loop through arrays in Copilot Studio

Copilot Studio doesn't have a built-in Apply-to-Each like Power Automate, but you can still loop through arrays and lists. This guide shows you how to use Power FX and Go-to-Step navigation to process multiple items

Here's how to loop through arrays in Copilot Studio

alt text

Challenge

Working with collections of data is fundamental to application development, and arrays represent one of the most essential data structures for t2his purpose. A frequent requirement involves iterating through these collections to execute specific logic on individual items. While Copilot Studio serves as Microsoft’s low-code platform for creating intelligent conversational agents, it currently lacks native looping functionality. Although a preview feature called “Loop through a list” has been introduced to handle list iteration, this capability remains in preview and hasn’t reached general availability yet. In the meantime, developers need alternative approaches to manage and process collections effectively. This comprehensive guide provides a practical solution for this limitation while also exploring the upcoming “Loop through a list” preview feature.

A Practical Example

AssetGenie helps marketing teams quickly generate multiple content pieces for their campaigns. Users simply enter their campaign topic (like “AI-powered CRM software launch”) and select which marketing assets they need from a checklist - email templates, LinkedIn posts, press releases, product one-pagers, etc. The bot then processes each selected item individually, generating customized content for every chosen asset type. This scenario perfectly demonstrates the need for looping in Copilot Studio, as we need to iterate through the user’s multiple selections and generate content for each one.

alt text

Setup

  • An adaptive card with text input for users to enter subject or context of the campaign
  • A choice set with all the asset types available for user to generate and a button to submit
  • This adaptive card is placed in the “Ask with Adaptive card” node and the inputs are stored in two variables namely: “inpSubject”[string] and “inpAssetsChoice” [Table]

Looping through inpAssetsChoice

  • Now let’s loop through inpAssetsChoice and pass the subject and current asset type (eg: Email template or Press release) to an AI builder prompt and generate content for that marketing asset

    alt text

  • Condition: If actionSubmitId is equal to “Generate assets”
  • Set LoopIndex to 0: Create Set a variable value node from variable management and create new variable with name “LoopIndex”, set its value as 0
  • “Incement LoopIndex by 1”: Next, create another Set a variable value node and use the same “LoopIndex” variable and in the vvalue field switch to Formula and enter the following Power Fx formula

    1
    
      Topic.LoopIndex+1 
    

    alt text

  • Condition: LoopIndex “is less than or equal to” fx: CountRows(Topic.inpAssetsChoice)
    1
    
      CountRows(Topic.inpAssetsChoice)
    
  • Prompt: Provide inputs: inpSubject and current item: fx: Index(Topic.inpAssetsChoice, Topic.LoopIndex).Value
    1
    
      Index(Topic.inpAssetsChoice, Topic.LoopIndex).Value
    
  • Message: Select the AI Builder output: Topic.AssetContent.text
    1
    
      Topic.AssetContent.text
    
  • Go To step: Insert Go To step from Topic management and select the node “Incement LoopIndex by 1””

Complete YAML topic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
kind: AdaptiveDialog
beginDialog:
  kind: OnConversationStart
  id: main
  actions:
    - kind: AdaptiveCardPrompt
      id: zlhU2Y
      card: |-
        {
          "type": "AdaptiveCard",
          "$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
          "version": "1.5",
          "body": [
            {
              "type": "Container",
              "showBorder": true,
              "roundedCorners": true,
              "style": "accent",
              "items": [
                {
                  "type": "ColumnSet",
                  "columns": [
                    {
                      "type": "Column",
                      "width": "stretch",
                      "items": [
                        {
                          "type": "TextBlock",
                          "text": "AssetGenie",
                          "wrap": true,
                          "size": "Large",
                          "color": "Default",
                          "isSubtle": true,
                          "style": "heading",
                          "horizontalAlignment": "Left"
                        }
                      ],
                      "backgroundImage": {
                        "verticalAlignment": "Center"
                      },
                      "horizontalAlignment": "Left",
                      "verticalContentAlignment": "Center"
                    },
                    {
                      "type": "Column",
                      "width": "stretch",
                      "backgroundImage": {
                        "verticalAlignment": "Center"
                      },
                      "items": [
                        {
                          "type": "Image",
                          "url": "https://icon-library.com/images/content-icon/content-icon-16.jpg",
                          "size": "Medium",
                          "horizontalAlignment": "Right"
                        }
                      ]
                    }
                  ]
                }
              ]
            },
            {
              "type": "Container",
              "showBorder": true,
              "roundedCorners": true,
              "separator": true,
              "items": [
                {
                  "type": "Input.Text",
                  "label": "Subject / Context",
                  "placeholder": "Placeholder text",
                  "isMultiline": true,
                  "id": "inpSubject"
                },
                {
                  "type": "Input.ChoiceSet",
                  "label": "Assets (Select all that you would like to generate)",
                  "choices": [
                    {
                      "title": "Email template",
                      "value": "Email template"
                    },
                    {
                      "title": "LinkedIn post",
                      "value": "LinkedIn post"
                    },
                    {
                      "title": "Twitter / X post",
                      "value": "Twitter / X post"
                    },
                    {
                      "title": "Press release",
                      "value": "Press release"
                    },
                    {
                      "title": "Product one-pager",
                      "value": "Product one-pager"
                    },
                    {
                      "title": "Landing page",
                      "value": "Landing page"
                    }
                  ],
                  "placeholder": "Placeholder text",
                  "style": "expanded",
                  "isMultiSelect": true,
                  "id": "inpAssetsChoice"
                }
              ],
              "backgroundImage": {
                "url": "https://static.vecteezy.com/system/resources/previews/001/946/670/original/abstract-template-grey-geometric-shine-and-layer-background-with-light-blue-effect-technology-style-free-vector.jpg"
              },
              "style": "emphasis"
            },
            {
              "type": "ColumnSet",
              "columns": [
                {
                  "type": "Column",
                  "width": "auto",
                  "items": [
                    {
                      "type": "ActionSet",
                      "actions": [
                        {
                          "type": "Action.Submit",
                          "title": "Generate assets"
                        }
                      ]
                    }
                  ]
                },
                {
                  "type": "Column",
                  "width": "stretch"
                }
              ]
            }
          ]
        }
      output:
        binding:
          actionSubmitId: Topic.actionSubmitId
          inpAssetsChoice: Topic.inpAssetsChoice
          inpSubject: Topic.inpSubject

      outputType:
        properties:
          actionSubmitId: String
          inpAssetsChoice:
            type:
              kind: Table
              properties:
                Value: String

          inpSubject: String

    - kind: ConditionGroup
      id: conditionGroup_GcegVi
      conditions:
        - id: conditionItem_bQUBZL
          condition: =Topic.actionSubmitId = "Generate assets"
          actions:
            - kind: SetVariable
              id: 7oWGWG
              displayName: Set LoopIndex to 0
              variable: Topic.LoopIndex
              value: 0

            - kind: SetVariable
              id: 9Tnelz
              displayName: Increment LoopIndex by 1
              variable: Topic.LoopIndex
              value: =Topic.LoopIndex+1

            - kind: ConditionGroup
              id: MCad3W
              conditions:
                - id: yOmnNq
                  condition: =Topic.LoopIndex <= CountRows(Topic.inpAssetsChoice)
                  displayName: LoopIndex < Array length
                  actions:
                    - kind: InvokeAIBuilderModelAction
                      id: ADKOpH
                      input:
                        binding:
                          AssetType: =Index(Topic.inpAssetsChoice, Topic.LoopIndex).Value
                          Subject: =Topic.inpSubject

                      output:
                        binding:
                          predictionOutput: Topic.AssetContent

                      aIModelId: a57edec0-c2de-4548-a09f-e85cb84bc3c6

                    - kind: SendActivity
                      id: Gm6vMl
                      activity: |-
                        **{Index(Topic.inpAssetsChoice, Topic.LoopIndex).Value}**
                        
                        
                        {Topic.AssetContent.text}

                    - kind: GotoAction
                      id: MDhyu4
                      actionId: 9Tnelz

    - kind: EndConversation
      id: idBfht

Preview feature

A preview feature “Loop through a list” is available. To try this, head to “https://copilotstudio.preview.microsoft.com/” alt text

The above looping scenario can be handled simply though this approach as in the below snapshot

  • After adding the “Loop through a list”, pass the variable of array/table.
  • This will automatically create a loop value variable, which stores the current item, and can be referenced in the actions inside the loop

    alt text

Thank you! Please reach out in case of any questions or comments on this blog


Sandeep Angara
June 15, 2025

This post is licensed under CC BY 4.0 by the author.