Logan Poynter
Mega Sage
Mega Sage

What is Flow Designer?

If you have not worked with Flow Designer, you probably wonder, “what is Flow Designer?” Well, ServiceNow has a great introductory video on their YouTube channel. Still, I’ll provide an excerpt directly from the ServiceNow datasheet, “Flow Designer gives you rich capabilities for automating processes to reduce repetitive tasks, allowing you to focus on high-value work. Use natural language tools to automate approvals, tasks, notifications, and record operations without writing a single line of code. Expand Flow Designer with IntegrationHub to integrate third-party services for more comprehensive workflows and automation across your enterprise.”

In laymen's terms, Flow Designer works similarly to Workflows by enabling you to drive a digital transformation in how your organization performs mundane, redundant tasks via automation in a no-code (or low-code if necessary) platform with a user-friendly, natural language environment. Actions are easy to understand, and visually, you can follow the data flow from start to finish without the guesswork. With San Diego, ServiceNow also introduced Flow Diagramming, which will give you an all too familiar flowchart look to make digestion even easier. @Mark Roethof has an excellent write-up on how to enable this feature.

 

The Problem

When it comes to managing a knowledge base, a challenge that will without a doubt arise is getting knowledge authors to validate their articles. OOTB, the Author field is hidden, and in some cases, this Author is a member of a Knowledge Management team and not directly the Subject Matter Expert (SME) of the content. Along with this, the SME can change as employees come and go from within the organization. Because of these challenges, maintaining visibility can become clouded, causing articles to be removed from the Service Portal when they have expired.

 

The Solution

We can create a flow that will identify expiring articles and notify the author and an SME we’ve designated for the content to overcome this problem. In this article, I’ll cover the foundational items needed and the components of our flow to make this successful. I’ve attached an update set containing everything created here, along with a PDF version of this article if you wish to download and save it. Now - let's get started!

 

---

 

First: Who’s the SME?

We need to identify who the SME of the article content is for the notification. To accomplish this, add a new reference field to the kb_knowledge table that references the sys_user table.

find_real_file.png

 

You can extend this further with reference qualifiers or other means to limit the selectable list of users, but we’re keeping it simple for this article. Once on the form, you’ll now see your nice new reference field.

find_real_file.png

 

I fully understand that SMEs can - and will - change as time goes on. Another good opportunity is a business process that will require an update to the SME field when a user is offboarded. (Hint: you can build that in a flow as well!)

 

---

 

Lights...camera...ACTION(s)

With this field added to our table, we can move on to the two actions that will play a crucial role in our flow.

 

1. Get All Authors with Expiring Articles

Our first action will collect an array of authors who have an expiring article within the next month. Navigate to Flow Designer by going to Process Automation > Flow Designer or typing “flow designer” in your navigator to get started.

find_real_file.png

 

Once here, click “New” and then click “Action”

find_real_file.png

 

For action name, enter “Get All Authors with Expiring Articles” and for description, enter a friendly description of what the action is for — the other items can be left as-is unless you know you need to make changes.

find_real_file.png

 

Now, this particular action does not need to take in any Inputs, so you can skip this section and go to add a new step by clicking the + and scrolling down until you see Script.

find_real_file.png

 

Now that you have added a Script step to your flow, you will see a screen like this:

find_real_file.png

 

At the top, replace “Script step” with the same name as the Action “Get All Authors with Expiring Articles.” Then we can skip our inputs for this action. For the script section, enter the following code:

(function execute(inputs, outputs) {
    //Create our GlideRecord Variable
    var knowledge = new GlideRecord('kb_knowledge');
    
    //Initialize an array for authors
    var authors = [];
    
    //Add an encoded query to articles valid to on next month and run the query
    knowledge.addEncodedQuery('valid_toONNext month@javascript:gs.beginningOfNextMonth()@javascript:gs.endOfNextMonth()');
    knowledge.query();
    
    //While loop to continue while there is a new record
    while (knowledge.next()) {
        
        //Push the knowledge author email to the array
        authors.push(knowledge.author.email);
    }
    
    //Use ArrayUtil.unique() to make authors unique and remove duplicates
    //This is useful in the event John Doe has 5 articles expiring, we 
    //only want John to be returned once.
    var uniqueAuthors = new ArrayUtil().unique(authors);
    
    //Push our array to action outputs as a comma split string
    outputs.authors = uniqueAuthors.toString().split(',');
})(inputs, outputs);

 

I’ve added comments to help explain what is going on, but this will be relatively straightforward for anyone familiar with scripting in ServiceNow. We query for articles with a valid to date on next month, push all authors to an array, and then make the array unique before outputting.

 

In our Output Variables, create an output with a Label and Name of authors as type Array.String

find_real_file.png

 

Then go to Action Outputs, repeat the same process above and click “Exit Edit Mode”

find_real_file.png

 

Now, click the Data Pill Picker and click into your script step and choose the authors string output.

find_real_file.png

find_real_file.png

 

You can now click Publish and move on to our second action with that done.

 

---

 

2. Get Authors Expiring Articles

Repeat the same process as in our first action to create a new action and fill in the information similarly

find_real_file.png

 

This action will utilize an input passed in for all articles from a Look Up Records action for the same author to pull out the short description, sme, and valid to date. So we create an input called expiringArticles using a Records type for the Knowledge table.

find_real_file.png

find_real_file.png

 

Script:

(function execute(inputs, outputs) {
    //Get our inputs in a variable
    var allArticles = inputs.expiringArticles;

    //Initialize an array to hold our article data
    var articles = [];

    //While we have more articles, loop over each
    while (allArticles.next()) {

        //Set an article variable to the format number Valid to | short description 
        var article = '<b>Article:</b> ' + allArticles.number + '<br/><b>Valid to:</b> ' + allArticles.valid_to + '<br/><b>Short Description:</b> ' + allArticles.short_description + '<br/><br/>';

        //Push our article to the array
        articles.push(article);
    }

    //Populate our outputs
    outputs.articles = articles.join('<br/>');
    outputs.author = allArticles.author.email;
    outputs.sme = allArticles.u_subject_matter_expert.email
})(inputs, outputs);

 

Output Variables:

find_real_file.png

 

Action outputs:

find_real_file.png

find_real_file.png

Note: The astute will have noticed that I used HTML syntax in our string in our article variable. The neat thing is this will be converted when we use our send email action to create some nice styling.

 

---

 

Time to Flow

Once again, go back to the main screen of Flow Designer, click New > Flow, fill out the Flow properties similar to below, and click submit to be taken into your Flow.

find_real_file.png

 

find_real_file.png

 

Components of a flow:

I feel it is imperative to describe the components that go into a Flow so that those new to Flow Designer do not feel lost or forgotten in the terminology. The below definitions come directly from the datasheet I referenced earlier:

  • Flows: A flow is an automated process consisting of a composite set of actions and subflows triggered by an event, resulting in the automation of business logic for an application or process.
  • Subflows: A subflow is a sequence of reusable actions and data inputs that allow it to be started from a flow, subflow, or script. Ex. Iterate on related records; Add a comment; Notify users of record changes.
  • Triggers: A trigger is an activity that once specified, automatically initiates the flow. Ex. Create a record in a specified table or a scheduled job.
  • Actions: An action is a single reusable operation executed by the system. Ex. Make a REST integration to a third party service; Update field value; Request approval; or Log Value.
  • Conditions: A condition is a statement that determines when or how an action runs. Ex. Run an action only if a field is over a certain value.

Note: For this demonstration, we will not be using a Subflow, but one could be created to submit the catalog requests for the SME to validate article content.

 

The structure of our flow is as follows:

find_real_file.png

Trigger: Monthly on the 1st at 10 am

1. Get All Authors with Expiring Articles

2. For each author, look up their expiring articles with a Look Up Records action

find_real_file.png3. Pass our Records into Get Authors Expiring Articles

find_real_file.png

4. Send email

find_real_file.png

 

Now that our Flow is built, we’re ready to test. As a validation of what to expect, I will see how many articles expire next month and the respective author and SMEs of those articles. For my testing, we have three articles expiring next month:

find_real_file.png

 

When we test our Flow and check the execution stats, we see that we did find three results

find_real_file.png

 

To see what the email looks like, you can click on the Send Email action and scroll down to where you see email in the Output Data to open the Email record by clicking on the sys_id and clicking “Open Record”

find_real_file.png

find_real_file.png

 

Then click on “Preview Email” under Related Links to see your email preview.

find_real_file.png

 

find_real_file.png

 

What happens when there are two articles for the same author with different SMEs?

find_real_file.png

 

Uh-oh! We found both articles, but only 1 SME is notified!

find_real_file.png

 

The reason for this is that we are only using the Author as our unique value, and when passed into our second action, we only return a single SME output based on the last expiringArticle passed input. So how do we correct this? We will populate our SMEs into an array for this demonstration, add an additional value for the knowledge article SME in our email, and update our script output to account for multiple SMEs (e.g., an array).

Note: Update u_full_name with the respective sys_user field you want to use. In my PDI I have this field to show as first last - email

(function execute(inputs, outputs) {
    //Get our inputs in a variable
    var allArticles = inputs.expiringArticles;

    //Initialize an array to hold our article data
    var articles = [];
    var smes = [];

    //While we have more articles, loop over each
    while (allArticles.next()) {

        //Set an article variable to the format number Valid to | short description 
        var article = '<b>Article:</b> ' + allArticles.number + '<br/><b>Valid to:</b> ' + allArticles.valid_to + '<br/><b>Short Description:</b> ' + allArticles.short_description + '<br/><b>SME:</b> ' + allArticles.u_subject_matter_expert.u_full_name + '<br/><br/>';

        //Push our article to the array
        articles.push(article);
      
        smes.push(allArticles.u_subject_matter_expert.email);
    }

    //Populate our outputs
    outputs.articles = articles.join('<br/>');
    outputs.author = allArticles.author.email;
    outputs.smes = smes.join(',');
})(inputs, outputs);

 

By joining our array with a comma on output, we can directly pass this into our To: field of the Send Email action, and it will be interpreted as separate recipients.

find_real_file.png

 

And our final email now looks like this:

find_real_file.png

 

---

 

Final Thoughts

Hopefully, this article has helped outline what Flow Designer can do to improve and automate processes within your organization with a (most likely) familiar use case.

Could you only notify the SME rather than the author? Absolutely, but visibility leads to results. Putting all SMEs on the same email can drive collaboration across teams - especially in the event content is referenced in other articles. You can tailor this to your use case however you deem necessary; again, this was to show what Flow Designer can do.

Also, as previously mentioned, this could submit a catalog item wherein the Author and SME have an approval task to complete. The sky is the limit. Look around at what actions are available for a Flow and think holistically about what processes you frequently do - and automate it!

Thanks for reading, have a great day!
--
Liked this article? Hit bookmark and mark it as helpful - it would mean a lot to me.
See something wrong with this article? Let me know down below!
LinkedIn

Comments
Rob Sestito
Mega Sage

Hey Logan,

I was wondering - within this process and I think specifically for the GET step before SEND email, how would / could you make the article number linked to the actual article?

Much like the current process that comes OOTB, the article number becomes a ref link. That way the Employee can just click and go directly to it if they so choose.

Can it be coded into the while loop that is pushing all the information? I attached a screenshot to show where I mean.

Thank you in advance!

-Rob

Logan Poynter
Mega Sage
Mega Sage

Hello Rob,

Yes, this is possible and you are on the right track! Since our script action is returning HTML content, all we have to do is modify our article number to be an a href link.

Our article variable will go from:

var article = '<b>Article:</b> ' + allArticles.number + '<br/><b>Valid to:</b> ' + allArticles.valid_to + '<br/><b>Short Description:</b> ' + allArticles.short_description + '<br/><b>SME:</b> ' + allArticles.u_subject_matter_expert.u_full_name + '<br/><br/>';

To: 

var article = '<b>Article:</b> ' + '<a href="https://{instance}.service-now.com/kb_view.do?sysparm_article=' + allArticles.number + '">' + allArticles.number + '</a>' + '<br/><b>Valid to:</b> ' + allArticles.valid_to + '<br/><b>Short Description:</b> ' + allArticles.short_description + '<br/><b>SME:</b> ' + allArticles.u_subject_matter_expert.u_full_name + '<br/><br/>';

Make sure you update the instance URL or you're going to have a bad time

 

Save and publish the script and run your workflow again, and your email output should look like the following (disregard the undefined for SME - the article does not have one)

find_real_file.png

 

Hope this helps!


Please mark my answer as correct/helpful if it has helped you.

Thanks,
Logan
--
LinkedIn

Rob Sestito
Mega Sage

Hey Logan,

Thank you - I had articles rather than article and that was why I kept getting an error. Of course I would have a typo... lol

To add to this (thank you by the way); using this option brings me to the view of the article on the backend, but not the article form itself. What could we adjust to make sure it goes to the form, rather than the view? I added the attachments to show what I am referring to (but I am sure you know anyway). I tried changing the script a few ways but to no avail.

Yes

find_real_file.png

 

No

find_real_file.png

Cheers,

-Rob

Logan Poynter
Mega Sage
Mega Sage

Greetings Rob,

Yes, we can redirect our Knowledge Article link to the form view rather than the portal view. This is done by modifying two points: the page, and using sys_id rather than article number. 

Page:
Notice our link goes to the /kb_view.do page, which is the portal side. To get to the knowledge form, we need to go to /kb_knowledge.do

Sys ID:
Secondly, we need to use our article sys_id to craft our hyperlink rather than the article number because the kb_knowledge endpoint uses the sys_id= URL parameter. Since in our script we have our allArticles variable which is the object of our found KB, we have access to our sys_id by using allArticles.sys_id. This change will result in a variable that looks like this:

var article = '<b>Article:</b> ' + '<a href="https://{instance}.service-now.com/kb_knowledge.do?sys_id=' + allArticles.sys_id + '">' + allArticles.number + '</a>' + '<br/><b>Valid to:</b> ' + allArticles.valid_to + '<br/><b>Short Description:</b> ' + allArticles.short_description + '<br/><b>SME:</b> ' + allArticles.u_subject_matter_expert.u_full_name + '<br/><br/>';

Notice our first allArticles is not the sys_id, but our second remains the same - we want our Hyperlink text to be the article number still. 

 

Result:
Testing our Flow one final time results in the following outcome:

find_real_file.png

find_real_file.png


Please mark my answer as correct/helpful if it has helped you.

Thanks,
Logan
--
LinkedIn

Rob Sestito
Mega Sage

Hey Logan,

Wonderful - thank you!

I continued to forget that I would need to hit the kb_knowledge. I kept trying different views to see if I could get there.

Much appreciated! This has been a great learning lesson with Flow Designer.

Thank you,

-Rob

Gokul Nath
Kilo Sage

Hello @Logan Poynter 

I am getting some errors for the same action which you have performed.

find_real_file.png

 Aslo send email step shows no valid email receipient, and I checked there are users with email ID 

Logan Poynter
Mega Sage
Mega Sage

Hello Gokul,

What changes did you make to the flow? Have you checked the context log for exception details as it shows? If so, what was the exception?

The update set contains a working flow and corresponding actions discussed within the article, so I will need to know what changes you made to assist. You're clearly getting back the email addresses meaning the action works fine, so it will be with the for each step. This is what a working execution looks like:

find_real_file.png


Please mark my answer as correct/helpful if it has helped you.

Thanks,
Logan
--
LinkedIn

Rob Sestito
Mega Sage

Hey @Logan Poynter

I am looking to see if I can grab addition help with this and maybe if anyone else runs into this issue, our comments can help them.

For some reason, the outgoing emails are ending two of the same emails to everyone.

First, I ran a quick list view on articles under Human Resources KB that are published, and expiring next month.

In total, there is 149 (in a dev instance) - I grouped them by the author, and I get a return of 25. So, essentially I should get hit with 25 emails being sent out (right?).

When I run a test with what I have, I get hit with 40 emails sent. I was thinking, okay maybe more since I am also trying to send to the group manager and the base owner. But in my send email step, I put only the Author in the To field so I could try and see why the emails are being sent twice.

Here is what I have for everything, and I am hoping, when you have time, that you could look this over and let me know if you see something that would trigger this issue.

Steps overall:

find_real_file.png

 

First Get:

find_real_file.png

 

First Get Action Output:

find_real_file.png

 

For each item step:

find_real_file.png

 

Look up Knowledge Records step:

find_real_file.png

 

Second Get:

find_real_file.png

 

Second Get con't:

find_real_file.png

 

Second Get con't:

find_real_file.png

 

Second Get con't:

find_real_file.png

 

Second Get con't:

find_real_file.png

 

Email most recent test with ONLY author in the To field:

find_real_file.png

 

If you are able to help out, you know I would greatly appreciate it!

Thank you,

-Rob

Logan Poynter
Mega Sage
Mega Sage

Hello Rob,

Interesting issue, I did not experience this when I was developing this solution. Please go into the last execution context of your flow and provide a screenshot of the Output of the all authors script (Your grouping shows 25 in a list view, which should be what the script returns because of the unique function at the end of the script step). 

Also, it may not hurt to just throw some log statements in the script after the query and JSON.stringify the whole array before uniqueness occurs. You're getting an extra 15 authors in this step somehow to loop over in step 2, so you'll want to look for duplicate users coming back or to easily identify any users the script is capturing not your list view. 


Please mark my answer as correct/helpful if it has helped you.

Thanks,
Logan
--
LinkedIn

Rob Sestito
Mega Sage

Hey Logan,

Yes - this is indeed an interesting issue. I even rebuilt the entire flow in another one of our dev instances with it being exactly as you have it (without the SME as we do not use that). And it still pushed out the same amount of emails as being doubled.

If I am following your request correctly, you want to see the script from the last Get All Expiring Articles for Same Author. If so, here that is:

(function execute(inputs, outputs) {
// ... code ...
  
  var base = new GlideRecord('kb_knowledge_base');
  var allArticles = inputs.expiringArticles;
  var articles = [];
  var manager = [];
  var base = [];
    
  while (allArticles.next()){
    var article = '<b>Articles:</b> ' + '<a href="https://idexxqa.service-now.com/kb_knowledge.do?sys_id=' + allArticles.sys_id + '">' + allArticles.number + '</a>' + '<br/><b>Author:</b> ' + allArticles.author.first_name + ' ' + allArticles.author.last_name + '<br/><b>Valid to:</b> ' + allArticles.valid_to + '<br/><b>Short Description:</b> ' + allArticles.short_description + '<br/><b>Manager:</b> ' + allArticles.ownership_group.manager.first_name + ' ' + allArticles.ownership_group.manager.last_name + '<br/><br/>'; 
    articles.push(article);
    manager.push(allArticles.ownership_group.manager.email);
    base.push(allArticles.kb_knowledge_base.owner.email);
  }
  
  outputs.articles = articles.join('<br/>');
  outputs.author = allArticles.author.email;
  outputs.manager = manager.join(',');
  outputs.base = base.join(',');
})(inputs, outputs);

 

Also, I am not sure if it matters but I will show it just in case. From the first Get All Authors with Expiring Articles, here is the script:

(function execute(inputs, outputs) {
// ... code ...
  var gr = new GlideRecord('kb_knowledge');
  var authors = [];
  
  gr.addEncodedQuery('workflow_state=published^sys_class_name!=kb_knowledge_block^valid_toONNext month@javascript:gs.beginningOfNextMonth()@javascript:gs.endOfNextMonth()^kb_knowledge_base=bb0370019f22120047a2d126c42e7073');
  gr.query();
  while(gr.next()){
    authors.push(gr.author.email);
    
  }
  var uniqueAuthors = new ArrayUtil().unique(authors);
  outputs.authors = uniqueAuthors.toString().split(',');
  
})(inputs, outputs);

 

And here is what I get for output after I run a test, which seems like it is pulling too many in to begin with.

find_real_file.png

If I misread what exactly you were looking for I apologize - and please let me know where I would need to go to get what you want to see.

Thank you,

-Rob

Logan Poynter
Mega Sage
Mega Sage

Hello Rob,

Looking at the last image your array contains duplicates - and if I counted correctly there are 40 matches. So this means that something is wrong with your uniqueAuthors variable and the ArrayUtils.unique function. I'd suggest going into a background script and seeing if the unique function performs as it should.

If that works, and you're not in a scoped app, but it's still passing back the total array with duplicate values in the output, I'd suggest recreating the script step and updating your flow to look at the new script as a test. Possible something is just not aligning right. 


Please mark my answer as correct/helpful if it has helped you.

Thanks,
Logan
--
LinkedIn

Logan Poynter
Mega Sage
Mega Sage

.

Roshini
Tera Contributor

@Logan Poynter 

Hi,

Could you please guide, how can we achieve the same through sending the authors a notification?and how can we configure the "TO" (author)and "CC" (kb manager) for a notification from the flow?

Gokul Nath
Kilo Sage

@Roshini   Guess you could use the Send email Flow action

Evan Duran
Kilo Guru

@Rob Sestito Did you ever manage to get the duplicates fixed?


Version history
Last update:
‎05-10-2022 11:25 AM
Updated by: