zackfanning
Tera Contributor

Agentic AI and GraphQL

This is a guide for anyone interested in the intersection of Agentic AI and GraphQL, two powerful technologies and how they can be used with the Now platform.

 

We will start with the assumption that you have no experience with either and give you the need-to-know behind the technologies and how they are used to unleash the power of workflows on the Now platform. By Part 5 you will be a pro! We will go into the background behind both GraphQL and Agentic AI but if you are interested in more information I would suggest reading the introduction from the GraphQL Org before starting this just to get some familiarity with terms and some of the benefits of GraphQL versus REST.

 

Inspiration from this article series was drawn from Setting up and Testing your first GraphQL API Tutorial by @Jon G Lind.

 

Note: Initially we planned for this article to have a narrower focus strictly on leveraging Agentic AI, but the use case assumes GraphQL knowledge and thus turned from 2 parts into 5. If you already are a GraphQL pro you can skip straight to part 4! 

 

Part 1 GraphQL Basics

Part 2 GraphQL Beyond the Basics

Part 3 GraphQL Security & Testing

Part 4 Agentic AI and GraphQL Basics

Part 5 Agentic AI and GraphQL Advanced

 

Testing Our API

Testing from an external tool will allow us to gain experience configuring a future integration. We will be using Postman (this is a link to use Postman online that just requires a free account) but feel free to use whatever tool you prefer. First create a collection using the vertical tabs on the left sidebar. Name it GraphQL Testing

zackfanning_0-1764450089844.png

Next create a request and name it getUser

  • Make sure you switch it from GET to POST
  • In the Authorization tab set the type to Basic Auth and use a set of user credentials that has READ access to the User table
  • For the URL use https://replace_ with_your_instance_name/api/now/graphql 
    • This is the same URL you would use for any GraphQL query to ServiceNow, as you can see there is no specific reference to an endpoint (powerful with regards to versioning)

Should look like this

zackfanning_1-1764451154762.png

Now let us go to the Body tab and select GraphQL. You should see to the right an Auto Fetch processing and when it finishes you should Schema Fetched in green. This is because we set up the authentication so it can retrieve the schema. Let us set the Query and GraphQL Variables sections with values.

Query Snippet

query ($userID: String!){
  snc {
    userGraphQLTutorial {
      getUser(userID: $userID) {
        userID
        name
        email
        department {
          name
        	departmentHead {
            userID
        		name
        		email
            department {
              name
            }
          }
        }
        manager {
          userID
          name
          email
          department {
            name
          }
        }
      }
    }
  }
}

Variables snippet

{
    "userID": "david.loo"
}

The important things here

  • Variables must be valid JSON
  • Variable type must be declared (the part in parentheses after query, try removing the ! after you test to see the error response)
  • Reference the variable using $

Variables are quite useful for reusability when testing especially as you build out more complex use cases. Sending the query should return you the following

{
    "data": {
        "snc": {
            "userGraphQLTutorial": {
                "getUser": {
                    "userID": "david.loo",
                    "name": "David Loo",
                    "email": "david.loo@example.com",
                    "department": {
                        "name": "Development",
                        "departmentHead": {
                            "userID": "fred.luddy",
                            "name": "Fred Luddy",
                            "email": "fred.luddy@example.com",
                            "department": {
                                "name": "Development"
                            }
                        }
                    },
                    "manager": {
                        "userID": "bud.richman",
                        "name": "Bud Richman",
                        "email": "bud.richman@example.com",
                        "department": {
                            "name": "Sales"
                        }
                    }
                }
            }
        }
    }
}

This is the same result we got before when we were testing from inside the instance!

 

Securing Our API

We are going to leverage GlideRecordSecure to (you guessed it) secure our APIs. This will check ACLs against the user attempting to make the GlideRecordSecure queries. Head back to our User GraphQL Tutorial API and update

  • Requires authentication to true

After saving the record go to each of the GraphQL Resolvers

  • Get User
  • Get Department

and update the code changing GlideRecord to GlideRecordSecure.

Get User snippet

(function process(/*ResolverEnvironment*/ env) {

	var userID = env.getArguments().userID;

	var userSysID = env.getSource();

	var userGR = new GlideRecordSecure('sys_user');
	userGR.setLimit(1);

	if(userID) {
		userGR.addQuery('user_name', userID);
	}
	if (userSysID) {
		userGR.addQuery('sys_id', userSysID);
	}
	userGR.query();

	return userGR;

})(env);

Get Department snippet

(function process(/*ResolverEnvironment*/ env) {

    var sysID = env.getSource();

	var grDepartment = new GlideRecordSecure('cmn_department');
	grDepartment.get(sysID);

	return grDepartment;

})(env);

This will enforce ACLs based on the authenticated user. Run the test again in Postman, you should get the same results since the credentials we are using are admin credentials. You could test the authentication piece by removing the basic auth credential but we can just skip to testing authorization which proves authentication is functioning by necessity. 

 

Let us go create a new user from User Administration > Users 

zackfanning_0-1764453034464.png

After you create the user set a password (make sure you copy it or you will have to set it again). The important things to note are to not give the user any roles and after you set the password make sure you set Password needs reset to false and save the record. Now go back into postman and update the Basic Auth credentials from the Authorization tab and then click the Send button. You should get a lot of nulls and some errors, but the important part is that you got a name back which is what snoopy.mcsnooperson should have access to. By using GlideRecordSecure our security is handled for us by our existing ACLs on the tables we are building our API around and we do not need to build any further security around our table data.

 

If you wanted to test authentication separately you could by clearing out the basic auth values and setting the request to no auth which should return a simple null value. 

 

This might get you thinking about how you could re-work the API to handle values when the user does not have READ access (make them nullable?) or if there is no data and what should be mandatory vs optional. For our purposes we will not be fixing it. 

 

Deep Dive

Skip this unless you are wondering about re-working that API to handle failures at different parts of the query chain. Since I am sure some folks would be wondering how to fix it - @source will not let you suppress nullable field errors due to ACL failures i.e. even though you mark something as nullable if the ACL check fails it will propagate up the stack as an error while also returning null. Basically you would have to rebuild the API to not use @source and instead handle the logic directly in the scripted resolver.

 

Part 4 Agentic AI

After completing this part, you should be comfortable that your GraphQL API is secure and with how to test from an external tool. Part 4 Agentic AI and GraphQL Basics will finally get into Agentic AI! We will cover the basics of create an Agentic Workflow, Agents, and how to test them together.

Version history
Last update:
4 hours ago
Updated by: