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

 

Updating our API

Let us update our User GraphQL Tutorial to 

schema {
    query: Query
	mutation: Mutation
}

type Query {
   getUser(userID: String!): User
}

type Mutation {
	updateUser(userID: String!, input: updateUserInput!): User
}
	
input updateUserInput {
	manager: String
	department: String
}

type User {
	userID: String! @source(value: "user_name.value")
	name: String @source(value: "name.display_value")
	email: String @source(value: "email.value")
	manager: User @source(value: "manager.value")
	department: Department @source(value: "department.value")
}

type Department {
	name: String! @source(value: "name.display_value")
	departmentHead: User @source(value: "dept_head.value")
}

Now we have not talked about mutations, but it is just either a create, update, or delete operation (technically and/or but do not go creating crazy mutations). They still need to return something, no empty return functions! I think it will make more sense when you look at the resolver we create for it. Go ahead and create a Scripted Resolver and name it Update User and use this code

(function process(env) {

    var userID = env.getArguments().userID;
    var input = env.getArguments().input;

    var userGR = new GlideRecordSecure('sys_user');
    if (!userGR.get('user_name', userID)) {
        return null;
    }

    if (input.manager) {
        var managerGR = new GlideRecordSecure('sys_user');
        if (managerGR.get('user_name', input.manager)) {
			if(managerGR.isValidRecord()) {
				userGR.setValue('manager', managerGR.getUniqueValue());
			}
        }
    }

    if (input.department) {
        var departmentGR = new GlideRecordSecure('cmn_department');
        if (departmentGR.get('name', input.department)) {
			if(departmentGR.isValidRecord()) {
				userGR.setValue('department', departmentGR.getUniqueValue());
			}
        }
    }

    userGR.update();
    return userGR;

})(env);

We make sure at each step that we have valid data and if so we are able to update the user's manager and department. Make sure you create the Resolver Mapping (Mutation:updateUser to Update User) and then try testing this in the GraphQL Explorer (System Web Services > GraphQL > GraphQL Explorer)

mutation {
    snc {
        userGraphQLTutorial {
            updateUser(userID: "david.loo", input: {manager: "fred.luddy"}) {
                name
                email
                manager {
                    name
                    email
                }
                department {
                    name
                }
            }
        }
    }
}

You can revert by changing the manager back to "bud.richman" and rerunning the udpateUser mutation. We now have a more complete API that can not only fetch data but also update it. 

 

Updating our Agentic Workflow, Agent, and Tool

  • Do we need to update our Get and Update User Data Agentic Workflow with our updated schema? No it does not reference our GraphQL API
  • Do we need to update our User Information Agent with our updated schema? No it does not reference our GraphQL API, however we do need to update the agent insturctions (use the image below)
  • Do we need to update our flow action? We do not. As we learned previously there's one endpoint to call and we just pass what we need
  • Do we need to update our Get User Information tool with our updated schema? Yes, the schema it has is now out of date (use the spoiler below)

zackfanning_0-1764705944526.png

 
Spoiler
Use this action to retrieve or update user information through the User GraphQL Tutorial schema.
Provide a GraphQL query that follows the schema structure below.
 
Important details:
- Application namespace: snc
- Schema namespace: userGraphQLTutorial
- userID corresponds to the user’s user_name field. You have to get that information from the user via user input
 
Example Query
query {
  snc {
    userGraphQLTutorial {
      getUser(userID: "david.loo") {
        name
      }
    }
  }
}
 
Example Mutation
mutation {
  snc {
    userGraphQLTutorial {
      updateUser(userID: "david.loo", input: {manager: "bud.richman"}) {
        name
        email
        manager {
          name
          email
        }
        department {
          name
        }
      }
    }
  }
}
 
Schema Reference
 
schema {
    query: Query
mutation: Mutation
}
 
type Query {
   getUser(userID: String!): User
}
 
type Mutation {
updateUser(userID: String!, input: updateUserInput!): User
}
 
input updateUserInput {
manager: String
department: String
}
 
type User {
userID: String! @source(value: "user_name.value")
name: String @source(value: "name.display_value")
email: String @source(value: "email.value")
manager: User @source(value: "manager.value")
department: Department @source(value: "department.value")
}
 
type Department {
name: String! @source(value: "name.display_value")
departmentHead: User @source(value: "dept_head.value")
}

 

Robust Use Cases

Let us test our User Information Agent (Testing tab of agent studio, Test scenario, select User Information Agent. We can update a user's manager and/or department. We can test using "Update david.loo's department to Finance and his manager to fred.luddy" and this was the result

  • User information has been retrieved. The user's name is David Loo, and their email is david.loo@example.com. The manager is Bud Richman, whose email is bud.richman@example.com. The user is part of the Development department.
  • The user's name is David Loo, and their email is david.loo@example.com. The manager is Fred Luddy, whose email is fred.luddy@example.com. The user is part of the Finance department.

We can revert using "Update david.loo's department to Development and his manager to bud.richman" and get this result

  • User information has been retrieved. The user's name is David Loo, and their email is david.loo@example.com. The manager is Fred Luddy, with the email fred.luddy@example.com. The user is part of the Finance department.
  • The user's name is David Loo, and their email is david.loo@example.com. The manager is Bud Richman, with the email bud.richman@example.com. The user is part of the Development department.

It seems to be working quite well! Let us make sure we did not break anything and try a query again. We can test using "Who is david.loo's manager and department head?" and get this result

  • The user's manager is Bud Richman, and the department head is Fred Luddy.

 

Things to Consider

Some things you might have been wondering about as you went through this tutorial

  • Users do not talk like this why are we using User IDs?
    • To make things simple. We could have added actions to look up users based on their name and then used sys_id's which would have made things cleaner.
  • Why did we not use the env.getSource(); in the Update User resolver function if we wanted to update someone's manager or department head?
    • We probably could have using similar logic as we get with the Get User resolver but I do think that code smells. Kind of ties into the last point if we had done the extra work of looking users up by name, presenting the options to the chatter, having them select, using the sys_id then we could have done things much simpler.
  • Why did we create a set of credentials for our action instead of using the user making the request?
    • It might be possible to do so in a very specific way where you are not required to provide authentication and the query executes as the user requiring no changes to the code. It could probably also be done with impersonation . The other options would probably be a security issue e.g using the session token and session ID would work but you cannot access that and if you could it would be bad, passing decrypted username and password, etc. This is one that would require more exploring for a real-world use case. 
  • This feels like it should be easier?
    • I think it likely will be one day. AI Agents can much more easily understand GraphQL compared to traditional REST APIs. Our use case was relatively simple but you could imagine something much more complex using an existing GraphQL API such as a customer ordering API where it could query for order status, items being ordered, receipt information, etc. I would love for native first-class support of ServiceNow GraphQL APIs some day!

 

Final Thoughts

This demo was meant to serve as a fun technical deep dive into GraphQL and Agentic AI on the Now platform. It was intended to make this a creative exploration of the art of the possible with ServiceNow as well as the future of AI and enterprise workflows.

 

The core of this lesson could be extended to more advanced use cases because the systems leverage the same concepts just repeated. Do not hesitate to experiment on your own, trying out small variations and applying these concepts in different scenarios is a great way to deepen your understanding.

 

We hope you enjoyed learning and feel comfortable with the basics of Agentic AI and GraphQL.
This demo is only the beginning of what is possible, or soon will be possible using Agentic AI technologies and automated workflows.

 

We would love to hear any feedback on the posts; what worked well for you and what could be improved. Feel free to post any questions or issues you are having with the posts, and we will be happy to answer. The more you explore Agentic AI and GraphQL on your own, the more you will see the potential for creative and practical applications for each and together.

Version history
Last update:
2 hours ago
Updated by: