diff --git a/docs.json b/docs.json index 5567368..33d9b80 100644 --- a/docs.json +++ b/docs.json @@ -229,6 +229,7 @@ "docs/user-documentation/agents/tools/voice-and-sound-generation", "docs/user-documentation/agents/tools/salesloft", "docs/user-documentation/agents/tools/semrush", + "docs/user-documentation/agents/tools/servicenow", "docs/user-documentation/agents/tools/slab", "docs/user-documentation/agents/tools/snowflake", "docs/user-documentation/agents/tools/statuspage", diff --git a/docs/user-documentation/agents/tools/servicenow.mdx b/docs/user-documentation/agents/tools/servicenow.mdx new file mode 100644 index 0000000..17b9a72 --- /dev/null +++ b/docs/user-documentation/agents/tools/servicenow.mdx @@ -0,0 +1,173 @@ +--- +title: "ServiceNow" +--- + +## Overview + +The ServiceNow tool lets Dust agents read and write records in your ServiceNow instance (incidents, changes, problems, requests, knowledge articles, or any other table) through the ServiceNow Table API. + +The connection uses **OAuth 2.0 (Authorization Code flow)** against your own ServiceNow instance. Setup has two parts: first prepare ServiceNow, then add the tool in Dust. + +**Requirements**: ServiceNow administrator access to create an OAuth application, and a ServiceNow user account (a dedicated integration user is recommended) whose roles and ACLs define what Dust can read and write. + + +OAuth authenticates the connection; it does not authorize anything by itself. What Dust can actually do is determined by the connected user's roles, table and field ACLs, REST API Access Policies, Business Rules, and Data Policies, each enforced by ServiceNow. + + +*** + +### 1. Create the OAuth application in ServiceNow + +1. Log in to your ServiceNow instance as an administrator. +2. Go to **All → System OAuth → Application Registry**. +3. Click **New**, then select **Create an OAuth API endpoint for external clients**. + +4. Configure the application: + +| Field | Value | +| ----- | ----- | +| **Name** | `Dust` (or any recognizable name) | +| **Redirect URL** | `https://dust.tt/oauth/servicenow/finalize` (US) or `https://eu.dust.tt/oauth/servicenow/finalize` (EU) | +| **Default Grant type** | `Authorization Code` | +| **Public Client** | Unchecked | +| **Active** | Checked | +| **Application** | `Global` | +| **Accessible from** | `All application scopes` | + + +The redirect URL must match exactly: same hostname (`dust.tt` vs `eu.dust.tt`), same path, no trailing slash. A mismatch causes an `invalid redirect URI` error. + + +5. Save the record and let ServiceNow **generate** the Client ID and Client Secret (do not type your own client ID). +6. Copy the **Client ID** and **Client Secret**. The secret may not be visible again after you leave the record. + +Dust does not request an OAuth scope by default: the authorization request is sent without a `scope` parameter, and no scope needs to be pre-configured to get connected. If you run into API access issues after connecting, adding the `useraccount` scope to the OAuth application's **Auth Scopes** can resolve them. + +*** + +### 2. Verify API authorization on the instance + +If your instance uses **REST API Access Policies** or **REST API Auth Scopes**, make sure the following is authorized for the OAuth application or authentication profile: + +* The **Table API** (`/api/now/table/...`). +* The HTTP methods Dust uses: **`GET`** (read), **`POST`** (create), **`PATCH`** (update). These are authorized independently; a working read does not prove writes will work. + +Also verify the integration user has: + +* Table-level read/create/write access on the target tables (for incident management, the `itil` role is the usual baseline). +* Field-level access on the fields agents will use, including all mandatory fields for record creation. + +*** + +### 3. Connect in Dust + +1. In Dust, go to **Spaces → Tools → Add Tools** and select **ServiceNow**. +2. Enter: + +| Field | Value | +| ----- | ----- | +| **Instance URL** | `https://.service-now.com` (no trailing slash) | +| **Client ID** | Generated by ServiceNow in step 1 | +| **Client Secret** | Generated by ServiceNow in step 1 | + +3. Start the connection. You are redirected to ServiceNow's authorization page (`/oauth_auth.do`). +4. Sign in with the **dedicated integration user** and approve the access. + +Dust exchanges and refreshes tokens automatically against `https://.service-now.com/oauth_token.do`. No manual token management is needed after the initial authorization. + +*** + +### 4. Validate the connection + +Test with the same integration user that will be used in production, ideally from an agent conversation: + +* **Read**: list one incident (`list_records` on table `incident`, limit 1). +* **Create**: create a disposable test incident and confirm mandatory fields pass. +* **Update**: update the test incident (for example, add a work note) and read it back. + +Test read and write separately: they are authorized independently in ServiceNow. + +*** + +## Available Tools + +The ServiceNow tool is a generic Table API connector. It works with **any table the connected user can access**; table access is enforced by ServiceNow's own ACLs. + +| Tool | Description | +| ---- | ----------- | +| **List Records** | Lists records from any table, with encoded query filters, field projection, and deterministic pagination (`hasMore`, `nextCursor`, `returnedCount`, opt-in `totalCount`). | +| **Get Record** | Gets a single record by `sys_id`. Returns nothing for records that don't exist or aren't visible to the connected user. | +| **Create Record** | Creates a record in any writable table, from a flat map of field values (including custom `u_*` fields). | +| **Update Record** | Updates a record by `sys_id`, from a flat map of field values (state changes, work notes, resolution codes, and so on). | + +### Usage tips + +* **Look up a ticket by number**: `get_record` takes a `sys_id`, not a number. To find `INC0010001`, first call `list_records` on `incident` with the query `number=INC0010001`, then use the returned `sys_id`. +* **Filters**: `list_records` accepts ServiceNow encoded queries (for example `active=true^priority=1^opened_at>=2026-08-01`). +* **Journal fields**: `comments` (customer-visible) and `work_notes` (internal) are written through `update_record`. +* **Missing fields are silent**: fields the connected user cannot read are simply absent from responses, with no error. Never assume a field is readable; test with the real integration user, not an admin. +* **ServiceNow validation applies**: mandatory fields, state-transition rules, Business Rules, and Data Policies are enforced by your instance and surfaced as errors by the tools. + +*** + +## Use the tool efficiently: create a companion skill + +The ServiceNow tool is intentionally generic: it can call any table, but it knows nothing about *your* instance. Every ServiceNow instance differs: available tables, custom `u_*` fields, mandatory fields, choice values, state-transition rules, and Business Rules. Without that context, agents may guess table or field names and hit validation errors. + +The recommended pattern is to **create a skill in Dust that documents your instance, and attach the ServiceNow tool to it**. The skill teaches agents how your ServiceNow works; the tool executes the calls. Share the skill with the users and agents that work with ServiceNow. + +Your skill should describe: + +1. **Approved tables**: API names (`incident`, `change_request`, ...), the purpose of each, and whether agents may read and/or write them. +2. **Mandatory fields for creation**, per table (for example, `incident` requires `short_description` and `caller_id` on most instances). +3. **State-transition rules** (for example, resolving an incident requires `close_code` and `close_notes`; putting it on hold requires `hold_reason`). +4. **Choice values** for state, urgency, impact, and other coded fields. +5. **Reference fields and how to resolve them**: `caller_id`, `assignment_group`, `assigned_to`, and `cmdb_ci` expect a `sys_id`; agents should look them up first in `sys_user`, `sys_user_group`, or `cmdb_ci`. +6. **Custom `u_*` fields** and any instance-specific Business Rules or Data Policies. +7. **Fields that must never be written** (`sys_id`, `number`, `sys_created_on`, ...). +8. **Examples of valid tool calls** for your most common workflows. + +Example skill excerpt: + +```markdown +## Table: incident + +Purpose: create and track IT incidents. + +Create (required): short_description, caller_id (sys_id of a sys_user). +Recommended: description, urgency (1-3), impact (1-3), category, assignment_group. +Do not set priority directly: it is derived from impact + urgency. + +States: 1 New, 2 In Progress, 3 On Hold, 6 Resolved, 7 Closed. +Transitions: On Hold requires hold_reason. Resolved requires close_code + close_notes. + +Journal fields (write via update_record): comments (customer-visible), work_notes (internal). + +Lookups: +- User by email: list_records(table="sys_user", query="email=jane@acme.com", fields="sys_id,name") +- Group by name: list_records(table="sys_user_group", query="name=Service Desk", fields="sys_id,name") +``` + +Keep credentials out of the skill: it should describe usage rules only. Access control always remains enforced by ServiceNow itself. + +*** + +## Troubleshooting + +| Error | Fix | +| ----- | --- | +| **`invalid redirect URI`** | The redirect URL in ServiceNow doesn't exactly match Dust's. Re-copy the URI; check `dust.tt` vs `eu.dust.tt`, the path, and the trailing slash. | +| **`unauthorized_client`** | The Application Registry record is an "OAuth Provider" instead of an "OAuth API endpoint for external clients". Recreate it with the correct type and let ServiceNow generate the credentials. | +| **`Access to unscoped API is not allowed`** | The OAuth application is securely scoped. Set it to `Global` / `Accessible from: All application scopes`, revoke old tokens in **System OAuth → Manage Tokens**, then reconnect. | +| **`401 Unauthorized` after OAuth succeeds** | Check the integration user, its roles, and the token configuration. | +| **`403 Forbidden`** | A REST API Access Policy, auth scope, table ACL, or field ACL rejected the call. Check each authorization layer separately (`rest_service`-type role, `itil`, table/field ACLs, access policies). Adding the `useraccount` scope to the OAuth application's **Auth Scopes** can also resolve API access errors. | +| **Read works but create/update fails** | `POST`/`PATCH` is not authorized, mandatory fields are missing, or field-level write ACLs block the write. Authorize the method in the access policy and inspect the ServiceNow error detail returned by the tool. | +| **Some fields missing from responses** | Field-level read ACLs. This is expected behavior; adjust ACLs only for the fields actually needed. | +| **`429 Too Many Requests`** | Instance rate-limit rules. Retry later; all traffic shares the integration user's quota. | + +## Limitations & Considerations + +* The tool covers the ServiceNow **Table API** only. Catalog ordering flows, attachments, and the Knowledge Management API are not exposed; knowledge articles are accessed through the `kb_knowledge` table. +* Creating catalog requests (`sc_request`, `sc_req_item`) through raw table writes bypasses catalog workflows; prefer reading and updating those tables. +* Deletes are not supported. +* ServiceNow rate limits are admin-defined per instance; there is no fixed platform-wide default.