ServiceNow Integration
Connect ServiceNow to let the AI agent query your CMDB and ITSM data during investigations — configuration items and their relationships (for blast-radius analysis), incidents, problems, change requests, assignment groups, users, and knowledge articles. You can also sync ServiceNow services, teams, and people into the Autoheal catalog, and forward ServiceNow incidents to Autoheal as alerts so they are triaged and investigated automatically. For those alert-sourced incidents, Autoheal writes each investigation's progress back onto the incident as work notes (see Investigation Write-Back).
Data queries are read-only — when reading the CMDB/ITSM, Autoheal never creates or modifies records. The one thing Autoheal writes is investigation work notes: for an incident you forward as an alert (see Alert Source Setup), Autoheal posts its investigation progress back onto that same incident as internal Work notes (see Investigation Write-Back). It writes only work notes, only on incidents it is actively investigating — never the customer-facing Additional comments, and never any other field or record.
Capabilities
Once connected, the AI agent can:
| Capability | Description |
|---|---|
| Query the CMDB | Read configuration items across any class (cmdb_ci and its descendants) |
| Service topology & blast radius | Fetch a CI together with its upstream/downstream relationships in one call |
| Incidents, problems, changes | Read incident, problem, and change_request records for RCA timelines and change-risk analysis |
| Assignment groups & users | Look up sys_user_group and sys_user records for SME routing |
| Knowledge articles | Search kb_knowledge for runbooks, SOPs, and architecture notes |
| Aggregate counts | Group-by counts over any table (e.g. CIs per class) for coverage questions |
| Catalog sync | Import ServiceNow services, assignment groups, and users into the Autoheal catalog |
| Alert source webhooks | Receive incident created/updated events pushed by a ServiceNow Business Rule — including every custom u_* field. Resolved, closed, or canceled incidents auto-resolve the Autoheal alert |
| Investigation write-back | Post investigation progress (started, root-cause hypothesis, needs-input, completion, postmortem) back onto the originating incident as internal work notes — requires a write-capable service account |
The agent reads ServiceNow through its REST APIs — the Table API (/api/now/table/{table}), the CMDB Instance API (/api/now/cmdb/instance/{class}/{sys_id}), and the Aggregate API (/api/now/stats/{table}).
Prerequisites
- A ServiceNow instance (e.g.
https://acme.service-now.com) - A service account (local ServiceNow user) for Autoheal to authenticate as
- Read access to the tables the agent queries (CMDB, incident, problem, change_request, sys_user, sys_user_group, kb_knowledge), and write access to the incident journal (
work_notes) so Autoheal can post investigation work notes back onto incidents
Authentication
Autoheal supports two authentication modes; pick one when you add the integration:
| Mode | What you provide | When to use |
|---|---|---|
| OAuth 2.0 (Client Credentials) — recommended | OAuth client ID + secret only | Best security posture — no password stored, short-lived tokens. The right choice for production. Requires ServiceNow Washington DC or later (the inbound client-credentials grant was introduced then), with the OAuth endpoint bound to a service-account user. |
| Username & Password (basic) | Service-account username + password | Simplest to set up — no OAuth registration. Works on every ServiceNow release, but the password is sent on every API call. Good for a quick start or older instances. |
Both modes authenticate as a service account (not a human user), so the required ServiceNow roles/ACLs (below) are the same regardless of which you choose. For production we recommend Client Credentials; use Username & Password when you want the fastest setup or are on a pre-Washington DC release.
Setup
- In ServiceNow, go to User Administration → Users and create a dedicated user (e.g.
autoheal.svc) - Set a strong password — used directly for Username & Password auth, and for Client Credentials this is the user the OAuth endpoint is bound to
- Grant read access to the tables Autoheal queries — the simplest path is the built-in
snc_read_onlyrole (plus any roles your instance requires for the CMDB, incident, problem, change, and knowledge tables), or table-level read ACLs - Grant write access to the incident journal so Autoheal can post investigation work notes back onto incidents — the built-in
itilrole covers this, or add a write ACL onincident(work_notes)
Skip this step if you're using Username & Password. This grant requires ServiceNow Washington DC or later.
Client-credentials grants are off by default instance-wide. An admin must set the system property glide.oauth.inbound.client.credential.grant_type.enabled to true (in sys_properties) — otherwise token requests fail. ServiceNow shows a banner reminding you of this on the grant form.
- In ServiceNow, go to System OAuth → Application Registry and click New
- Choose New Inbound Integration Experience — the guided flow for letting an external client (Autoheal) authenticate into ServiceNow
- On the Select your application connection type screen, choose OAuth - Client credentials grant ("machine-to-machine access to the application without the user's context") — not Authorization code, JWT bearer, Resource owner password, or the OIDC third-party option
- On the New record form, fill in:
- Name and Provider name — any label, e.g.
Autoheal(both are required) - OAuth application user — your Autoheal service account. This is the key field: the access token authenticates as this user, so its roles/ACLs become the token's permissions. The account must be Active, must not have Password needs reset set, and should be a Machine Identity type user with a Name (a name is required, or the account won't appear in this picker)
- Leave Active checked; Comments is optional
- Name and Provider name — any label, e.g.
- Under Auth scope, keep Allow access only to APIs in selected scope checked (ServiceNow's recommended posture) and add an Auth scope row. The
useraccountscope grants exactly the resources available to the bound user — so the token inherits the service account's read + work-note-write permissions and nothing more. For tighter control, click Create auth scope to define a scope limited to the specific APIs instead - Click Save, then copy the generated Client ID and Client Secret (the secret is only fully shown once — use the reveal/copy icon)
Creating a custom auth scope? In Limit authorization to the following APIs, select exactly the three APIs Autoheal calls — nothing else is needed:
- Table API (
/api/now/table) — reads incidents, problems, change requests, CMDB CIs, users, assignment groups, and knowledge articles, and posts investigation work notes back onto incidents - CMDB Instance API (
/api/now/cmdb/instance) — a CI with its relationships (service topology / blast radius) - Aggregate API (
/api/now/stats) — group-by counts (e.g. CIs per class)
Access to individual tables is still governed by the bound user's roles/ACLs (read on the query tables, write on the incident journal) — the scope only limits which APIs the token may call.
On older releases that don't offer the inbound integration experience, use the equivalent Create an OAuth API endpoint for external clients option under the same New menu instead — it produces the same Client ID and Client Secret.
- Go to Integrations in Autoheal and click ServiceNow
- Enter a name (e.g. "Production ServiceNow")
Enter the Instance URL (your instance base URL, e.g. https://acme.service-now.com — not the REST API path), then choose an Authentication mode and fill in its fields:
- OAuth 2.0 (Client Credentials): Client ID + Client Secret
- Username & Password: service-account username + password
For security, Autoheal only sends credentials (and mints OAuth tokens at /oauth_token.do) on ServiceNow-owned domains (*.service-now.com, *.servicenowservices.com). If your instance is fronted by a custom/vanity domain (e.g. https://snow.acme.com), ask your Autoheal operator to add that host (or its parent domain) to the SERVICENOW_ALLOWED_INSTANCE_HOSTS deployment setting before saving — otherwise the Instance URL is rejected as not allowed.
Click Test Connection to verify, then Save. The connection test reads a single row from sys_user.
Required Permissions
The service account needs read access to the tables the agent queries, plus write access to the incident journal for the investigation write-back:
| Table / field | Access | Why it's needed |
|---|---|---|
cmdb_ci (+ class tables) and cmdb_rel_ci | read | Configuration items and their relationships (topology, blast radius) |
incident | read | Incident timelines for root-cause analysis and customer impact |
problem | read | Problem records for the RCA ledger |
change_request | read | Change records for change-risk and blast-radius analysis |
sys_user_group, sys_user, sys_user_grmember | read | Assignment groups, users, and membership for SME routing |
kb_knowledge | read | Knowledge articles (runbooks, SOPs) |
incident → work_notes | write | Post investigation work notes back onto the incident (write-back) |
Grant read + write: read access to the query tables above (e.g.
snc_read_only), and write access to the incident journal (work_notes)
so Autoheal can post investigation work notes
back onto the incidents it investigates — the built-in itil role covers the
write, or add a scoped write ACL on incident. A purely read-only account
still answers data queries, but every work-note post is rejected with a 403.
Example Queries
Once connected, you can ask the AI agent questions like:
Show me the open P1 incidents for the Payments business service
What does the payments-api CI depend on, and what depends on it?
List the change requests that touched the checkout database in the last 7 days
Which assignment group owns the order-service, and who are its members?
How many configuration items exist per CMDB class?
Catalog Sync
ServiceNow can populate the Autoheal catalog with your organizational context:
| ServiceNow source | Catalog entity |
|---|---|
Assignment groups (sys_user_group) | Team |
Users (sys_user) | Person |
Business / application services (cmdb_ci_service) | Service |
Configuration items (cmdb_ci) | Configuration Item |
Because a CMDB can hold tens of thousands of items, the sync runs as a background job that pages through ServiceNow with rate-limiting, so it never blocks the UI. Trigger it with an authenticated POST /api/v1/catalog/servicenow/sync/{integrationId} (the caller needs integration-write access for the tenant); a dedicated UI action is coming. Re-run it any time to refresh — entities are matched on their ServiceNow sys_id, so re-runs update in place.
The catalog sync brings in entities, ownership, and group membership. Fine-grained CI-to-CI dependency edges are read on demand during investigations via the CMDB relationship lookup, so the catalog stays accurate without snapshotting the entire relationship graph.
Alert Source Setup
ServiceNow can act as an alert source by forwarding incidents to Autoheal, where each incident becomes an alert that is triaged and investigated automatically. Unlike tools with a built-in webhook UI, ServiceNow forwards records with a small Business Rule — a script that runs whenever an incident is created or updated. This works on every ServiceNow instance and needs no IntegrationHub license.
Each incident lands as one alert group (keyed on the incident sys_id), later updates refresh it, and every field — including your custom u_* fields — is captured with both its raw value and its human-readable display value.
- Open your ServiceNow integration in Autoheal
- Scroll to the Alert Source section
- Enable the webhook and copy the Webhook URL
- Optionally, enter a Webhook Signing Secret — any token you choose. You'll paste the same value into the script below so Autoheal can authenticate incoming alerts.
- In ServiceNow, go to System Definition → Business Rules and click New. Keep the Application scope as Global (the default) — the script below uses global-scope APIs.
- Set Table to Incident [incident] and check the Advanced checkbox (this reveals the When field and the Advanced tab).
- On the When to run tab, set When to After — not Async — and check both Insert and Update. (An after rule reliably exposes the create-vs-update operation and the instance base URL the script needs; async rules do not. Optionally set Filter Conditions — e.g. Priority · is one of · 1 - Critical, 2 - High — to forward only the incidents you care about.)
- On the Advanced tab, paste the script below into the Script field, then fill in the
ENDPOINT(the Webhook URL you copied) andSECRET(the Webhook Signing Secret, or leave it''). - Click Submit.
(function executeRule(current, previous) {
// ── Paste these two values from the Autoheal integration page ──────────
var ENDPOINT = 'https://<your-tenant>.autoheal.ai/api/v1/webhooks/servicenow/<webhook-secret>'; // the "Webhook URL"
var SECRET = ''; // the "Webhook Signing Secret" you set in Autoheal, or leave '' to skip auth
// ───────────────────────────────────────────────────────────────────────
var MAX_FIELD_CHARS = 2000; // cap huge fields (journal comments, work notes)
var MAX_BODY_CHARS = 900000; // stay under Autoheal's 1 MB request limit
function trunc(s) {
if (s === null || s === undefined) return '';
s = String(s);
return s.length > MAX_FIELD_CHARS ? s.substring(0, MAX_FIELD_CHARS) + '...[truncated]' : s;
}
// Emit EVERY field on the record — standard and custom (u_*) alike — as
// { value: <raw>, display_value: <human-readable> }.
var fields = {};
var elements = current.getElements();
for (var i = 0; i < elements.size(); i++) {
var el = elements.get(i);
var name = String(el.getName());
var raw = '';
var display = '';
try { raw = trunc(current.getValue(name)); } catch (e1) { /* skip unreadable */ }
try { display = trunc(el.getDisplayValue()); } catch (e2) { /* skip unreadable */ }
fields[name] = { value: raw, display_value: display };
}
// Instance base URL. glide.servlet.uri resolves inside an "after" rule;
// fall back to the instance name for incidents created without an HTTP
// context (e.g. inbound email or another integration).
var instanceUrl = String(gs.getProperty('glide.servlet.uri', ''));
if (!instanceUrl) {
instanceUrl = 'https://' + gs.getProperty('instance_name') + '.service-now.com';
}
if (instanceUrl.length > 0 && instanceUrl.charAt(instanceUrl.length - 1) === '/') {
instanceUrl = instanceUrl.substring(0, instanceUrl.length - 1);
}
var payload = {
event_type: (current.operation() == 'insert') ? 'incident.created' : 'incident.updated',
schema_version: '1.0',
instance_url: instanceUrl,
incident_url: instanceUrl + '/incident.do?sys_id=' + current.getUniqueValue(),
sent_at: new GlideDateTime().getValue(),
incident: fields
};
var body = JSON.stringify(payload);
if (body.length > MAX_BODY_CHARS) {
// Pathologically large record: send core fields only. The full record
// is still readable via the Autoheal ServiceNow data-source integration.
var core = ['sys_id', 'number', 'short_description', 'description', 'state',
'impact', 'urgency', 'priority', 'category', 'subcategory',
'assignment_group', 'assigned_to', 'caller_id', 'cmdb_ci',
'opened_at', 'resolved_at', 'closed_at', 'sys_created_on',
'sys_updated_on', 'close_code', 'close_notes'];
var slim = {};
for (var j = 0; j < core.length; j++) {
if (fields[core[j]]) slim[core[j]] = fields[core[j]];
}
payload.incident = slim;
body = JSON.stringify(payload);
}
try {
var r = new sn_ws.RESTMessageV2();
r.setEndpoint(ENDPOINT);
r.setHttpMethod('POST');
r.setRequestHeader('Content-Type', 'application/json');
if (SECRET) {
r.setRequestHeader('Authorization', 'Bearer ' + SECRET);
}
r.setRequestBody(body);
r.executeAsync(); // sent asynchronously — ServiceNow does not wait for Autoheal's response
} catch (ex) {
gs.error('Autoheal webhook business rule failed: ' + ex);
}
})(current, previous);
Create or update a test incident, then confirm it appears on Autoheal's Alerts page. In ServiceNow you can inspect delivery under System Logs → Outbound HTTP Requests (set the outbound web-service log level to Elevated or All to see request bodies). ServiceNow sends both created and updated events to the same endpoint, and resolving, closing, or canceling the incident automatically resolves the Autoheal alert.
The Webhook Signing Secret is an optional second layer of authentication. The
webhook URL already contains a unique secret identifying your integration; the
signing secret adds verification via the Authorization: Bearer <secret>
header the script sends. If you leave SECRET empty in the script, leave the
Webhook Signing Secret blank in Autoheal too.
Investigation Write-Back
When an incident is forwarded as an alert (see Alert Source Setup) and Autoheal investigates it, Autoheal posts the investigation's progress back onto that same incident as work notes — internal, fulfiller-visible entries in the incident's Activity stream — so your ITIL team stays in ServiceNow without switching tools. No setup is required beyond the alert source and a write-capable service account (below); write-back turns on automatically for ServiceNow-sourced incidents.
Autoheal posts a work note at these lifecycle points:
- Investigation started — with a link to follow along in Autoheal.
- Root-cause hypothesis — the finalized most-likely cause, with a confidence label. Preliminary/iterating hypotheses are suppressed, so the incident gets a single root-cause note rather than a stream.
- Needs input / paused for approval — when the agent needs a human to answer a question or approve a gated action.
- Investigation complete and postmortem generated.
Each note ends with a "🤖 Posted automatically by Autoheal" attribution line so it's never mistaken for a human comment.
This is the only thing Autoheal writes to ServiceNow, and only on incidents you forward to it as alerts — the investigation's progress, or a one-line note when it decides not to investigate (see When an investigation is skipped). It posts to internal Work notes — never the customer-facing Additional comments — and never modifies any other field or record.
The write-back needs write access to the incident journal (work_notes) — the
built-in itil role or a scoped write ACL on incident, granted when you set up the
service account (see Required Permissions). A purely read-only
account (e.g. snc_read_only alone) can still read and receive alerts, but each
work-note post is rejected with a 403. ServiceNow journal fields are plain
text, so links appear as label: https://… (not a labelled hyperlink); whether the URL
renders clickable depends on your instance's activity-stream settings.
When an investigation is skipped
Autoheal doesn't always start an investigation for a forwarded incident. When it decides not to, it posts a short work note so your team isn't left wondering whether anything happened. Three reasons a skip happens:
- A recent investigation already found the root cause for a matching alert — the note links that earlier investigation. Always posted.
- Your workspace reached its investigation limit (daily or weekly) — the note names which limit. Always posted.
- A skip rule you configured matched the alert — off by default. Because you wrote the rule to cut noise, the note stays quiet unless you opt in.
To get a work note when one of your own skip rules skips an incident, go to Settings → Alert Response → Investigate Group, expand the skip rule, and turn on Notify the source ticket. (The toggle appears only when a Pylon, Jira, or ServiceNow integration is connected.)
Troubleshooting
401 Unauthorized
- Verify the username/password (basic) or OAuth Client ID/Secret are correct and the account is active
- Confirm the Instance URL is your ServiceNow base URL (e.g.
https://acme.service-now.com), not an API path - Client Credentials: confirm the Application Registry endpoint is active, allows the client-credentials grant (Washington DC+), and is bound to the service-account user
- Client Credentials, if the token request itself fails with
server_error/access_denied: this is the token mint being refused, not bad credentials. Check, in order: (1) the instance-wide propertyglide.oauth.inbound.client.credential.grant_type.enabledistrue(client-credentials is disabled by default); (2) the OAuth client's OAuth application user is set and that user is Active, has no Password needs reset flag, and is a valid (Machine Identity) account - If your instance enforces SSO, ensure the service account can still authenticate locally (basic auth logs in as the user directly)
403 Forbidden / Empty Results for a Table
- The service account lacks read access (ACL/role) for that table
- Grant
snc_read_onlyor the specific table read ACLs (see Required Permissions)
No Records Returned
- Check your filter — ServiceNow uses encoded query syntax (e.g.
active=true^priority=1), not SQL - Reference fields (assignment group, CI) are matched by display value by default; confirm the name matches
- Widen the time range or remove filters to confirm data exists
Instance URL Rejected / Not an Allowed Domain
- Autoheal only sends credentials to ServiceNow-owned domains (
*.service-now.com,*.servicenowservices.com) - If your instance uses a custom/vanity domain (e.g.
https://snow.acme.com), ask your Autoheal operator to add that host or its parent domain to theSERVICENOW_ALLOWED_INSTANCE_HOSTSdeployment setting, then save again - The URL must use
httpsand be the base URL (no path, query, or fragment)
Rate Limiting / Slow Catalog Sync
- ServiceNow enforces per-instance and per-account transaction limits
- The agent and the catalog sync both rate-limit their requests; very large CMDBs simply take longer to sync
- Use more specific queries (fewer fields, tighter filters) to keep responses fast
Alert Source: Webhook Returns 401 Unauthorized
- The
SECRETvalue in your Business Rule script must exactly match the Webhook Signing Secret set on the integration in Autoheal - The script must send it as an
Authorization: Bearer <secret>header — the provided script does this automatically whenSECRETis non-empty - If you don't want signature verification, clear the Webhook Signing Secret in Autoheal and leave
SECRETempty ('') in the script
Alert Source: Incidents Not Appearing in Autoheal
- Confirm the Business Rule is Active, set to run After with Insert and Update checked
- In ServiceNow, open System Logs → Outbound HTTP Requests and check the request status and URL — a non-2xx status shows the error Autoheal returned
- Confirm the
ENDPOINTis the full Webhook URL copied from Autoheal (https://<tenant>/api/v1/webhooks/servicenow/<secret>) - Make sure your ServiceNow instance can reach the Autoheal host over outbound HTTPS (443); check any Filter Condition on the rule isn't excluding your test incident
- A 413 Payload Too Large means the incident exceeded 1 MB; the script already truncates long fields and falls back to core fields, but a custom field with a very large value can still trip this — trim it in the script's
corelist if needed
Write-Back: Work Notes Not Appearing on the Incident
- Most common cause: the service account lacks write access to the incident journal — reads and alert forwarding can succeed while the work-note post is rejected with a 403. Grant the
itilrole or a scoped write ACL onincident.work_notes(see Investigation Write-Back) - Write-back only fires for incidents forwarded as alerts and investigated — confirm the incident shows on the Alerts page and an investigation ran
- Only the final root-cause hypothesis posts (preliminary ones are suppressed), so a still-running investigation may have posted only the "started" note so far
- Autoheal writes to Work notes, not Additional comments — check the internal Work notes stream, not the customer-visible comments
Self-hosted (BYOC): can't reach the instance
All authentication modes — including OAuth, where Autoheal mints tokens at https://<instance>/oauth_token.do — require the Autoheal host to make outbound HTTPS (443) calls to your ServiceNow instance.
- Ensure the Autoheal
api-server-gocontainer has outbound egress to your instance host (e.g.*.service-now.com) - If your network routes outbound traffic through a proxy, set
HTTP_PROXY/HTTPS_PROXY(andNO_PROXY) on the Autoheal stack — these are honored automatically - If your instance presents a certificate signed by a private/internal CA (e.g. behind a TLS-terminating gateway), install that CA bundle into the
api-server-gocontainer's trust store, or front the instance with a publicly-trusted certificate. Do not disable TLS verification in production — turning off certificate validation lets an attacker on the egress/proxy path present a forged certificate and capture your ServiceNow credentials (Basic password, or the OAuth client secret and token) - If your instance is fronted by a custom/vanity domain or is only reachable on a private network, see the "Instance URL Rejected" item above and contact your Autoheal operator