mindthread.
All insights

From Copilot to Operations Agent

Agentic process automation for the service desk, integrated with ServiceNow. The copilot generation put answers next to the ticket. The next step moves the procedure itself into software: an agent that reads the request, applies the access policy, raises the approval where approvals already live, performs the change through a governed API, and leaves a record a human can audit. This article builds one such agent for one high-volume process.

Services

Agentic process automation, ServiceNow integration, Governed action APIs, Identity and access workflows

Industry

Enterprise IT, IT service management

Tuesday 09:14, INC0045812

The short version: a copilot stops at the edge of the ticket. It can find the knowledge article and draft the reply, and then a person has to do the procedure. An operations agent does the procedure. It still does not get to decide policy or approve anything, and it never holds a credential.

The design that makes this safe is unglamorous. ServiceNow stays the system of record. The approval runs where approvals already run. The one action that changes the world goes through a governed API that checks the approval for itself. And the agent runs under an identity narrow enough that the worst it can do is ask.

Priya in Finance opens the Service Portal and types: "I can't open the Finance month-end SharePoint site. Access denied since this morning, need it for the close." It lands in ServiceNow as INC0045812, category Access, priority 4, assigned to Service Desk L1. Nothing is broken. A group membership is missing.

A copilot handles the first minute of this well. It reads the text, matches the knowledge article on site access, suggests the category, and drafts a reply. A copilot we built into an ITSM vendor's product a while ago did exactly that, and it removed most of the searching from a service desk agent's day. Then it stopped, because everything after that point is a procedure with side effects. Which group governs this site? Does the line manager have to approve? Who raises the approval, and where? Who adds the user to the group, who checks that it worked and tells Priya? The copilot could describe those steps. It was not allowed to take them.

The human part of the procedure is maybe twenty minutes of work. The elapsed time is a day and a half, because the ticket waits for an L1 agent to pick it up, waits for the manager, waits for the agent to come back to it, and waits for the change to propagate. Priya's month-end close does not care which of those waits was the long one.

This is where the industry conversation has moved. In a Q2 2026 survey of 256 ITSM professionals run by ITSM.tools, nearly three quarters said their organization already uses the AI built into its ITSM tool. Asked which agentic use case matters most, the top answers were autonomous incident triage and resolution (18 percent), autonomous knowledge creation (18 percent), and end-to-end automated service request fulfillment (13 percent). The barriers were just as clear: poor data quality (32 percent), risk and governance concerns around autonomous actions (30 percent), and a lack of skills to run it (24 percent). The same survey, read twice, says people want the agent to act and are not sure they can let it.

They are right to be careful. Gartner's June 2025 press release predicts that over 40 percent of agentic AI projects will be canceled by the end of 2027, citing "escalating costs, unclear business value or inadequate risk controls", and coins "agent washing" for vendors relabeling chatbots and RPA as agents. McKinsey's 2025 State of AI survey found 62 percent of organizations experimenting with agents and 23 percent scaling one somewhere. In no single business function did more than 10 percent report scaling. The gap between the pilot and the second process is where most of the money is lost. The rest of this article is about building the first process so that the second one is cheap.

Copilot, workflow, agent

The vocabulary is worth pinning down, because the vendors have blurred it. Anthropic's Building effective agents (December 2024) draws the line in one sentence each. Workflows are "systems where LLMs and tools are orchestrated through predefined code paths." Agents are "systems where LLMs dynamically direct their own processes and tool usage." The same piece recommends starting with the simplest thing that works and adding agency only where the number of steps genuinely cannot be predicted.

Most service desk processes fail that test in the agent's favor. The steps of an access request are known. The order is known. What a human L1 agent actually contributes is a handful of bounded judgments: which resource is this person really asking for, which policy row does it fall under, is this a request wearing an incident's clothes, does something about it smell wrong. "Agentic process automation", as ServiceNow and UiPath now use the phrase, is that combination: a workflow skeleton written in ordinary code, with a model filling in the judgments that used to need a person. When we say operations agent in this article, we mean that shape. The model decides inside bounds. Code does the steps.

The history matters because it predicts the failure mode. The last generation of process automation, RPA, drove the vendor's user interface with scripts, and it broke whenever the interface changed. The agentic generation talks to APIs instead, so it survives a UI refresh, and it breaks differently: it is confidently wrong when the data underneath it is wrong. A stale manager field routes an approval to someone who left. A site missing from the policy table gets an educated guess. That is why the survey's top barrier is data quality and why so much of what follows is about checking the world instead of trusting the model.

On the ServiceNow side, the platform has spent three releases moving toward this. Now Assist is the copilot layer. AI Agent Studio and the AI Agent Orchestrator, introduced and expanded across the Xanadu through Australia releases, are ServiceNow's own agents and the machinery that coordinates them. Then on May 5, 2026, at Knowledge 2026, ServiceNow announced Action Fabric: a generally available Model Context Protocol (MCP) server that lets any external agent "execute governed work: flows, playbooks, approvals, catalogs" on the platform, with OAuth identity and a full audit trail, metered in the same Assist currency as Now Assist, with Anthropic's Claude as the lead design partner and Microsoft Copilot alongside. Governance sits in AI Control Tower, where the AI Gateway feature set watches the MCP traffic.

That announcement changes the build-versus-buy question for a platform team. ServiceNow will keep shipping its own agents for the ITSM lifecycle, and for steps that live entirely inside the platform those are the right default. The question is which processes to run on the platform's agents and which to run on an agent you own: processes that cross into identity, cloud, or line-of-business systems, processes where you need to choose the model or keep inference inside the EU, processes whose policy is owned by a team that never opens ServiceNow, or estates that run more than one ticketing tool. The access request in this article is the first kind, and it is a good place to learn the integration, because the process is high-volume and the judgment is already written down.

What the work instruction says

The service desk already has the procedure. It is a knowledge article that L1 agents follow, and it reads like every work instruction ever written: one action at the end, and a page of conditions above it.

KB0014627  Work instruction: Access to a SharePoint site (L1)

1. Confirm the site is one we govern through an Entra ID group.
   Look it up in "Resource access policy". If it is not listed,
   assign to the Collaboration team. Do not grant anything.
2. Read the eligibility column for that resource:
     manager_approval  - the requester's line manager approves
     owner_approval    - the group owner approves
     restricted        - assign to IAM. Never grant from L1.
3. Confirm the requester is an active employee and is not
   already a member of the group.
4. Convert the incident to a request (catalog item "Site or
   application access") so the approval runs on the request.
5. After approval: add the user to the group in Entra ID.
   Only the group named in the policy row. Nothing else.
6. Verify membership. Tell the requester it can take up to
   15 minutes to take effect.
7. Add a work note on every step. Resolve the incident with
   resolution code "Access granted" and link the request.
8. If this is the third incident for the same resource in
   30 days, flag the resource for a knowledge or catalog fix.

Step five is the whole side effect: one call to Microsoft Graph that adds a member to a group. Every other line is either a condition or a record-keeping duty. Steps one and two are a policy lookup against a table the identity team owns. Step three is verification against the identity provider. Step four is a reclassification, and an important one: in ITIL terms this was never an incident. It is a service request, and moving it onto a request means the approval runs on the object ServiceNow built approvals for. Steps six and seven are verification and audit. Step eight is the seed of continuous improvement, the one thing in the list that a human L1 agent almost never has time to do.

In From Runbook to Governed API we took an incident runbook apart the same way and found that each warning wanted to become a precondition, a bound, a redaction, an approval, or an audit field. The access procedure sorts the same way, with one addition: several of its lines want to become a lookup against ServiceNow itself. The policy table, the request, and the approval all live there already. The agent's job is to use them, and the integration's job is to make sure it cannot do anything else.

The shape of the system

Make it concrete. The agent runs outside ServiceNow, as a small service in the client's own cloud tenant, which for most of our clients means an EU region and their choice of model. It reaches into ServiceNow through the MCP Server Console, the inbound half of Action Fabric, where an administrator has created an MCP server named access-ops and exposed exactly six tools on it. ServiceNow reaches back out through Flow Designer: one flow notifies the agent when an Access incident is created, and the catalog item's own flow calls the agent's callback endpoint when an approval is decided. The one change to the outside world, adding a member to an Entra ID group, goes through a governed action API that holds the Microsoft Graph credential and verifies the approval on its own before it acts.

AI Control Tower and AI Gateway: identity, audit trail, metering Priya, Finance Service Portal ServiceNowsystem of record Incident INC0045812 Access · P4 Access policy owned by the identity team Request and approval decided by the line manager MCP server access-ops six tools, runs as svc.access-ops Flow Designer notifies the agent, calls back on approval access-ops agent your tenant, EU region model decides within bounds Governed action API verify, policy, execute, audit Microsoft Graph Entra ID group Audit log who, why, decision files tool calls events grant add member writes verifies the approval with ServiceNow

Follow INC0045812 through it.

  1. The incident is created. A Flow Designer flow filtered on category Access posts its number to the agent.
  2. The agent calls get_incident_context and gets the description, the caller, the caller's manager and department, and the caller's incidents from the last 30 days.
  3. The model reads "Finance month-end SharePoint site" and produces a resource hint. The agent calls get_access_policy, which returns exactly one row: group FIN-MonthEnd-Members, eligibility manager_approval.
  4. The agent calls convert_to_access_request. ServiceNow creates the request from the catalog item, links it to the incident, puts the incident on hold, and the catalog item's flow raises the approval with Priya's line manager.
  5. Nothing runs for two hours and twenty-seven minutes. There is no agent process waiting.
  6. Daniel approves in the ServiceNow approval he already uses. The catalog flow's REST step calls the agent's callback with the request number and the decision.
  7. The agent asks the governed action API to grant the membership. The API confirms with ServiceNow that the request is approved, confirms with Entra that Priya is active and not yet a member, checks the group's tag against policy, adds the member through Graph, reads it back, and writes an audit record.
  8. The agent writes the work note, resolves the incident with a plain message to Priya, and links the request.

Read the diagram once more with one question in mind: what does the agent hold? An OAuth token for one ServiceNow integration user, and a token for one governed API. It never holds the Graph credential and it never approves anything. Every fact it acts on is re-checked by something that is not the model.

Pattern: System of Record Stays Put

The system of record stays put means the agent has no state that ServiceNow does not also have. The incident, the request, the approval, the policy row, and every work note live in the platform, and the agent's memory is a derived view of them that can be thrown away and rebuilt. Use it whenever an agent participates in a process that people also participate in, which in ITSM is every process. The trade-off is chattiness: every step becomes a write to ServiceNow before it becomes an action anywhere else.

Kleppmann's distinction in Designing Data-Intensive Applications between systems of record and derived data is the right lens. A system of record holds the authoritative version of a fact; derived data can always be regenerated from it. Treat the agent's context window as derived data. If the agent process dies between step four and step six above, nothing is lost: the request exists, the approval exists, the incident is on hold with a work note explaining why, and a restarted agent rebuilds its picture by reading them. Compare that with an agent that keeps the process state in its own database and updates the ticket at the end. When that one dies, a manager has approved something no system remembers asking for.

The practical consequence is a small, deliberate tool surface. The access-ops MCP server exposes six tools, and each is a Scripted REST resource or a synchronous Flow Designer action that already encodes a rule. The conversion tool is the most interesting, because it refuses to convert anything the policy row does not support, whatever the agent asked for.

// Scripted REST API  x_mt_aops/access-ops
// Resource: POST /convert_to_access_request
// Exposed as one MCP tool in the MCP Server Console.
(function process(request, response) {
  var body = request.body.data;

  var inc = new GlideRecord('incident');
  if (!inc.get(body.incident_sys_id) || inc.getValue('active') != '1') {
    response.setStatus(409);
    return { outcome: 'denied', reason: 'incident_not_open' };
  }

  // Policy lives in a table the identity team owns. The check is
  // against the row, never against what the agent claims.
  var policy = new GlideRecord('x_mt_aops_resource_access_policy');
  if (!policy.get(body.resource_id) ||
      policy.getValue('group_id') != body.group_id ||
      policy.getValue('eligibility') == 'restricted') {
    response.setStatus(403);
    return { outcome: 'denied', reason: 'resource_policy_mismatch' };
  }

  var requester = inc.caller_id.getRefRecord();
  var cart = new sn_sc.CartJS();
  var order = cart.orderNow({
    sysparm_id: gs.getProperty('x_mt_aops.access_catalog_item'),
    sysparm_quantity: '1',
    sysparm_requested_for: requester.getUniqueValue(),
    variables: {
      resource: policy.getUniqueValue(),
      entra_group: body.group_id,
      justification: body.justification,
      source_incident: inc.getUniqueValue()
    }
  });

  // The catalog item's own flow raises the approval and calls
  // the agent back once it is decided.
  inc.work_notes = '[access-ops-agent] Converted to ' +
    order.request_number + '. Approval runs on the request.';
  inc.setValue('state', 3); // On Hold
  inc.update();

  return {
    outcome: 'converted',
    request_number: order.request_number,
    approval_path: policy.getValue('eligibility')
  };
})(request, response);

Two details carry the weight. The policy check reads the row the identity team maintains and compares it with the group the agent proposed; a mismatch is a 403 with a reason, and the agent's work note has to say so. And the conversion goes through the same catalog item a human would order from, so the approval, the SLA clock, the reporting, and the requester's history are the ones the service desk already understands. The agent did not get a new approval mechanism. It got the old one.

Pattern: Synchronous Tools, Asynchronous Process

Synchronous tools, asynchronous process means the tool calls complete in seconds while the process spans hours, so the waiting must live in the system of record and the agent must be resumable from a callback. Use it for any process with an approval or a change window in it, which is to say any process with a person in it. The trade-off is that you now run a small web service with an inbound endpoint, and you have to secure it.

ServiceNow forces the issue, and helpfully so. According to the MCP Server Console FAQ, the tools you can expose are Now Assist skills, Knowledge Graph queries, Scripted REST APIs, synchronous subflows, and synchronous actions. Flows with wait steps are excluded. You cannot wrap "ask for approval and wait" in a tool, which is the right restriction, because an agent process sleeping for two hours is a liability and an agent polling every minute is a bill, because calls through the MCP server are metered in Assists. So the agent does its part and exits.

from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

SN_MCP = "https://acme.service-now.com/sncapps/mcp-server/mcp/access-ops"


async def handle_new_incident(number: str) -> None:
    # The token belongs to the integration user svc.access-ops.
    # It came from a one-time authorization-code login; the
    # runtime refreshes it from a secret store, never from code.
    headers = {"Authorization": f"Bearer {await sn_token()}"}

    async with streamablehttp_client(SN_MCP, headers=headers) as (r, w, _):
        async with ClientSession(r, w) as sn:
            await sn.initialize()
            ctx = as_dict(await sn.call_tool(
                "get_incident_context", {"incident_number": number}))

            plan = ask_model(PROMPT, observation=ctx)
            # plan.kind is one of: convert, handoff, stop

            if plan.kind != "convert":
                await sn.call_tool("add_work_note", {
                    "incident_sys_id": ctx["sys_id"],
                    "note": plan.note})       # e.g. restricted -> IAM
                return

            policy = as_dict(await sn.call_tool(
                "get_access_policy", {"resource_hint": plan.resource_hint}))
            if not policy:
                # Empty is not "no policy". It may be a missing ACL.
                await sn.call_tool("add_work_note", {
                    "incident_sys_id": ctx["sys_id"],
                    "note": "Policy lookup returned nothing. Stopping."})
                return

            await sn.call_tool("convert_to_access_request", {
                "incident_sys_id": ctx["sys_id"],
                "resource_id": policy["sys_id"],
                "group_id": policy["group_id"],
                "justification": plan.justification})

    # Nothing waits here. The approval lives in ServiceNow, and
    # ServiceNow calls back when a human has decided.

Notice the empty-result branch. The FAQ is explicit that a tool without a properly configured execute ACL and role masking "may return empty results rather than an error." An agent that reads an empty policy lookup as "this resource is not governed" will make a confident mistake, so the loop treats empty as unknown and stops with a work note. That single branch is worth more than most of the prompt.

The second half of the process starts when a human decides. The catalog item's flow has an IntegrationHub REST step that posts the decision to the agent, authenticated with its own OAuth client. The callback verifies the caller before it reads the body.

from fastapi import FastAPI, Header

app = FastAPI()
GOVERNED_API = "https://actions.internal"


@app.post("/callbacks/servicenow/approval")
async def approval_decided(event: ApprovalEvent,
                           authorization: str = Header()):
    # The Flow Designer REST step authenticates with its own OAuth
    # client. Verify the caller first, then act on the claim.
    await verify_servicenow_caller(authorization)

    if event.decision != "approved":
        await sn_tool("add_work_note", incident_sys_id=event.incident_sys_id,
                      note=f"Request {event.ritm_number} declined by "
                           f"{event.approver}. Nothing was changed.")
        await sn_tool("resolve_incident", incident_sys_id=event.incident_sys_id,
                      resolution_code="Declined by approver",
                      notes="Your manager declined this request.")
        return {"status": "closed"}

    # The agent asks. The governed API checks the approval in
    # ServiceNow for itself and is the only thing holding a
    # Microsoft Graph credential.
    result = await httpx.post(
        f"{GOVERNED_API}/actions/grant-group-membership",
        headers={"authorization": f"Bearer {AGENT_TOKEN}"},
        json={"ritm_number": event.ritm_number,
              "group_id": event.group_id,
              "user_upn": event.requested_for_upn,
              "reason": f"Approved access request {event.ritm_number}"},
    )
    outcome = result.json()

    if outcome["outcome"] != "executed":
        await sn_tool("add_work_note", incident_sys_id=event.incident_sys_id,
                      note=f"Grant refused by policy: {outcome['reason']}. "
                           "Assigned to IAM with this context.")
        return {"status": "refused"}

    await sn_tool("add_work_note", incident_sys_id=event.incident_sys_id,
                  note=f"Added to {event.group_id}. Membership verified "
                       f"at {outcome['verified_at']}.")
    await sn_tool("resolve_incident", incident_sys_id=event.incident_sys_id,
                  resolution_code="Access granted",
                  notes="Access to the site is active. It can take up to "
                        "15 minutes to appear. Reply to this ticket to reopen.")
    return {"status": "resolved"}

The callback does not trust the decision it was handed, either. It passes the request number to the governed API, and the governed API checks the approval state in ServiceNow with its own credential before it touches Graph. A forged callback, or a replayed one, gets a refusal and a work note. The process is asynchronous, and every resumption re-verifies the world.

Pattern: Governed Action API

We described the Governed Action API in From Runbook to Governed API: a narrow endpoint for one operational action that authenticates the caller, checks the request against the live state of the world, applies policy from configuration, executes inside the bounds it was given, and audits both answers and refusals. Here it is the endpoint that performs the only irreversible step in the process, and its policy file is short enough to review in a security meeting.

agents:
  access-ops-agent:
    owner: platform-team
    actions:
      grant-group-membership:
        autonomy: autonomous
        required_context:
          - ritm_approved_in_servicenow    # the API queries ServiceNow
          - requester_active_in_entra
          - requester_not_already_member
          - group_matches_policy_row
        allowed_group_tags: [manager_approval, owner_approval]
        blocked_group_tags: [restricted, privileged_role, admin, break_glass]
        max_grants_per_requester_per_day: 3
        verify_after: true

      remove-group-membership:
        autonomy: requires_approval
        approvers: [iam-lead]

defaults:
  unknown_agent: deny
  unknown_action: deny
  audit: all

Read the required context list slowly, because it is where the judgment from the work instruction ended up. The API queries ServiceNow to confirm the request is approved. It queries Entra to confirm the user is active and not already a member. It confirms the group matches the policy row for the resource. Only groups tagged for manager or owner approval are grantable at all; anything carrying one of the blocked tags is refused before a model gets a vote. Removal, which is harder to undo well, needs an IAM lead. And a requester who somehow accumulates a fourth grant in a day trips a rate limit, which is the kind of bound that catches a compromised account or a runaway loop equally well.

A fair question is why the grant does not simply run inside ServiceNow through the Azure AD spoke in IntegrationHub. For a shop where every process starts and ends in ServiceNow, it should, and the agent would call a synchronous action that does it. We put the action behind our own API for two reasons that are not always present. The same grant is needed by agents that do not live in ServiceNow, and the policy about which groups may be granted by software belongs to identity governance, which should not have to edit a ticketing flow to change it. If neither reason applies to you, use the spoke and keep the policy file.

Pattern: One Identity per Agent

One identity per agent means each agent authenticates to ServiceNow as its own integration user, holding a custom role that grants execute on its tools and nothing else. Use it from the first day, because the integration user's roles are the agent's authority, and a shared service account with the itil role is an agent that can edit any incident in the instance. The trade-off is administrative: more users to provision, more OAuth clients to rotate, more ACLs to configure, and a one-time interactive login per agent.

That last point is a ServiceNow specific worth knowing before you design. The MCP Server Console FAQ states that for autonomous agents, tool invocations "execute under the identity of the integration user account configured during OAuth setup," and that the OAuth client-credentials grant, which would let an agent authenticate without a user identity, "is not currently supported." So the agent's token comes from an authorization-code login that a person performs once for svc.access-ops, and the runtime keeps the refresh token in a secret store. It also means every tool the agent calls runs under that user's ACLs, and every tool needs an execute ACL and role masking configured for it, or it silently returns nothing.

In return you get something valuable: the agent shows up in ServiceNow the way any user does. Its work notes carry its name. Its requests appear in the requester's history. AI Control Tower registers the MCP server, the AI Gateway logs every tool invocation with the client and server it came through, blocks regulated data patterns such as card numbers before they cross a tool boundary, and exports the audit history. On the other side, the governed API knows the agent by its own token, with its own row in the policy file. Two auditable identities, and neither of them is the model.

For the record, this integration needs Zurich Patch 9 or Australia Patch 2 as the minimum platform version according to ServiceNow's Action Fabric explainer, plus a Now Assist SKU for ITSM and the Pro Plus tier for AI Gateway. Many instances are not there yet, and an upgrade plan is part of the project.

What the ticket looks like afterwards

The test of the whole design is whether a service desk lead who has never heard of MCP can open the incident and understand what happened. This is the work note trail on INC0045812.

09:14  INC0045812 opened by Priya (Finance) via Service Portal.
09:15  [access-ops-agent] Request is for site "Finance Month-End".
       Policy row: group FIN-MonthEnd-Members, manager_approval.
       Requester active, not a member. Converting to request.
09:15  [access-ops-agent] Converted to REQ0031904 / RITM0032210.
       Approval requested from Daniel (line manager).
11:42  RITM0032210 approved by Daniel.
11:42  [access-ops-agent] Grant requested through governed API.
       Decision: allow (access-ops-agent:grant-group-membership).
11:42  [access-ops-agent] Added to FIN-MonthEnd-Members.
       Membership verified 11:42:31Z. Resolving.
11:43  Resolved. Code: Access granted. Linked: REQ0031904.

Every line names who acted and why. The agent's entries are prefixed so they can be filtered, and the two entries that matter in an audit, the approval and the policy decision, name the human and the rule. The governed API's own audit record holds the rest: what it verified, what it redacted, what Graph returned, and how long it took. A reviewer can trust this ticket without reading a prompt.

Where it fails

Data first, because the survey respondents were right. If the manager field on the user record is stale, the approval goes to someone who left, and the request sits until the SLA breaches. If a site is missing from the resource access policy, the agent stops and assigns to the Collaboration team, which is the correct behavior and also a ticket that used to be resolved by an L1 agent who knew the answer. The first weeks of running this agent are mostly a data-quality project on tables nobody thought of as infrastructure. Budget for that, and treat the agent's hand-offs as a report on what the tables are missing.

Approval fatigue is the second failure, and it is a policy problem wearing an automation costume. If every access request pings the manager within a minute, the manager stops reading and approves. The agent made that worse by removing the delay that used to space requests out. The fix belongs in the policy table: move genuinely low-risk groups to a pre-approved tier that grants without a human, and reserve manager approval for groups where a manager would actually think.

Some access-denied tickets are security events. A requester whose recent incidents show denials across several unrelated resources may have a broken account or a compromised one, and granting the next access is the wrong response to either. The prompt tells the model to hand off in that case, and the rate limit in the policy file catches the version the model misses. Neither is a substitute for the security team seeing those tickets, so the hand-off assigns them, with the context attached.

Cost is a new failure domain. Every tool call through the MCP server is metered in Assists, and ServiceNow publishes no price list, so the question "what does this cost per ticket" has to be answered by counting calls. Our design uses six to eight per ticket. An agent that polls for the approval, or re-reads the incident on every turn, uses dozens. Design for the count before you negotiate the pool.

Two platform boundaries deserve respect. The A2A protocol, the peer-to-peer half of Action Fabric, sits outside AI Gateway governance at its current release, so do not route anything that writes through it yet. And the two ServiceNow MCP clients differ: the AI Agent Studio client does not enforce AI Gateway by default, while the Universal client used by Workflow Data Fabric always does. If a ServiceNow-native agent ever calls your governed API, check which client it uses.

Finally, ownership. ServiceNow will likely ship a native agent for access requests, if it has not by the time you read this. Then you have two agents for one process, and the failure is not technical. Decide, per process, which agent owns it, and write that down in the same place you register the agents. The pattern in Agent-Ready Infrastructure we called an agent registry exists for exactly this.

What we would build first

If we were building this for a client this quarter, we would pick the access request and nothing else, and we would run the agent in propose mode for the first month. Propose mode means every tool call except the work note is replaced by a draft: the agent writes "I would convert this to a request for group X under manager approval" into the ticket, and an L1 agent clicks the button. This costs almost nothing in automation and buys the two things the first month is for. The desk learns to read the agent's reasoning in the ticket, and we learn which of its proposals the desk overrides and why. Every override is either a bug in the prompt or a gap in the policy table, and it tells us which.

We would choose the process by four tests rather than by enthusiasm. There is a written procedure. The action is reversible or at least bounded. The outcome is verifiable by a query, so the agent can prove it worked instead of asserting it. And the volume is high enough that the elapsed-time saving is felt by people who did not ask for an AI project. Access requests pass all four. Password resets pass them too, though most desks automated those years ago, and major incident coordination fails the first two and should stay with people for now.

We would measure four numbers from the first ticket: human touches per ticket, elapsed time from open to resolve, reopen rate within seven days, and the share of tickets the agent handed off. The last one is the health metric. It should start high and fall as the tables get better, and if it falls to zero the agent is guessing. We would capture those numbers for a month of tickets before the agent exists, because the second workflow is only cheap if the first one left a baseline behind.

Then the second process, which is where the design earns its keep. Shared mailbox access, distribution list membership, guest account creation, and license assignment are the same shape: a policy row, an approval on a request, one governed action, a verification. They reuse the integration user, the MCP server, the callback endpoint, the governed API's evaluator, and the audit schema. The second agent is a new prompt, a new policy row type, one new action on the governed API, and a week of testing. Most of its cost is the testing.

What changes

The copilot generation moved knowledge to the point of need, and it was worth doing. The operations agent moves the procedure into software, and the interesting thing is where the judgment lands when it does. None of it lands in the model. Which groups may be granted lives in a table the identity team owns. Who approves lives in the request, where it always did. Whether the grant may execute lives in a policy file that a governed API reads. What happened lives in work notes and an audit log that a service desk lead can read without knowing what a prompt is.

What the L1 agent does changes too, and for the better. They stop being the person who performs the procedure and become the person who reads the exceptions: the site that is not in the table, the requester whose pattern looks wrong, the policy row nobody updated after a reorg, the approval that keeps getting declined. That is the work the procedure was always getting in the way of. Priya gets her site at 11:43 instead of Thursday, and Daniel approved one thing in the place he already approves things. The ticket tells the truth about all of it.

FAQ: Agentic process automation with ServiceNow

What is agentic process automation in ITSM?

A service desk process, such as an access request, run end to end by software in which a language model makes the bounded judgments (which resource the person means, and which policy row it falls under) and ordinary code performs the steps: reading the ticket, raising the approval in ServiceNow, calling a governed API for the change, verifying it, and resolving the incident. The workflow skeleton is fixed. The model fills in the decisions a human L1 agent used to make.

How does an external AI agent integrate with ServiceNow?

Through Action Fabric, generally available since May 2026. An administrator creates an MCP server in the MCP Server Console and exposes specific Scripted REST APIs, synchronous subflows, actions, or Now Assist skills as tools. The agent connects as an MCP client over OAuth and runs under an integration user's identity and roles. ServiceNow calls the agent back through a Flow Designer REST step when something asynchronous, such as an approval, is decided. AI Control Tower's AI Gateway governs, audits, and meters the traffic. The minimum platform version is Zurich Patch 9 or Australia Patch 2.

Should we use ServiceNow's own AI agents or build our own?

Usually both, decided per process. ServiceNow's native agents are the right default for steps that live entirely inside the platform. An agent you own makes sense when the process crosses into identity, cloud, or line-of-business systems, when you need to choose the model or keep inference in the EU, when the policy is owned by a team that never opens ServiceNow, or when the estate runs more than one ticketing tool. Avoid ending up with two agents for one process.

Does the agent need admin rights in ServiceNow?

No. It runs as a dedicated integration user with a custom role that grants execute on its exposed tools and nothing else. Each tool needs an execute ACL and role masking configured, or it returns empty results instead of an error. Never give an agent the itil or admin role.

Where does the approval happen?

In ServiceNow, on the request, by the line manager or group owner, through the same approval they already use. The agent never approves anything. The governed API that performs the change checks the approval record in ServiceNow for itself before it executes.

Further reading

Anthropic - Building effective agents

Martin Fowler - Emerging Patterns in Building GenAI Products

ServiceNow - MCP Server Console FAQ

Want one service desk process running end to end, with ServiceNow as the system of record?

Get started