This article is human-conceptualized but written with the assistance of AI and may include some inaccuracies. Always validate independently. — DLYog Lab Research Services LLC is an independent research entity, not affiliated with or endorsed by ServiceNow, Inc. See footer for full disclaimer.
ServiceNow development has historically meant opening a browser, logging into your instance, and clicking through Studio forms. The Now SDK and Claude Code change that equation entirely. In this walkthrough we built a complete IT Asset Tracking application — three tables, two roles, twelve ACLs, two business rules, two email notifications, and two scheduled scripts — entirely from the terminal, using Claude Code as an AI coding agent that reads a PRD and writes production-grade Fluent code. The build took one session. The deploy was a single command.
ServiceNow is not a single product — it is a layered enterprise platform. Understanding its structure is key to understanding why the SDK + Claude Code workflow fits so naturally.
Industries
Domain Modules
CRM
IT
← we built here
Security & Risk
Human Resources
Finance & Supply Chain
Application Dev
Platform Foundations
AI
🗄 Data
⚙️ Workflows
Items in bold are directly relevant to the IT Asset Tracking app built in this article.
If you are an AI or software developer new to the ServiceNow ecosystem, these eight terms are the minimum vocabulary you need to be productive. Everything else builds on them.
Any trackable component in your IT environment — a server, router, VM, application, or even a logical construct like a service. Every CI gets its own record in the CMDB with attributes like owner, location, and status. Think of it as the atomic unit of IT inventory.
ServiceNow.com/cmdb →The single source of truth for all IT infrastructure. Instead of asset data living in scattered spreadsheets or monitoring tools, the CMDB stores every CI and the relationships between them — what depends on what, what runs where, who owns it. AI agents query the CMDB to understand blast radius before making changes.
docs.ServiceNow.com →The collection of processes — aligned with ITIL standards — that govern how IT services are delivered and maintained. Covers Incident Management (restore service fast), Problem Management (eliminate root causes), Change Management (control risk), and Request Fulfillment. ServiceNow ITSM is where most enterprise IT teams live day-to-day.
ServiceNow.com/itsm →An automated network scanning process that finds devices, applications, and services — then creates or updates their CI records in the CMDB automatically. Uses SSH, SNMP, WMI, and REST to probe infrastructure. Without Discovery, teams manually maintain CMDB data; with it, the database stays current without human effort.
docs.ServiceNow.com →A self-contained application that runs inside its own isolated namespace — for example x_snc_itasset. Tables, scripts, and roles are all prefixed to that scope, preventing collisions with other apps or the global platform. This is the right unit of packaging for any custom ServiceNow build — including the app in this article.
ServiceNow's server-side JavaScript API layer. GlideRecord is the ORM — use it to query, insert, update, and delete records without SQL (gr.addQuery(), gr.next()). GlideSystem (aliased as gs) provides logging, user context, date utilities, and event queuing. Business Rules and Script Includes are built on these APIs.
ServiceNow's low-code visual workflow builder. Drag-and-drop actions, conditions, and triggers to automate multi-step business processes — no scripting required. Sits above Business Rules in the abstraction ladder: Business Rules run on record saves; Flows orchestrate sequences across modules and time. The Agentic Workflow capability in the AI tier extends Flows with LLM-driven decision steps.
docs.ServiceNow.com →The unified cloud runtime underneath every ServiceNow product — ITSM, HR, Security, and custom scoped apps all run on it. Provides shared services: AI engine, workflow automation, CMDB, identity, and a low-code toolchain. Think of it the way you think of a cloud provider: your app runs on the platform; the platform manages infrastructure, scaling, and shared data.
ServiceNow.com →Now Assist is ServiceNow's native generative AI assistant — a copilot woven into every major module. It summarises incidents, drafts resolution notes, generates chat replies, writes code for Flow Designer, and powers virtual agents — all without leaving the platform. It runs on ServiceNow's own domain-specific Now LLMs and also supports third-party models (Azure OpenAI, Google Gemini, IBM WatsonX). Unlike a bolt-on chatbot, Now Assist has full access to live CMDB data, open tickets, and workflow context, so its responses are grounded in your actual enterprise state.
Platform Shift: AI is No Longer a Sidecar
"Most providers are making it worse, bolting intelligence onto disconnected systems as a sidecar that can't execute across the enterprise with real context or accountability."
On April 9, 2026, ServiceNow announced it was officially moving beyond the "sidecar AI era." The message: AI built as an add-on to existing systems — queried via API, disconnected from live data, unable to take action — is a dead end. ServiceNow's answer is a fully AI-native platform where the AI layer shares the same data model, workflow engine, and security context as every other product.
"ServiceNow brings it all together, so customers start with a complete AI-native experience across all products and packages, not a procurement project."
"The software industrial complex of the 21st century is converging onto ServiceNow, as the AI operating system for the enterprise."
For developers this means: when you build a scoped app on ServiceNow today, AI capabilities — Now Assist, AI Agent Orchestrator, Agentic Workflows — are not plugins you add later. They are built into the same runtime your tables, business rules, and scheduled scripts run on. The app you build is an AI-native app by default.
One of the most misunderstood aspects of ServiceNow is the assumption that it is a closed cloud product. It is not. Enterprises run ServiceNow against their own on-premises infrastructure — databases, LDAP directories, VMware clusters, proprietary APIs, legacy systems — through a lightweight agent called the MID Server. Understanding this is essential for any AI developer building integrations.
MID Server Architecture — Cloud to On-Premises
External AI Clients
ServiceNow Cloud Instance
Now Assist
AI Copilot & Agent Orchestrator
MCP Server Console
Exposes Now Assist Skills as MCP tools
IntegrationHub
180+ spokes, 450+ app connectors
CMDB / ECC Queue
Async message bus to MID Server
MID Server (Java daemon — runs inside enterprise network)
Discovery Probes
SSH / SNMP / WMI scans
Orchestration
Run scripts & remediation actions
MCP Client / Host
Hosts local MCP server & Ollama LLMs
Integration Relay
Bridges cloud spokes to on-prem APIs
On-Premises Enterprise Network
MID Server communicates outbound-only to the ServiceNow cloud via HTTPS/TLS. No inbound firewall ports are required in the enterprise.
The MID Server is a Java application (OpenJDK-based, no Oracle license required) deployed as a Windows service or Linux daemon inside the enterprise firewall. It polls the ServiceNow cloud via an outbound-only HTTPS connection — the cloud never opens an inbound connection to the enterprise. This single design decision makes enterprise adoption practical: no DMZ, no open inbound ports, just outbound port 443.
Once running, the MID Server enables four critical enterprise capabilities:
ServiceNow CEO Bill McDermott has explicitly stated: "ServiceNow is not and never has been a SaaS company." The platform is positioned as an AI operating layer that orchestrates and executes across cloud and on-premises environments — with the MID Server as the critical on-premises connector. Cloud Wars →
This is where things get interesting for AI developers. Starting with the Zurich release (Patch 4+), ServiceNow shipped native Model Context Protocol (MCP) support in both directions:
The practical implication: any on-premises service can be wrapped as an MCP tool and made available to Now Assist as live context. A proprietary database, a legacy ERP API, an internal knowledge base, a local LLM — all can be exposed through the MID Server's MCP hosting capability and consumed by AI agents running in the ServiceNow cloud.
How On-Premises Data Reaches Now Assist via MCP
User / AI Agent
"What is the current status of asset #4821 in our ERP?"
Now Assist (MCP Client)
Discovers available tools, selects get_erp_asset_status
MID Server (MCP Host)
Calls on-prem ERP API, returns structured result
On-Prem ERP / DB
Asset #4821: Active, last updated 2026-04-10
Now Assist calls the MCP tool, the MID Server bridges to the on-premises system, and the result is returned as grounded context for the AI response. No data leaves the enterprise perimeter uncontrolled.
Think of it as a universal adapter: any service your enterprise runs — regardless of age, vendor, or protocol — can be surfaced to ServiceNow's AI layer as a typed, discoverable tool. The AI agent does not need to know how the ERP works internally. It just calls the tool and gets a result.
Key Facts & Citations
Before diving into how we built the app, it helps to understand the landscape. ServiceNow is an enterprise platform that runs applications inside scoped apps — sandboxed namespaces that bundle tables, roles, business logic, and UI configuration together. Historically, developers create and manage these entirely inside the platform through a browser-based IDE called Studio.
The Now SDK introduced a fundamentally different path: write code locally, compile it, and push it to the instance. Both approaches produce identical artifacts on the platform. The difference is everything about the developer experience.
| Dimension | Studio (Browser-Based) | Now SDK + Claude Code (CLI-Based) |
|---|---|---|
| Where you work | Browser tab, ServiceNow instance UI | Terminal, VS Code, or any editor |
| How artifacts are created | Click through forms, fill fields, save records | Write TypeScript (.now.ts files), run build |
| Version control | Studio Source Control (GitHub integration) | Native git — diff, branch, PR like any codebase |
| AI assistance | Limited to in-platform AI tools | Full Claude Code agent with SDK build skills |
| Repeatability | Manual recreation across instances | Run now-sdk build && now-sdk install |
| Collaboration | Shared instance, concurrent edits can conflict | Independent local environments, merge via git |
| Best for | Visual work, Flow Designer, form layouts, demos | Tables, rules, ACLs, scripts, notifications, testing |
Key Insight: Studio and the Now SDK are not competitors — they are complementary. Many teams use ServiceNow's Build Agent (in-platform AI) to scaffold the initial data model and navigation, then pull it locally to iterate with Claude Code for complex business logic, ACLs, and automated testing. The SDK produces the same native scoped app either way.
To understand what we're building, it helps to know how ServiceNow organizes applications under the hood. Every custom application runs inside a scope — a namespace that isolates its data, scripts, and metadata from other applications and the global platform. A scope looks like x_<company_code>_<app_name>. Our app uses the scope x_snc_itasset.
Within that scope, every artifact type maps to a platform table. When you define a table, a business rule, or an email notification in Fluent, the SDK compiles it to the corresponding sys_metadata record that ServiceNow already knows how to handle. Nothing proprietary — just metadata in a structured format the platform natively understands.
| Fluent Artifact | Platform Table | What It Does |
|---|---|---|
Table() |
sys_db_object + sys_dictionary |
Defines the database schema and all column metadata |
Role() |
sys_user_role |
Named permission assigned to users and groups |
Acl() |
sys_security_acl |
Controls read/write/create/delete per table or field |
BusinessRule() |
sys_script |
Server-side logic that fires on record operations |
EmailNotification() |
sysevent_email_action |
Automated email triggered by events or record changes |
ScheduledScript() |
sysauto_script |
Recurring background job (cron-style) |
Record() on sysevent_register |
sysevent_register |
Registers a named custom event that scripts can fire |
Claude Code is Anthropic's AI coding agent that runs directly in your terminal. Unlike autocomplete tools, Claude Code reads your entire repository, executes commands, edits files, and follows multi-step instructions autonomously. It can scaffold a project, write all the source files, run the build, interpret errors, and fix them — all in one conversational session.
What makes it powerful for ServiceNow development specifically is the plugin and skills system. ServiceNow open-sourced a set of build skills packaged as a Claude Code plugin that gives the agent deep knowledge of:
This knowledge is not baked into the model's training data — it is injected at runtime from markdown skill files that ship with the SDK itself. The documentation versions with the SDK, so the agent always works from docs that match the installed version.
# Install Claude Code (Mac/Linux) curl -fsSL https://claude.ai/install.sh | bash # Inside Claude Code, install the ServiceNow plugin /plugin marketplace add servicenow/sdk /plugin install fluent /reload-plugins
The ServiceNow SDK (@servicenow/sdk) is a Node.js CLI toolkit that introduces Fluent — a TypeScript-based domain-specific language for defining ServiceNow metadata. Instead of clicking through forms to create a table, you write a TypeScript file:
import '@servicenow/sdk/global' import { Table, StringColumn, DateColumn, ReferenceColumn } from '@servicenow/sdk/core' export const x_snc_itasset_hardware_asset = Table({ name: 'x_snc_itasset_hardware_asset', label: 'Hardware Asset', display: 'asset_tag', schema: { asset_tag: StringColumn({ label: 'Asset Tag', mandatory: true }), purchase_date: DateColumn({ label: 'Purchase Date' }), warranty_expiration_date: DateColumn({ label: 'Warranty Expiration Date' }), vendor: ReferenceColumn({ label: 'Vendor', referenceTable: 'x_snc_itasset_vendor_contact', cascadeRule: 'none', }), }, })
Run now-sdk build and this compiles to the exact same table record that Studio would create. The SDK supports the full spectrum of ServiceNow development: tables, columns, roles, ACLs, business rules, flows, client scripts, service catalog items, UI pages, REST APIs, and more.
To demonstrate the agentic workflow end-to-end, we built a realistic enterprise application: an IT Asset Tracking system that lets Asset Managers manage hardware inventory, software licenses, and vendor contacts, while Read-Only Viewers can browse records without editing them.
The requirements came from a single PRD.md file placed at the project root. Claude Code read the PRD and translated every business rule, relationship, and notification requirement into production Fluent code with no manual scaffolding.
Three tables form the core data model, with the Vendor Contact serving as a shared lookup for both hardware and software records:
| Table | Scope Name | Key Fields |
|---|---|---|
| Vendor Contact | x_snc_itasset_vendor_contact |
Vendor name, contact name, email, phone, support contract #, renewal date, notes |
| Hardware Asset | x_snc_itasset_hardware_asset |
Asset tag, serial number, model, category, assigned user (→ sys_user), department, location, purchase date, warranty expiration, status, vendor (→ vendor contact) |
| Software License | x_snc_itasset_software_license |
License key, software name, vendor (→ vendor contact), total seats, seats used, expiration date, renewal status, assigned department |
The Now SDK organizes source into two directories: src/fluent/ for metadata definitions (.now.ts files) and src/server/ for server-side JavaScript modules. The agent structured the project by artifact type, which aligns with SDK conventions.
Architecture Principle: Fluent files define what artifacts exist. Server JS files define what logic runs. Keeping them separate gives you typed Glide API access in src/server/, full IDE autocompletion, and clean code reuse — a business rule function can be shared across multiple rules without duplication.
With a single init command, the SDK creates the project skeleton with now.config.json, package.json, and the required SDK/Glide devDependencies. The scope name follows the x_<company_code>_<app_name> convention required for non-admin scopes.
npx @servicenow/sdk init \ --appName "IT Asset Tracking" \ --packageName "it-asset-tracking" \ --scopeName "x_snc_itasset" \ --template "base" npm install
The agent was told: "read @PRD.md and build the ServiceNow app." Before writing a single file, Claude Code invoked the fluent:now-sdk-explain skill to read the SDK documentation — fetching the full reference for tables, roles, ACLs, business rules, email notifications, scheduled scripts, and the event registration guide. This is what separates an agentic SDK workflow from a generic code generator: the agent knows the platform's specific rules, not just general TypeScript.
Critical rules the agent learned from the docs before writing code:
Table() must exactly match the name property — a mismatch causes build failuresscript property is string-only (no ES module imports) — use Now.include() for file-based scripts@servicenow/glidegenerationType: 'engine') do not need a triggering business ruleTwo roles are defined first because ACLs reference them. The security pattern covers all four CRUD operations per table — twelve ACLs total. Read access grants both roles; write, create, and delete restrict to asset managers only.
export const assetManagerRole = Role({ $id: Now.ID['asset_manager_role'], name: 'x_snc_itasset.asset_manager', description: 'Can create, edit, and retire assets and licenses.', }) export const readOnlyViewerRole = Role({ $id: Now.ID['read_only_viewer_role'], name: 'x_snc_itasset.read_only_viewer', description: 'Read-only access to all asset records.', }) // Read: both roles. Write/Create/Delete: asset manager only. Acl({ $id: Now.ID['hardware_asset_read'], type: 'record', table: 'x_snc_itasset_hardware_asset', operation: 'read', roles: [assetManagerRole, readOnlyViewerRole], adminOverrides: true, })
The PRD defined two validation rules. Both are before rules that run on insert and update, calling setAbortAction(true) if validation fails. The logic lives in src/server/ as ES module functions, imported directly into the .now.ts definition — giving full TypeScript/Glide API type checking in the IDE.
// src/server/business-rules/validate-hardware-asset.js import { gs } from '@servicenow/glide' export function validateHardwareAsset(current, previous) { var purchaseDate = current.getValue('purchase_date') var warrantyDate = current.getValue('warranty_expiration_date') if (purchaseDate && warrantyDate) { var purchase = new GlideDate() purchase.setValue(purchaseDate) var warranty = new GlideDate() warranty.setValue(warrantyDate) if (warranty.before(purchase)) { gs.addErrorMessage( 'Warranty expiration date cannot be earlier than the purchase date.' ) current.setAbortAction(true) } } }
The 30-day license and 60-day warranty alert requirements were implemented as an event-driven pipeline: a daily scheduled script fires a custom event per expiring record, and an EmailNotification rule responds to that event. The event name must fit within 40 characters including the scope prefix.
// Register custom events (sysevent_register) // "x_snc_itasset.lic_renewal" = 26 chars ✓ Record({ $id: Now.ID['license_renewal_event'], table: 'sysevent_register', data: { event_name: 'x_snc_itasset.lic_renewal', suffix: 'lic_renewal', table: 'x_snc_itasset_software_license', fired_by: 'Scheduled Script: Check License Renewals', }, }) // Email notification responds to the event EmailNotification({ $id: Now.ID['license_renewal_notification'], name: 'Software License Renewal Approaching', table: 'x_snc_itasset_software_license', triggerConditions: { generationType: 'event', eventName: 'x_snc_itasset.lic_renewal', }, recipientDetails: { eventParm1WithRecipient: true }, emailContent: { subject: 'Action Required: License "\${software_name}" Expires in 30 Days', messageHtml: `<p>Expiration Date: \${expiration_date}</p>`, }, })
The scheduled script fires the event daily at 06:00 UTC, passing the record creator's username as parm1 so eventParm1WithRecipient resolves to the right Asset Manager:
// src/server/scheduled/check-license-renewals.js (IIFE — modules not supported here) (function checkLicenseRenewals() { var targetDate = new GlideDate() targetDate.addDaysUTC(30) var gr = new GlideRecord('x_snc_itasset_software_license') gr.addQuery('expiration_date', targetDate.getValue()) gr.addQuery('renewal_status', 'active') gr.query() while (gr.next()) { gs.eventQueue( 'x_snc_itasset.lic_renewal', gr, gr.getValue('sys_created_by'), // parm1 → recipient gr.getValue('software_name') ) } })()
The SDK uses an environment variable SN_SDK_NODE_ENV=SN_SDK_CI_INSTALL to activate non-interactive CI mode, where credentials are read from environment variables instead of a stored keychain entry. We store credentials in a .env file (gitignored) and source it in a deploy script:
# .env (gitignored — never commit credentials)
SN_SDK_NODE_ENV=SN_SDK_CI_INSTALL
SN_SDK_INSTANCE_URL=https://dev351321.service-now.com
SN_SDK_USER=admin
SN_SDK_USER_PWD=your_password_here
#!/usr/bin/env bash # deploy.sh export $(grep -v '^#' .env | xargs) npx @servicenow/sdk build npx @servicenow/sdk install
$ bash deploy.sh
[now-sdk] Build completed successfully
[now-sdk] Running in CI mode, using instance https://dev351321.service-now.com
[now-sdk] Starting installation...
[now-sdk] Attempting to log into instance https://dev351321.service-now.com as admin.
[now-sdk] Installation completed.
[now-sdk] Access the application at:
https://dev351321.service-now.com/sys_app.do?sys_id=6b30759afde9413999535f0b0a56572c
The traditional workflow for building an app of this scope in Studio would involve navigating to seven or eight different sections of the platform: Tables, Dictionary, Roles, ACLs, Business Rules, Email Notifications, Scheduled Jobs, Event Registry. Each record is created separately by filling out form fields. It is reliable and well-understood, but it is also inherently sequential and non-reproducible — there is no file you can check into git that recreates the app from scratch on a new instance.
The agentic workflow collapses this into a conversation. Claude Code:
What the Agent Did Not Do: It did not hallucinate ServiceNow APIs. It fetched documentation from the installed SDK before writing each artifact type. When it encountered an error (the env var credential issue), it read the SDK source code to find the root cause rather than guessing. This is the distinction between an agent that knows a platform and one that pretends to know it.
| Task | Studio (Manual) | Claude Code + SDK (Agentic) |
|---|---|---|
| Define 3 tables with 30+ fields | Navigate to each table, add columns one by one via forms | 3 .now.ts files, all fields typed and documented |
| Create 12 ACL rules | 12 separate form submissions in Security → Access Controls | One acls.now.ts file, roles imported and reused |
| Write 2 before-BR validations | Script editor in browser, no type hints, no linting | Typed JS module with @servicenow/glide imports and IDE autocompletion |
| Set up event + notification pipeline | Event Registry → Business Rule → Email Notification — 3 separate sections | 3 Fluent definitions in 2 files, cross-referenced by export |
| Recreate on a second instance | Repeat all of the above manually, or manage update sets | bash deploy.sh — same app, clean install |
| Code review | Screenshot comparisons, XML update set diffs | Standard git diff, pull request, inline comments |
The SDK and Studio are genuinely complementary. Neither replaces the other for all scenarios:
now-sdk init --from <sys_id> to pull it locally for iterative development with Claude Code.Install Node.js 20+, then: npm install -g @servicenow/sdk. Verify with now-sdk --version.
curl -fsSL https://claude.ai/install.sh | bash (Mac/Linux) or the Windows PowerShell installer. Then inside Claude Code: /plugin marketplace add servicenow/sdk, /plugin install fluent, /reload-plugins.
Create a PRD.md at your project root with: purpose, users/roles, tables and fields, business rules, and integration requirements. This is the single source of truth the agent will reference throughout development.
Run npx @servicenow/sdk init --appName "..." --scopeName "x_<co>_<app>", then tell Claude Code: "read @PRD.md and build the ServiceNow app." The agent reads SDK docs, writes all source files, and runs the build.
Create a .env file with your PDI credentials and SN_SDK_NODE_ENV=SN_SDK_CI_INSTALL, then run bash deploy.sh. The app installs on your instance and Studio shows the full scoped app.
Edit .now.ts files or server scripts, run now-sdk build to validate, and now-sdk install to push changes. Use git for branching, code review, and history. Repeat.
src/server/ support ES imports and typed Glide APIs. Scheduled script bodies must use IIFEs or Now.include() — a platform-specific nuance the agent knows from the docs.SN_SDK_NODE_ENV=SN_SDK_CI_INSTALL flag is required for non-interactive deployments; without it the SDK ignores env var credentials even when they are correctly set.npx @servicenow/sdk explain --list --format=raw (versioned with SDK, always current)npx @servicenow/sdk explain fluent-overview --format=raw@servicenow/sdk on npm