sn-sdk-fluent
ServiceNow Fluent SDK
ServiceNow Fluent is a TypeScript-based DSL for defining application metadata (sys_metadata) as code. Files use the .now.ts extension and are compiled with now-sdk build. Two-way sync keeps metadata in sync between code and the ServiceNow instance. All Fluent APIs import from @servicenow/sdk/core.
Reference Files
Read these files when you need them — do not pre-load all references at session start. Paths are relative to the skill root (the directory containing this SKILL.md file).
| File | When to read |
|---|---|
references/metadata-types.md |
When generating or reviewing any Fluent metadata type |
references/column-types.md |
When working with Table column definitions (StringColumn, IntegerColumn, etc.) |
references/now-globals.md |
When using Now.ID, Now.include, or the script tagged template literal |
references/getting-started.md |
When helping someone install the SDK or create their first project |
references/project-structure.md |
When explaining file layout, now.config.json, or scope prefix rules |
references/gotchas.md |
When encountering auth errors, XML/source conflicts, --reinstall questions, Now.ID or Now.ref usage, -now: import prefix issues, JS module sync questions, or npx vs now-sdk confusion |
references/cli-reference.md |
When running or explaining build, install, transform, clean, or pack commands |
Example Assets
Use these as structural templates — only read the example that matches your target type, do not pre-load all examples:
| File | Metadata type |
|---|---|
assets/examples/table.now.ts |
Table (all 6 column types) |
assets/examples/acl.now.ts |
Acl + Role |
assets/examples/business-rule.now.ts |
BusinessRule |
assets/examples/client-script.now.ts |
ClientScript (.client.js extension) |
assets/examples/script-include.now.ts |
ScriptInclude |
assets/examples/ui-action.now.ts |
UiAction |
assets/examples/ui-page.now.ts |
UiPage |
assets/examples/rest-api.now.ts |
RestApi |
assets/examples/flow.now.ts |
Flow (trigger + action) |
Hard Rules
-
Read before writing. Always read the relevant reference file before generating or reviewing Fluent code. Do not write from memory.
-
Only use documented APIs. Only use field names and options that appear in the reference files. If a user requests something not in the reference, say so and suggest the closest documented alternative.
-
Never use GlideRecord. GlideRecord is the legacy scripting API. Fluent is the correct pattern for SDK applications.
-
Never omit
Now.IDwhere required. Check the$id-required typeslist in the header ofreferences/metadata-types.mdbefore writing any metadata type. -
Always import from
@servicenow/sdk/core. Never from@servicenow/sdk— the/coresubpath is required. -
Scope prefix comes from
now.config.json. NEVER invent or assume the scope prefix. Readreferences/project-structure.mdfor the schema. Ifnow.config.jsonis absent from the workspace, ask the user for their application scope before writing any names (table names, API names, role names, etc.). -
Never run install without a successful build first.
now-sdk installdeploys whatever is indist/. Running it without a priornow-sdk buildsilently pushes stale or missing artifacts. Build must complete cleanly before deploy. -
Always verify auth before deploying. OAuth tokens expire silently. Run
now-sdk auth --listand confirm the correct alias is active before every deploy. -
sys_app.dois the app record, not the running UI. After deploy, the install output link points to the app record. The live UI URL is theendpointvalue in theUiPage()call in the.now.tssource — e.g.https://<instance>.service-now.com/<endpoint>.do.
ATF tests: When a user asks to generate ATF tests, do NOT generate ATF code from this skill. ATF API surface is extensive and version-sensitive. Direct them to: github.com/ServiceNow/sdk-examples/tree/main/test-atf-sample
Behavior by Task Type
Build & Deploy
Pre-deploy checklist — always run through this first:
now-sdk auth --list→ confirm the correct alias is marked as default- Ensure all
.now.tschanges are saved and complete - Run build — it must succeed cleanly before proceeding
The sequence — never skip or reorder:
npm run build # now-sdk build — type-check + bundle
npm run deploy # now-sdk install — push artifacts to instance
Post-deploy verification — always confirm the right version landed:
- Open
https://<instance>.service-now.com/sys_app.do?sys_id=<scopeId>(scopeId is innow.config.json) - Confirm version matches what you just deployed
- Confirm state is
Active - If either is wrong, check
sys_app_install_logon the instance for errors
Finding the live UI URL after deploy:
The install output shows a sys_app.do link — that is the app record, not the running UI. To get the live URL:
- Open the
UiPage()definition in your.now.tssource file - Read the
endpointvalue (e.g.x_snc_myapp_portal.do) - Live URL:
https://<instance>.service-now.com/<endpoint>.do
Targeting a specific instance:
now-sdk install --auth <alias> # override the default alias
Common failures and fixes:
| Symptom | Cause | Fix |
|---|---|---|
| Auth error mid-deploy | Expired OAuth token | Re-run now-sdk auth --add <url> --type oauth --alias <name> to refresh |
| Install succeeds but UI shows old code | Build was skipped or stale | Re-run npm run build then npm run deploy |
| Type-check error blocks build | TypeScript error in source | Fix the error reported — do not bypass |
| Scope conflict on install | Another app owns the scope | Check sys_app for conflicting scope, resolve before retrying |
Generating Fluent code
- If the scope prefix, metadata type, or required fields have not been stated by the user and cannot be unambiguously determined from the workspace — gather them before writing (ask for each piece of information sequentially to avoid overwhelming the user)
- Read
references/metadata-types.mdfor the target metadata type - Read the matching example from
assets/examples/ - Write code following the example structure exactly
- Use
Now.ID['descriptive_key']for stable IDs; useNow.include('./filename.ext')for external scripts - Prefix table names, API names, and role names with
x_scope_(wherescopecomes fromnow.config.json); ifnow.config.jsonis absent, apply Hard Rule 6
Reviewing Fluent code
- Read
references/metadata-types.md - Check every field and option in the code against the reference
- Flag options not in the reference as "not in reference — may be valid but verify against SDK docs"
- Flag missing
$idon types that require it (marked in the reference header) - Flag any GlideRecord usage
- Flag imports from
@servicenow/sdk(should be@servicenow/sdk/core)
Explaining Fluent code
- Read the relevant section of
references/metadata-types.md - For each field, paraphrase the reference definition — do not explain from memory
- For Now.ID, Now.include, or
scripttag questions, also readreferences/now-globals.md