Recursive Workflows in Dynamics CRM
Dynamics CRM workflows can wait, but they can’t loop. Here’s how I think about Wait conditions:
- A workflow can wait for something to happen. For example, a business process might wait until a record’s status changes, or until it gets reassigned. In cases like these, a workflow with a Wait condition will just sit there … waiting (its System Job’s status reason value will be equal to “Waiting”, in case you want to do an Advanced Find to verify)…until the status changes or the record gets reassigned.
- A workflow can also wait for time to pass. There’s a special “Timeout” function you can access through Local Values in the Specify Workflow Conditions dialog you can use for these kinds of wait conditions. This is useful for processes that wait for a certain time after a record is created. For example, a lead might need to be followed up on, or a service level agreement might require a case to be resolved within a certain period of time.
But what if you had a staged sales process and in certain scenarios you need to go back to a previous stage in the process? Or what if a lead record needs to be reassigned to successive people or queues if it’s neglected for too long? Or what if a case needs to be escalated if it’s not resolved according to a service level agreement?
| These are all scenarios where a looping process can help, and while there’s no built-in functionality for looping, you can get the same result by having a workflow call itself recursively. | Need to learn about workflows in Dynamics CRM? Consider my one-day live online class, Building Workflows in Dynamics CRM, which also includes a copy of my book on the topic. |
Recursive Workflow Mechanics
I like to start out with a simple example that has absolutely no business value, but is the simplest way to see how recursive workflows work. Consider the following workflow:
Figure 1
The only thing this one does is call itself with the Start child workflow action. Remember that As a child workflow needs to be checked in for a workflow to be “callable” like this. (Notice I’ve made this little pedagogic workflow only available to run On demand. Generally when I’m testing something like this, on demand is a good way to start, but keep in mind that if your business process needs to be tied to the “created on” date, on demand workflows won’t provide a very good test in that case!) After publishing the workflow and selecting a lead record to run it on, here’s what you’ll see on the lead record:
Figure 2
It runs successfully six times, then fails on the seventh. This is the built-in “infinite-loop” protection and it’s a good thing it’s there! Suppose I make two small additions to the workflow:
Figure 3
The Update action does a single thing: it uses the “Increment by” operator to add a “1″ to a numeric field on the lead record. (I use the “Employee count” field for demo purposes; in anything other than an illustrative workflow like this one, I’d generally add a custom integer attribute called something like “Counter” to keep track of how many times the workflow has called itself.)
Then I added a Wait/Timeout condition to force a 2-hour wait between recursions.
To test a workflow like this one you have to be a little more patient, so I’ll come back and take a look tomorrow and see how it worked….
…zzzzzzzzzz….[sound of alarm ringing] Wake up!…yawn, stretch, rub eyes…
OK, I’m back, let’s see how that workflow did. This time, if I open the lead record and click the Workflows button I see a different result:
Figure 4
Notice that the Infinite Loop detector didn’t Fail the workflow this time. The two-hour wait I put in there gets around that, since you really might have a business process that requires a workflow to call itself like this more than six times!
Besides the longer timeout period, the only difference between this workflow and the first version is the Update action you can see in Figure 3. Next, I’ll show you an (actually) useful variation on this theme, and how you can increment a counter field within the Update action. This can be important, since it introduces persistence across different instances of the same workflow, giving each instance information it would not otherwise have…like how many times a case has been escalated.
Now, a Recursive Workflow that Does Something!
A common scenario requiring an escalation process is for service cases. Suppose you’ve got an SLA requiring case resolution within a certain period of time of when the case record is created. Dynamics CRM case records can be “assigned” to queues, so I’ll show an example using three queues: “Standard Service”, “Escalation Level 1″, and “Escalation Level 2″:
Figure 5
For simplicity, let’s assume that when a new case is created it gets routed to the Standard Service queue. Then if it’s not resolved according to the SLA requirements, it “escalates” to the Escalation Level 1 queue. Then if it still doesn’t get resolved it ends up in the Escalation Level 2 (!) queue, alarms go off, heads roll, senior engineers get involved…[fill in your business-specific case escalation scenario here].
Figures 6-8 show a workflow that implements this process, starting with the Workflow Properties section:
Figure 6
The workflow itself is dvidided into two main sections. The first is a conditional block that starts by checking the status of the case record, and if it’s still active, uses the “counter” attribute to route the case to the appropriate queue:
Figure 7
Next, the “Wait, then escalate” section will look a little familiar:
Figure 8
First, notice the one-minute timeout. I generally use that when I’m testing a workflow like this to get some quick feedback. Just remember to thoroughly test one of these recursive workflows, you will need to test with whatever the real timeout value’s going to be.
Finally, here’s what the Update action looks like if I click the Set Properties button in Figure 8:
Figure 9
For this workflow, the important part is the “Escalation Counter” field, which gets incremented by “1″ every time the workflow runs. If you haven’t done this before, it takes a little getting used to setting one of these, but if you follow these steps you can get it to work every time:
- Click inside the counter field. (It needs to be a numeric field for this to work correctly.)
- In the Dynamic Values section, select Increment by from the drop down Operator list.
- Then type “1″ in the Default value field, and click OK.
Notice I customized the case form by adding a “Troubleshooting information” section and placing my Escalation Counter field there (along with a couple others I’ll describe in a minute). Obviously this is not information you want the CSRs seeing or updating! Before moving this workflow to production you’d want to remove those from the user form; in the workflow design environment they’ll still be accessible on the Additional Fields tab.
The only customization to the case entity required to make this work is the Escalation Counter attribute. I mentioned this before but it bears repeating: this is what provides the workflow the information it needs to route the case to the appropriate queue (Figure 7). I think of this as introducing some “persistence” across workflows: without something like this, one instance of a workflow doesn’t know anything about another one. Ben Vollmer’s ”Round-Robin” lead assignment trick is another of my favorite examples of the general technique. Once you start thinking about it, it’s easy to come up with other examples:
- Leads might be assigned, and if not qualified within a certain time, reassigned to another user. After a specified time or a certain number of reassignments, you could use a “Dead Leads” queue to flag leads before disqalifying them.
- Or what if you wanted to treat a case differently if it had already been resolved and then got reactivated? An automatic workflow might run on “Status change” and need to take appropriate action if the previous status value was “Resolved”. Out of the box, the workflow instance won’t know anything about what the previous status value was, so you could use something like the techniques described here to give it something to go on.
A related point is the lack of any history information for Dynamics CRM records. There are plenty of examples of how to build “audit trails” to track how records change over time, and there’s even an accelerator on Codeplex for it. Baseline duplicate checking got added in the 4.0 release; who knows, maybe we can look forward to some audit functionality in 5.0?
In the meantime, we have what we have, and you can use approaches like the one I described here to build looping functionality into your workflows. Here’s a video illustrating the case escalation workflow. It’s an excerpt from my one-day live online class, “Building Workflows in Dynamics CRM”, and if you like the recording, you will love it live!
Here’s the link to the video, and here are a few other links you might find useful:
- Ben Vollmer’s article about round-robin lead assignment
- My video on round-robin lead assignment
- The Codeplex accelerators for Dynamics CRM
- My Dynamics CRM Essentials series (includes the one-day workflow class I mentioned above).


Donna Edwards Said,
June 3, 2010 @ 10:24 am
Great article, I really like your posts!
Richard Knudson Said,
June 3, 2010 @ 10:33 am
Thanks for your note, Donna, and thanks for reading!
Andrey Said,
June 4, 2010 @ 5:29 am
Very interesting subject. I bought your book about workflows, and it is very nice that you did not stop and still go on!
I have one question. Why two hours? May I use 1 minute timeout, is it enough to stop built-in “infinite-loop” protection?
Thanks.
Richard Knudson Said,
June 4, 2010 @ 5:39 am
Hi Andrey,
Thanks for your note and for reading!
I’ve read that the cutoff is a one hour wait between recursive calls. I just ran the same workflow with a wait of 10 minutes and it failed after 6 iterations. I just changed it to a 70-minute wait and fired it up again. I’ll let you know how it turns out.
Richard
Another Good ‘un by Richard Knudson - A CRM Riff - Site Home - MSDN Blogs Said,
June 4, 2010 @ 9:33 am
[...] 0 Recursive Workflows in Dynamics CRM from Richard Knudson’s Dynamics CRM Trick [...]
Another Good ‘un by Richard Knudson - A CRM Riff Said,
June 4, 2010 @ 9:34 am
[...] Recursive Workflows in Dynamics CRM from Richard Knudson’s Dynamics CRM Trick Bag [...]
Mehmet Nuri Can Said,
June 12, 2010 @ 11:23 am
another great article. from now on, you’re my favourite crm guy
Mehmet Nuri Can Said,
June 12, 2010 @ 11:27 am
Moreover I want to ask about something you mentioned in the article. Firstly, I copy & paste it.
Leads might be assigned, and if not qualified within a certain time, reassigned to another user. After a specified time or a certain number of reassignments, you could use a “Dead Leads” queue to flag leads before disqalifying them.
How can a lead record be assigned to a queue? Is there a way which I don’t know?
Richard Knudson Said,
June 13, 2010 @ 6:53 am
Hi Mehmet,
Thanks for your two notes. I’m impressed that you caught that bit about leads and queues. When I put that in there I wondered if anybody would! You’re correct that leads cannot be assigned directly to queues (activities and cases only). But there’s a technique you can use within a workflow to accomplish much the same result. Here’s an article I wrote on it a while back: http://www.dynamicscrmtrickbag.com/2009/04/19/first-come/
You get the Trick Bag reader of the month award for catching that!
Mehmet Nuri Can Said,
June 14, 2010 @ 1:52 am
Hi Richard;
Thanks for your reply. I have red “First-Come First-Served Lead Assignment Workflow Using CRM Queues” article, and it is really a nice solution in order to add leads (or other entities) to the queues.
Nowadays, I am designing one of my customers’ sales processes and it is also including assignement of leads issue. I was thinking about the same way with you, using tasks, but I was not sure whether it is a good way. Now I am sure, it is a good way
By the way thanks for the award
Peter Said,
June 22, 2010 @ 5:45 am
Hi Richard!
Thanks for your post. Very interesting indeed for me since I’m about to implement a clone function for Service Activity. However, my customer wants to be able to clone multiple records out of one Service Activity, let’s say 1-50 records. Can that be done with this kind of workflow?
Richard Knudson Said,
June 22, 2010 @ 6:25 am
Hi Peter,
Thanks for your note, and thanks for reading! That’s an interesting question. Here are a few approaches you might try…none of which is perfect, I’m afraid:
1. The clone workflow could simply have multiple create actions. So you could run it on one service activity and use the data on that record to create multiple cloned records. The problem with this approach is you’d have to hardwire the number of records to be created inside the workflow.
2. The clone workflow could call itself recursively. The problem with this is that unless you put a long enough timeout before recursing, I believe the “infinite loop detector” would stop the workflow. This might be worth experimenting with, however.
My guess is the best way to do this would be to write code, use the Create method of the CrmService web service to create the service activity records. If I can come up with a good example of that I’ll write up a separate article on it, but in the meantime, here’s a starting point for you: http://msdn.microsoft.com/en-us/library/bb928994.aspx
Here’s a related article that might even be more helpful, on calling the create method from client-side JavaScript code: http://msdn.microsoft.com/en-us/library/cc677070.aspx
Cheers!
Waits, Timeouts and Recursive Workflows Said,
June 22, 2010 @ 10:42 am
[...] two previous separate articles I discussed Waits and Timeouts in Workflows, and Recursive Workflows. Thanks to web analytics being integrated in my CRM, I know these are two of the more popular [...]
Fernando Ferreira Said,
November 5, 2010 @ 11:12 am
Grate article!
Richard Knudson Said,
November 5, 2010 @ 12:03 pm
Thanks Fernando!