HR Leave · Australia

14 — AI in ServiceNow + Agents

Platform AI features after core Studio app (01–12) exists.

Scopex_786686_hr_leave
sys_ide5f5bc9493a303507520703efaba104d
Instance labdev398980
URL token{BASE}
Quick open Visual map Now Assist

Visual map — Ch.14 · AI — after core works

See in 10 seconds

Now Assist / VA / Agent Studio / Control Tower

You build

Optional layer

Track

Development

E2EMust be green
→
AGENTTools
→
ACLInvoking user
→
TOWERRegister
✓ GlideRecordSecure✓ Read-mostly tools✗ AI before ACLs✗ Tool writes u_state

Full visual path (all chapters): VISUAL_FROM_SCRATCH_00_16.html

Studio-only for core app: Create chapters 01 through 12 first. AI configuration uses ServiceNow platform UI (Now Assist, AI Agent Studio, Virtual Agent).

Also open: Properties + Direct Links · Schema · Studio Create All Objects · Previous: 13 Summary

Prerequisite: All tables, BR, Flow, and ACLs must exist on the instance before enabling AI features.

How AI features relate to HR Leave

Core app (ch.01–12) — tables, BR, Flow, ACLs
        │
        ▼
Platform AI (this chapter) — Now Assist, Agents, VA, Search
        │
        ▼
Optional: HR Leave skills/topics referencing req_v2 / bal_v2 data

AI layers sit on top of the scoped app — they do not replace Studio create steps in chapters 01–12.


Rule 0 — Before any object (Application + Update Set + Studio)

Repeat these checks before creating or editing any application file. This section is also section 00 Update Set — create the capture set first.

  1. Application picker — top-right globe / application menu → select HR Leave (x_786686_hr_leave). Never leave Global selected when creating scoped artifacts.
  2. Update Set — All → System Update Sets → Local Update Sets → New:
    FieldValue
    NameHR Leave – Build
    ApplicationHR Leave
    StateIn Progress
    DescriptionCaptures all HR Leave lab artifacts
    After submit: open the record → click Make Current. Direct list: {BASE}/sys_update_set_list.do
  3. Open Studio — {BASE}/$studio.do → confirm header shows HR Leave.

If artifacts land in Global scope, delete them and recreate under HR Leave. ACLs and events created globally will not behave correctly for this app.

Verify Update Set: Create a test Script Include in Studio → open HR Leave – Build → Related List Customer Updates shows the new file.


Deep-dive sections below — original AI implementation guide content.


14 — AI in ServiceNow + Agents — Complete Implementation Guide

اقرأ أولاً (ملخص سريع): MASTER_ALL_IN_ONE_SUMMARY.md · HTML: html/MASTER_ALL_IN_ONE_SUMMARY.html
الدليل الشامل الواحد: MASTER_ALL_IN_ONE.md · HTML: html/MASTER_ALL_IN_ONE.html
ممارسة الشاشات (New/Open): MASTER_PRACTICE_GUIDE_ALL_TOPICS.md · html/MASTER_PRACTICE_GUIDE_ALL_TOPICS.html
Platform: ServiceNow Australia · Scope x_786686_hr_leave · sys_id e5f5bc9493a303507520703efaba104d

دليل الذكاء الاصطناعي والوكلاء — تنفيذ كامل من الصفر إلى الإنتاج

Platform: ServiceNow Australia (September 2026) · Next EA: Brazil
App: Custom · Scope: x_786686_hr_leave · sys_id: e5f5bc9493a303507520703efaba104d
Tables: x_786686_hr_leave_employee_v2, x_786686_hr_leave_req_v2, x_786686_hr_leave_bal_v2, x_786686_hr_leave_audit_v2
URL pattern: {BASE} = https://YOUR_INSTANCE.service-now.com


Table of Contents

  1. What You Will Build
  2. Direct Navigation URLs
  3. Part 0 — Quick Map & Prerequisites
  4. Part 1 — Plugin Activation & Roles
  5. Part 2 — Now Assist Studio (Skills)
  6. Part 3 — AI Agent Studio
  7. Part 4 — BYO LLM (Claude / GPT)
  8. Part 5 — AI Search + GenAI Search
  9. Part 6 — Predictive Intelligence
  10. Part 7 — Virtual Agent + NLU (Full Topics & Flows)
  11. Part 8 — Document Intelligence (IDP)
  12. Part 9 — Workflow Studio AI Actions
  13. Part 10 — Now Assist for Developers
  14. Part 11 — End-to-End HR Leave AI Example
  15. Part 12 — AI Governance & Safety
  16. Part 13 — Performance & Cost Optimization
  17. Part 14 — Hands-On Labs (5 Sessions)
  18. Part 15 — Best Practices
  19. Part 16 — Production Deployment Checklist
  20. Appendices

🎯 What You Will Build — ماذا ستبني

By the end of this guide you will have deployed a complete AI layer on the HR Leave scoped app:

Style in this doc: English instruction line → Arabic explanation on its own line where helpful. All code in fenced blocks.


📍 Direct Navigation URLs — روابط التنقل المباشرة

Replace {BASE} with your instance URL (e.g. https://dev12345.service-now.com).

Now Assist & AI Agents

Tool Navigation Path Direct URL Purpose
Now Assist Admin All > Now Assist > Now Assist Admin {BASE}/now/assist/admin Skill setup wizard
Now Assist Studio App Picker > Now Assist Studio {BASE}/now/assist/studio Create/edit skills
Now Assist Skills Now Assist Admin > Skills {BASE}/sys_one_extend_skill_list.do Skill records
Prompt Templates (Skill) Templates related list {BASE}/sys_one_extend_prompt_template_list.do Versioned prompts
Skill Audit Log Now Assist Admin > Audit {BASE}/sys_one_extend_audit_list.do Execution telemetry
AI Agent Studio All > AI Agent Studio {BASE}/now/aia/studio Build agents + tools
AI Agents AI Agent Studio > Agents {BASE}/sn_aia_agent_list.do Agent definitions
AI Tools AI Agent Studio > Tools {BASE}/sn_aia_tool_list.do Callable tools
Agent Executions AI Agent Studio > Executions {BASE}/sn_aia_execution_list.do Run history
LLM Provider Config Now Assist Admin > LLM Providers {BASE}/sys_one_extend_provider_config_list.do BYO LLM setup
AI Policy Center All > AI Governance > AI Policy Center {BASE}/now/ai/policy Policies & rules
Tool Navigation Path Direct URL Purpose
AI Search Admin All > AI Search > Admin {BASE}/now/ais/admin Search admin home
Search Sources AI Search Admin > Sources {BASE}/ais_search_source_list.do Index sources
Search Profiles AI Search Admin > Profiles {BASE}/ais_search_profile_list.do Profile config
Search Applications AI Search Admin > Applications {BASE}/ais_search_application_list.do Portal/Workspace UI
Query Log AI Search Admin > Analytics {BASE}/sys_aisearch_query_log_list.do Zero-result analysis
GenAI Search Log AI Search Admin > GenAI Log {BASE}/sys_aisearch_genai_log_list.do RAG answers

Predictive Intelligence

Tool Navigation Path Direct URL Purpose
Solution Definitions All > Predictive Intelligence > Solution Definitions {BASE}/ml_solution_definition_list.do Define ML problem
Solutions All > Predictive Intelligence > Solutions {BASE}/ml_solution_list.do Trained models
Solution Monitor All > Predictive Intelligence > Solution Monitor {BASE}/ml_solution_monitor_list.do Drift & accuracy
Training Dataset (Solution) Training Dataset {BASE}/ml_capability_definition_base_list.do Feature mapping

Virtual Agent & NLU

Tool Navigation Path Direct URL Purpose
Virtual Agent Designer All > Virtual Agent > Designer {BASE}/now/virtual-agent/designer Topic builder
Topics Virtual Agent > Topics {BASE}/sys_cs_topic_list.do Topic records
Conversations Virtual Agent > Conversations {BASE}/sys_cs_conversation_list.do Chat logs
NLU Workbench All > NLU > Workbench {BASE}/now/nlu/workbench Intent/entity models
NLU Models NLU > Models {BASE}/nlu_model_list.do Model list
NLU Intents (Model) Intents {BASE}/nlu_intent_list.do Intent definitions
Employee Center Direct {BASE}/esc Test VA in prod-like UI
Service Portal Direct {BASE}/sp?id=chat Portal chat widget

Document Intelligence

Tool Navigation Path Direct URL Purpose
IDP Admin All > Document Intelligence {BASE}/now/idp/admin IDP home
Templates IDP Admin > Templates {BASE}/sn_idp_template_list.do Document templates
Extraction Models IDP Admin > Models {BASE}/sn_idp_model_list.do Trained extractors
Extraction Results IDP Admin > Results {BASE}/sn_idp_extraction_result_list.do Run output

HR Leave App Tables (Grounding & Tools)

Table Direct URL Key Fields for AI
Leave Request {BASE}/x_786686_hr_leave_req_v2_list.do u_leave_type, u_state, u_reason, u_days_count
Employee {BASE}/x_786686_hr_leave_employee_v2_list.do u_employee_id, user reference
Balance {BASE}/x_786686_hr_leave_bal_v2_list.do u_leave_type, u_remaining_days
Audit {BASE}/x_786686_hr_leave_audit_v2_list.do u_action, u_payload
Knowledge (policy) {BASE}/kb_knowledge_list.do?sysparm_query=topic=HR Leave text, short_description

Development & Deployment

Tool Direct URL
Studio {BASE}/$studio.do
Script Includes {BASE}/sys_script_include_list.do?sysparm_query=sys_scope.scope=x_786686_hr_leave
Business Rules {BASE}/sys_script_list.do?sysparm_query=sys_scope.scope=x_786686_hr_leave
Flow Designer {BASE}/now/flow-designer
Update Sets {BASE}/sys_update_set_list.do
Background Scripts {BASE}/sys.scripts.do
System Properties {BASE}/sys_properties_list.do?sysparm_query=nameSTARTSWITHx_786686_hr_leave
Plugins {BASE}/v_plugin_list.do

Part 0 — Quick Map & Prerequisites

0.1 Decision matrix — which AI tool when?

User need Best tool Why Section
One-click summary on form Now Assist Skill Deterministic, cheap, fast §2
“How many days left?” in chat Virtual Agent topic OR AI Agent tool VA = predictable; Agent = flexible §3, §7
Open-ended policy Q&A AI Search GenAI + Agent RAG with citations §3, §5
Predict if manager approves in 24h Predictive Intelligence Classical ML on history §6
Extract fields from medical PDF Document Intelligence Structured extraction §8
Multi-step: check balance → request → confirm AI Agent Studio Plans + tools + memory §3
Classify free-text leave reason Now Assist Skill OR PI Skill = LLM; PI = ML on features §2, §6
Code a Business Rule faster Now Assist for Developers In-Studio codegen §10

ابدأ بـ Skill للمهام أحادية الخطوة. انتقل إلى Agent عندما يحتاج المستخدم محادثة متعددة الخطوات مع أدوات.

0.2 Prerequisites checklist

Before starting any AI work:

[ ] HR Leave v2 tables exist and have ≥ 50 test leave requests
[ ] Roles assigned: x_786686_hr_leave.employee, .manager, .hr_admin
[ ] Update Set created: "HR Leave AI v1.0"
[ ] Application picker set to HR Leave (x_786686_hr_leave) in Studio
[ ] At least 5 KB articles tagged topic=HR Leave (for AI Search)
[ ] Integration user NOT used for AI testing — use real employee personas
[ ] Instance has outbound HTTPS to LLM APIs (if BYO) — check ACL network rules
[ ] Admin access to activate plugins (requires admin role)

0.3 Verify app scope (Background Script)

URL: {BASE}/sys.scripts.do

var app = new GlideRecord('sys_app');
app.addQuery('scope', 'x_786686_hr_leave');
app.query();
if (app.next()) {
    gs.info('App: ' + app.name + ' | sys_id: ' + app.sys_id);
} else {
    gs.error('HR Leave app not found — create via 01_DEVELOPMENT.md first');
}

var tables = ['x_786686_hr_leave_req_v2', 'x_786686_hr_leave_bal_v2',
              'x_786686_hr_leave_employee_v2', 'x_786686_hr_leave_audit_v2'];
tables.forEach(function (t) {
    var gr = new GlideRecord(t);
    gs.info(t + ' exists: ' + gr.isValid());
});

Part 1 — Plugin Activation & Roles

Step 1.1: Activate required plugins

Navigation: All > System Definition > Plugins — Open direct
Direct URL: {BASE}/v_plugin_list.do

# Plugin name (search) Plugin ID (typical) Required for
1 Now Assist for HRSD com.snc.now_assist.hrsd HR skills pack
2 Now Assist Platform com.snc.now_assist.platform Core GenAI
3 AI Agents com.snc.ai_agents Agent Studio
4 AI Search com.snc.ai_search Modern search + RAG
5 Predictive Intelligence com.glide.platform_ml ML solutions
6 Document Intelligence com.snc.document_intelligence IDP
7 Virtual Agent com.glide.cs.chatbot Chatbot topics
8 NLU Workbench com.snc.nlu_workbench Intent models
9 Now Assist for Creator com.snc.now_assist.creator Dev codegen (optional)

Detailed activation steps:

1. Open {BASE}/v_plugin_list.do
2. Filter: Name contains "Now Assist" OR "AI Search" OR "Virtual Agent"
3. For each plugin in the table above:
   a. Click the plugin name
   b. Click "Activate" (or "Install" on some instances)
   c. UNCHECK "Load demo data" in production-like sub-prod
   d. Wait for activation (may take 2–10 minutes)
   e. Note any dependent plugins auto-activated
4. After all activations: logout and login (refresh session roles)
5. Open Now Assist Setup wizard: {BASE}/now/assist/admin
6. Accept terms → select data region → Enable HRSD skill pack
7. Verify: All > Now Assist > Now Assist Admin shows "Configured"

Step 1.2: Assign AI admin roles

Navigation: All > User Administration > Users — Open direct
Direct URL: {BASE}/sys_user_list.do

Role Assign to Purpose
sn_nowassist_admin AI lead developer Skills, providers
sn_aia.admin AI lead developer Agent Studio
ai_search_admin Search admin AI Search profiles
ml_admin Data/ML owner Train PI solutions
nlu_admin Chatbot owner NLU models
sn_idp.admin Doc processing owner IDP templates
x_786686_hr_leave.hr_admin HR team Use AI on records
x_786686_hr_leave.manager Managers Summarize UI Action

Step 1.3: Create system properties (AI config)

Navigation: All > System Properties — Open direct
Direct URL: {BASE}/sys_properties_list.do

Create these properties in scope x_786686_hr_leave:

Name Type Default Description
x_786686_hr_leave.ai.enabled true/false true Master kill switch
x_786686_hr_leave.llm.daily_budget_usd string 10 Daily spend cap
x_786686_hr_leave.llm.timeout_ms string 15000 REST timeout
x_786686_hr_leave.llm.anthropic.api_key password2 (empty) Claude key
x_786686_hr_leave.llm.anthropic.model string claude-sonnet-4-5 Model id
x_786686_hr_leave.llm.openai.api_key password2 (empty) OpenAI key
x_786686_hr_leave.llm.openai.model string gpt-4o-mini Model id
x_786686_hr_leave.ai_search.profile string hrlx_kb_profile Default profile
x_786686_hr_leave.nlu.model string hrlx_leave_nlu NLU model name
x_786686_hr_leave.idp.template string hrlx_medical_cert IDP template
x_786686_hr_leave.va.bot_name string HR Leave Bot Display name

Verification script:

var props = ['ai.enabled', 'llm.daily_budget_usd', 'ai_search.profile'];
props.forEach(function (p) {
    var v = gs.getProperty('x_786686_hr_leave.' + p, 'NOT SET');
    gs.info('x_786686_hr_leave.' + p + ' = ' + v);
});

Part 2 — Now Assist Studio (Skills)

2.1 Architecture overview

Object Table Purpose
Skill sys_one_extend_skill One GenAI capability
Prompt template sys_one_extend_prompt_template Versioned prompt text
Activation sys_one_extend_activation Where skill is enabled
Audit sys_one_extend_audit Every execution logged

Step 2.1: Open Now Assist Studio

URL: {BASE}/now/assist/studio

1. App picker (top-left) → select "HR Leave" scope
2. Click "Skills" in left nav
3. Click "New" → "Create Skill"
4. Confirm Application = x_786686_hr_leave on every record

Step 2.2: Skill 1 — hrlx_summarize_reason

Field Value
Name hrlx_summarize_reason
Label Summarize Leave Reason
Type Summarization
Application HR Leave
LLM Now LLM Service (change to BYO in §4)
Max tokens 120
Temperature 0.2
PII redaction ON

Prompt template (SYSTEM + USER):

SYSTEM:
You are an HR assistant for a multinational company. Summarize the employee's
leave reason in ONE sentence, maximum 25 words, neutral professional tone.
Do NOT include medical diagnoses, medication names, or sensitive health details.
If reason is empty, return exactly: "No reason provided."
Respond in the same language as the reason text (English or Arabic).

USER:
Employee: {{employee_name}}
Leave type: {{u_leave_type}}
Start: {{u_start_date}} | End: {{u_end_date}} | Days: {{u_days_count}}
Reason:
"""
{{u_reason}}
"""

Variable mapping:

Variable Source field on x_786686_hr_leave_req_v2
employee_name u_requested_for_user (display)
u_leave_type u_leave_type
u_start_date u_start_date
u_end_date u_end_date
u_days_count u_days_count
u_reason u_reason

Grounding config:

1. Skill > Grounding tab > Enable
2. Table: x_786686_hr_leave_req_v2
3. Key: sys_id
4. Map each {{variable}} to column above
5. Save

Test in Playground (5 samples):

# u_reason input Expected output quality
1 “Family wedding in Dubai, need 4 days travel” Mentions wedding/travel, no PII
2 “Flu — doctor advised rest” Generic “medical rest”, no diagnosis
3 (empty) “No reason provided.”
4 Arabic: “إجازة أمومة” Arabic one-liner
5 500-word essay ≤ 25 words
Playground steps:
1. Skills > hrlx_summarize_reason > Test
2. Paste sys_id of test request OR fill variables manually
3. Run → check latency (target ≤ 2s)
4. If bad output → edit prompt → Save as version 1.1
5. Repeat until 90%+ acceptable on 20 samples
6. Status → Active

Step 2.3: Skill 2 — hrlx_classify_leave_type

Field Value
Name hrlx_classify_leave_type
Type Classification
Output validation Regex: ^(annual\|sick\|parental\|unpaid)$
SYSTEM:
Classify the leave request text into EXACTLY ONE label:
annual, sick, parental, unpaid
Return ONLY the label, lowercase, no punctuation or explanation.

USER:
Leave type already selected (may be wrong): {{u_leave_type}}
Employee reason: {{u_reason}}
Additional notes: {{u_notes}}

Wire to Business Rule (before insert/update when u_leave_type empty):

(function executeRule(current, previous) {
    if (!gs.getProperty('x_786686_hr_leave.ai.enabled', 'true') === 'true') return;
    if (current.u_leave_type) return;
    if (!current.u_reason) return;

    try {
        var ext = new sn_one_extend.OneExtendUtil();
        var res = ext.execute({
            executionRequests: [{
                capabilityId: 'hrlx_classify_leave_type',
                payload: {
                    u_leave_type: String(current.u_leave_type),
                    u_reason: String(current.u_reason),
                    u_notes: String(current.u_notes || '')
                }
            }]
        });
        var label = (res.capabilities[0] || {}).response;
        if (/^(annual|sick|parental|unpaid)$/.test(label))
            current.u_leave_type = label;
    } catch (e) {
        gs.warn('hrlx_classify_leave_type failed: ' + e);
    }
})(current, previous);

Step 2.4: Skill 3 — hrlx_suggest_dates

Field Value
Name hrlx_suggest_dates
Type Generic / Structured output
Output schema JSON Schema (see §12)
SYSTEM:
Suggest adjusted leave dates avoiding public holidays.
Return ONLY valid JSON:
{"start":"YYYY-MM-DD","end":"YYYY-MM-DD","notes":"..."}
No markdown fences.

USER:
Country: {{u_country}}
Requested start: {{u_start_date}}
Requested end: {{u_end_date}}
Leave type: {{u_leave_type}}
Public holidays next 90 days:
{{holidays_json}}

Pre-step Script Include to build holidays_json:

var HRLXHolidayUtil = Class.create();
HRLXHolidayUtil.prototype = {
    initialize: function() {},
    getHolidaysJson: function(country, days) {
        // Replace with your holiday table or IntegrationHub spoke
        var out = [];
        var gr = new GlideRecord('sn_hr_core_federal_holiday'); // if HRSD installed
        if (gr.isValid()) {
            gr.addQuery('country', country);
            gr.addQuery('date', '>=', new GlideDate());
            gr.setLimit(days || 90);
            gr.query();
            while (gr.next()) {
                out.push({ date: String(gr.date), name: String(gr.name) });
            }
        }
        return JSON.stringify(out);
    },
    type: 'HRLXHolidayUtil'
};

Step 2.5: Skill 4 — hrlx_summarize_history

Summarizes last N leave requests for a manager email.

SYSTEM:
Summarize this employee's leave history for a manager briefing.
Max 150 words. Bullet format. Include totals by type. Neutral tone.

USER:
Employee: {{employee_name}}
Lookback days: {{lookback_days}}
History records:
{{history_text}}

Step 2.6: Skill 5 — hrlx_detect_sentiment

SYSTEM:
Classify employee leave reason sentiment: positive, neutral, frustrated, urgent.
Return ONLY the label.

USER:
Reason: {{u_reason}}

Use output to route frustrated → human HR in Flow Designer.

Step 2.7: Skill 6 — hrlx_draft_manager_email

SYSTEM:
Draft a short email from HR system to employee about their leave request.
Professional, empathetic. Max 120 words. Include request number and dates.
Do not invent approval status — use {{u_state}} exactly.

USER:
Employee name: {{employee_name}}
Request: {{u_number}}
Type: {{u_leave_type}}
Dates: {{u_start_date}} to {{u_end_date}}
State: {{u_state}}
Manager note: {{manager_comment}}

Step 2.8: Activate skills per channel

URL: {BASE}/sys_one_extend_activation_list.do

For each skill create activation:

Skill Channels enabled
hrlx_summarize_reason Workspace, UI Action, Flow Designer
hrlx_classify_leave_type Business Rule (server), Flow Designer
hrlx_suggest_dates Service Portal widget
hrlx_summarize_history Flow Designer
hrlx_detect_sentiment Flow Designer
hrlx_draft_manager_email Workspace

Step 2.9: UI Action — Summarize on form

URL: {BASE}/sys_ui_action_list.do

Field Value
Name Summarize reason (AI)
Table x_786686_hr_leave_req_v2
Condition current.u_state != 'cancelled' && gs.hasRole('x_786686_hr_leave.manager')
Form button true
Client false (server-side)
(function executeAction(current) {
    var ext = new sn_one_extend.OneExtendUtil();
    var res = ext.execute({
        executionRequests: [{
            capabilityId: 'hrlx_summarize_reason',
            payload: { record: current.getUniqueValue() }
        }]
    });
    var summary = (res.capabilities[0] || {}).response || 'No summary';
    gs.addInfoMessage('AI Summary: ' + summary);
})(current);

Part 3 — AI Agent Studio

3.1 What AI Agent Studio provides

AI Agent Studio builds agentic assistants: an LLM that plans steps, selects tools, executes them, observes results, and responds — across multiple conversation turns.

Table Purpose
sn_aia_agent Agent definition + system prompt
sn_aia_tool Callable action (Script Include, Flow, AI Search)
sn_aia_team Multi-agent routing
sn_aia_trigger Chat, email, record, schedule triggers
sn_aia_execution One run (tokens, latency, cost)
sn_aia_execution_step Each tool invocation
sn_aia_audit Compliance-grade immutable log

Direct URL: {BASE}/now/aia/studio

Step 3.1: Create Script Include HRLXAIAgentTools

URL: {BASE}/sys_script_include_list.do
Application: HR Leave

Field Value
Name HRLXAIAgentTools
Client callable false
Accessible from This application scope only
var HRLXAIAgentTools = Class.create();
HRLXAIAgentTools.prototype = {
    initialize: function() {
        this.SCOPE = 'x_786686_hr_leave';
        this.T_EMP = 'x_786686_hr_leave_employee_v2';
        this.T_REQ = 'x_786686_hr_leave_req_v2';
        this.T_BAL = 'x_786686_hr_leave_bal_v2';
        this.T_AUD = 'x_786686_hr_leave_audit_v2';
    },

    _getEmployeeByUser: function(userId) {
        var gr = new GlideRecord(this.T_EMP);
        gr.addQuery('user', userId);
        gr.setLimit(1);
        gr.query();
        return gr.next() ? gr : null;
    },

    getBalance: function(userId) {
        var emp = this._getEmployeeByUser(userId);
        if (!emp) return { error: 'employee_not_found' };
        var out = { annual: 0, sick: 0, parental: 0, unpaid: 0 };
        var bal = new GlideRecord(this.T_BAL);
        bal.addQuery('u_employee_ref', emp.getUniqueValue());
        bal.query();
        while (bal.next()) {
            var t = String(bal.u_leave_type);
            if (out.hasOwnProperty(t)) out[t] = Number(bal.u_remaining_days) || 0;
        }
        return out;
    },

    requestLeave: function(payload) {
        try {
            if (gs.getProperty(this.SCOPE + '.ai.enabled', 'true') !== 'true')
                return { ok: false, error: 'ai_disabled' };

            var emp = this._getEmployeeByUser(payload.user_id);
            if (!emp) return { ok: false, error: 'employee_not_found' };

            var start = new GlideDateTime(payload.start_date);
            var end = new GlideDateTime(payload.end_date);
            if (start.compareTo(end) > 0)
                return { ok: false, error: 'start_after_end' };

            var bal = this.getBalance(payload.user_id);
            var days = Math.ceil((end.getNumericValue() - start.getNumericValue()) / 86400000) + 1;
            if ((bal[payload.type] || 0) < days)
                return { ok: false, error: 'insufficient_balance', needed: days, available: bal[payload.type] || 0 };

            var req = new GlideRecord(this.T_REQ);
            req.initialize();
            req.u_requested_for_user = payload.user_id;
            req.u_employee_ref = emp.getUniqueValue();
            req.u_leave_type = payload.type;
            req.u_start_date = payload.start_date;
            req.u_end_date = payload.end_date;
            req.u_reason = payload.reason || '';
            req.u_state = 'submitted';
            req.u_source = 'ai_agent';
            var sysId = req.insert();
            this._audit('ai_request_leave', sysId, payload);
            return { ok: true, request_id: sysId, number: req.getValue('u_number') };
        } catch (e) {
            gs.error('HRLXAIAgentTools.requestLeave: ' + e);
            return { ok: false, error: 'exception' };
        }
    },

    checkPolicy: function(question) {
        var profile = gs.getProperty(this.SCOPE + '.ai_search.profile', 'hrlx_kb_profile');
        try {
            var sn = new sn_ais.AISearch();
            var results = sn.search(profile, question, { limit: 5, genai: true });
            return {
                answer: results.genai_answer || '',
                citations: results.citations || []
            };
        } catch (e) {
            return { answer: '', citations: [], error: String(e) };
        }
    },

    escalate: function(userId, summary) {
        var emp = this._getEmployeeByUser(userId);
        if (!emp) return { ok: false, error: 'employee_not_found' };
        var hr = new GlideRecord('sn_hr_core_case');
        if (!hr.isValid()) {
            // Fallback: create audit + notify
            this._audit('ai_escalate_no_hrsd', userId, { summary: summary });
            return { ok: true, case_id: null, note: 'HRSD not installed — audit only' };
        }
        hr.initialize();
        hr.opened_for = userId;
        hr.short_description = 'AI escalation: ' + (summary || '').substring(0, 80);
        hr.description = summary;
        hr.subject_person = userId;
        var sysId = hr.insert();
        this._audit('ai_escalate', sysId, { summary: summary });
        return { ok: true, case_id: sysId };
    },

    getMyRequests: function(userId, days) {
        var emp = this._getEmployeeByUser(userId);
        if (!emp) return [];
        var since = new GlideDateTime();
        since.addDaysLocalTime(-1 * (days || 90));
        var gr = new GlideRecord(this.T_REQ);
        gr.addQuery('u_employee_ref', emp.getUniqueValue());
        gr.addQuery('sys_created_on', '>=', since);
        gr.orderByDesc('sys_created_on');
        gr.query();
        var out = [];
        while (gr.next()) {
            out.push({
                id: gr.getUniqueValue(),
                number: String(gr.u_number),
                type: String(gr.u_leave_type),
                start: String(gr.u_start_date),
                end: String(gr.u_end_date),
                state: String(gr.u_state)
            });
        }
        return out;
    },

    cancelRequest: function(userId, requestId) {
        var gr = new GlideRecord(this.T_REQ);
        if (!gr.get(requestId)) return { ok: false, error: 'not_found' };
        if (gr.u_requested_for_user != userId) return { ok: false, error: 'not_owner' };
        if (gr.u_state != 'submitted') return { ok: false, error: 'not_cancellable' };
        gr.u_state = 'cancelled';
        gr.update();
        this._audit('ai_cancel_request', requestId, { user: userId });
        return { ok: true };
    },

    _audit: function(action, recordId, payload) {
        var a = new GlideRecord(this.T_AUD);
        a.initialize();
        a.u_action = action;
        a.u_record = recordId;
        a.u_payload = JSON.stringify(payload || {});
        a.u_actor = gs.getUserID();
        a.u_source = 'ai_agent';
        a.insert();
    },

    type: 'HRLXAIAgentTools'
};

Step 3.2: Define tools in AI Agent Studio

URL: {BASE}/sn_aia_tool_list.do

Tool 1 — GetMyBalance

Field Value
Name GetMyBalance
Description Returns current user’s leave balance by type (annual, sick, parental, unpaid)
Implementation Script Include
Script Include HRLXAIAgentTools
Method getBalance
Input user_id (string) — auto-map from session
Output JSON object with balances

Tool 2 — RequestLeave

Input field Type Required
user_id string yes
type string (enum) yes
start_date date (YYYY-MM-DD) yes
end_date date (YYYY-MM-DD) yes
reason string no

Confirmation gate: Enable “Require user confirmation” for this tool in Agent Studio.

Tool 3 — CheckPolicy

Field Value
Implementation AI Search Profile OR Script
Profile hrlx_kb_profile
Input question (string)

Tool 4 — GetMyRequests

| Method | getMyRequests |
| Input | user_id, days (default 90) |

Tool 5 — CancelRequest

| Method | cancelRequest |
| Input | user_id, request_id |

Tool 6 — EscalateToHR

| Method | escalate |
| Input | user_id, summary |

Step 3.3: Create agent “HR Leave Assistant”

URL: {BASE}/sn_aia_agent_list.do

Field Value
Name HR Leave Assistant
Application x_786686_hr_leave
Model now-llm-pro-v1
LLM Provider Now LLM Service
Status Draft → Active

System prompt:

You are "HR Leave Assistant" for employees of this company.

CAPABILITIES (use tools):
- GetMyBalance: show remaining leave days
- RequestLeave: submit a new request (ALWAYS confirm dates/type first)
- CheckPolicy: answer policy questions from official KB (cite sources)
- GetMyRequests: list recent requests
- CancelRequest: cancel a submitted request owned by the user
- EscalateToHR: create HR case when user is frustrated or issue is complex

RULES:
1. Identity comes from session — never ask for employee ID number.
2. NEVER reveal another employee's data.
3. Out of scope → "I can only help with leave. Contact HR at [email protected]."
4. Match user language (English or Arabic).
5. Before RequestLeave: summarize dates, type, days count, ask "Shall I submit?"
6. If tool returns error insufficient_balance, explain clearly with numbers.
7. For medical/sick policy, remind user a certificate may be required.

STYLE: concise, friendly, professional. Use bullet lists for balances.

Agent JSON export reference:

{
  "name": "HR Leave Assistant",
  "scope": "x_786686_hr_leave",
  "model": "now-llm-pro-v1",
  "tools": ["GetMyBalance", "RequestLeave", "CheckPolicy", "GetMyRequests", "CancelRequest", "EscalateToHR"],
  "knowledge_sources": [{ "type": "ai_search_profile", "name": "hrlx_kb_profile" }],
  "triggers": [
    { "type": "chat", "channel": "employee_center" },
    { "type": "chat", "channel": "service_portal" }
  ],
  "memory": { "session": true, "persistent": { "enabled": true, "max_turns": 8 } },
  "guardrails": {
    "pii_redaction": true,
    "escalation_keywords": ["urgent", "complaint", "discrimination", "harassment", "lawyer"]
  },
  "audit": { "store_inputs": true, "store_outputs": true, "retention_days": 365 }
}

Step 3.4: Enable agent on Employee Center

1. Open {BASE}/now/assist/admin
2. Channels > Employee Center
3. Enable "AI Agents"
4. Add agent: HR Leave Assistant
5. Position: HR Leave category in chat launcher
6. Save
7. Test: {BASE}/esc → open chat → "How many annual days do I have?"

Step 3.5: Test agent (10 test utterances)

# User says Expected tool Pass criteria
1 “my balance” GetMyBalance Shows 4 types
2 “request 3 days annual next Mon-Wed” RequestLeave (after confirm) Creates req
3 “can I carry over leave?” CheckPolicy Cites KB
4 “show my last requests” GetMyRequests Lists records
5 “cancel HRLX0001234” CancelRequest State=cancelled
6 “what is parental leave?” CheckPolicy Policy answer
7 Arabic: “كم يوم إجازة عندي؟” GetMyBalance Arabic response
8 “I want 100 days annual” RequestLeave insufficient_balance error
9 “this is discrimination!” EscalateToHR Case created
10 “what’s the weather?” none Out of scope message

Part 4 — BYO LLM (Claude / GPT)

Step 4.1: When to use BYO LLM

Scenario Recommendation
Default Now Assist skills Now LLM Service
Regulated data residency Azure OpenAI in your region
Existing Anthropic/OpenAI contract BYO
Cost optimization at scale gpt-4o-mini for classify, Claude for complex

Step 4.2: Configure Anthropic provider

URL: {BASE}/sys_one_extend_provider_config_list.do

1. New > Provider type: Anthropic (or Generic REST)
2. Name: hrlx_anthropic
3. API endpoint: https://api.anthropic.com/v1/messages
4. Credential: link to Generic API Key credential (x-api-key)
5. Default model: claude-sonnet-4-5
6. Test connection
7. Per skill: LLM Provider = hrlx_anthropic

Step 4.3: REST Message — Claude_API

URL: {BASE}/sys_rest_message_list.do

Header Value
x-api-key ${x_786686_hr_leave.llm.anthropic.api_key}
anthropic-version 2023-06-01
content-type application/json

Body template:

{
  "model": "${model}",
  "max_tokens": ${max_tokens},
  "system": "${system}",
  "messages": [{ "role": "user", "content": "${user_message}" }]
}

Step 4.4: Script Include — HRLXAIProvider (fallback chain)

var HRLXAIProvider = Class.create();
HRLXAIProvider.prototype = {
    initialize: function() {
        this.SCOPE = 'x_786686_hr_leave';
        this.TIMEOUT_MS = parseInt(gs.getProperty(this.SCOPE + '.llm.timeout_ms', '15000'), 10);
    },

    _prop: function(name, def) { return gs.getProperty(this.SCOPE + '.' + name, def); },

    _budgetCheck: function(provider) {
        var budget = parseFloat(this._prop('llm.daily_budget_usd', '10'));
        var key = 'llm.spent.' + provider + '.' + new GlideDateTime().getDate().getDisplayValue();
        return parseFloat(gs.getProperty(this.SCOPE + '.' + key, '0')) < budget;
    },

    askClaude: function(prompt, model, maxTokens, system) {
        if (!this._budgetCheck('anthropic')) return { error: 'budget_exceeded' };
        try {
            var rm = new sn_ws.RESTMessageV2('Claude_API', 'post');
            rm.setHttpTimeout(this.TIMEOUT_MS);
            rm.setStringParameterNoEscape('model', model || this._prop('llm.anthropic.model', 'claude-sonnet-4-5'));
            rm.setStringParameterNoEscape('max_tokens', String(maxTokens || 400));
            rm.setStringParameterNoEscape('system', system || 'You are a helpful HR assistant.');
            rm.setStringParameterNoEscape('user_message', prompt);
            var resp = rm.execute();
            if (resp.getStatusCode() >= 400) return { error: 'http_' + resp.getStatusCode() };
            var json = JSON.parse(resp.getBody());
            var text = '';
            (json.content || []).forEach(function(c) { if (c.type === 'text') text += c.text; });
            return { text: text, usage: json.usage || {} };
        } catch (e) { return { error: 'exception', message: String(e) }; }
    },

    askWithFallback: function(prompt, options) {
        options = options || {};
        var chain = options.chain || ['anthropic', 'openai', 'now_llm'];
        for (var i = 0; i < chain.length; i++) {
            var res = (chain[i] === 'anthropic') ? this.askClaude(prompt, options.model, options.max_tokens, options.system) : null;
            if (res && !res.error && res.text) return res;
        }
        return { error: 'all_providers_failed' };
    },

    type: 'HRLXAIProvider'
};

Step 4.5: HRLXRagService (custom RAG)

var HRLXRagService = Class.create();
HRLXRagService.prototype = {
    initialize: function() {
        this.PROVIDER = new HRLXAIProvider();
        this.PROFILE = gs.getProperty('x_786686_hr_leave.ai_search.profile', 'hrlx_kb_profile');
    },

    answer: function(question) {
        var sn = new sn_ais.AISearch();
        var res = sn.search(this.PROFILE, question, { limit: 5, genai: true, min_similarity: 0.65 });
        if (res.genai_answer) return { text: res.genai_answer, citations: res.citations || [] };
        return { text: 'I could not find an answer in HR Leave policies.', citations: [] };
    },

    type: 'HRLXRagService'
};

5.1 AI Search vs Zing

Feature Zing AI Search
Vector search No Yes (RaptorDB)
GenAI answers No Yes
Re-ranking Basic ML re-ranker
Multi-source profiles Limited Native

Step 5.1: Create search source — hrlx_kb

URL: {BASE}/ais_search_source_list.do

1. New Search Source
2. Name: hrlx_kb
3. Table: kb_knowledge
4. Condition: topic=HR Leave^workflow_state=published^active=true
5. Indexed fields:
   - title (boost 2.0)
   - short_description (boost 1.5)
   - text (boost 1.0)
   - meta (boost 0.5)
6. Index transform script (PII mask):
(function transform(record, indexed) {
    indexed.title = record.short_description + '';
    var body = (record.text || '') + '';
    indexed.body = body.replace(/\b(SSN|PASSPORT|MRN|diagnosis)\b[: ]?\S+/gi, '[REDACTED]');
    indexed.u_kb_number = record.number + '';
    return indexed;
})(record, indexed);
7. Save → Full Index (wait for completion)
8. Verify: AI Search Admin > Index Status = Green

Step 5.2: Create source — hrlx_policy_attachments

Field Value
Name hrlx_policy_attachments
Table kb_knowledge (attachment text extraction)
Condition Same as hrlx_kb
Enable Attachment indexing

Step 5.3: Create profile — hrlx_kb_profile

URL: {BASE}/ais_search_profile_list.do

Setting Value
Name hrlx_kb_profile
Sources hrlx_kb, hrlx_policy_attachments
GenAI Search ON
LLM Now LLM Service
Max chunks 5
Min similarity 0.65
Chunk size 800
Chunk overlap 100
Refusal message “I cannot find the answer in HR Leave policies. Contact HR.”
Citation format KB number + title

Step 5.4: Create search application (Portal)

URL: {BASE}/ais_search_application_list.do

1. New Application: hrlx_portal_search
2. Profile: hrlx_kb_profile
3. UI: Service Portal
4. Placeholder: "Ask about leave policy, sick days, carry-over..."
5. Enable GenAI answer panel + citations
6. Link to page: {BASE}/sp?id=hrlx_policy_search

Widget HTML (Service Portal):

<div class="hrlx-aisearch">
  <sp-search
    profile="hrlx_kb_profile"
    placeholder="Ask about leave policy"
    show-genai-answer="true"
    show-citations="true">
  </sp-search>
</div>

Step 5.5: Boost rules & synonyms

Type Example
Synonym “PTO” = “annual leave” = “vacation”
Synonym “sick” = “medical” = “illness”
Boost u_leave_type field match × 1.3
Filter facet country, leave_type

URL for synonyms: {BASE}/ais_dictionary_term_list.do

Step 5.6: Search analytics dashboard

Build PA indicators from:

Table Metric
sys_aisearch_query_log Queries/day, zero-result rate
sys_aisearch_click_log Click-through rate
sys_aisearch_genai_log GenAI answer rate, citation count

Target: zero-result rate < 5% after 30 days.


Part 6 — Predictive Intelligence

6.1 Solution types for HR Leave

Type HR Leave use case Output field
Classification Approved within 24h? u_predicted_approval_24h
Regression Predict duration days u_predicted_duration
Similarity Find similar past requests (UI Action link)
Anomaly Unusual sick-leave pattern u_anomaly_score

Step 6.1: Add ML output fields to req_v2

URL: {BASE}/sys_dictionary_list.do?sysparm_query=name=x_786686_hr_leave_req_v2

Column Type Label
u_predicted_approval_24h string (40) Predicted 24h Approval
u_predicted_confidence_24h decimal Prediction Confidence
u_predicted_duration decimal Predicted Duration
u_anomaly_score decimal Anomaly Score
u_approved_within_24h string Actual 24h Approval (training label)

Step 6.2: Backfill training label (one-time script)

Run after you have historical approvals:

var gr = new GlideRecord('x_786686_hr_leave_req_v2');
gr.addQuery('u_state', 'IN', 'approved,rejected');
gr.query();
while (gr.next()) {
    var created = new GlideDateTime(gr.sys_created_on);
    var updated = new GlideDateTime(gr.sys_updated_on);
    var hours = (updated.getNumericValue() - created.getNumericValue()) / 3600000;
    var approved = gr.u_state == 'approved' && hours <= 24;
    gr.u_approved_within_24h = approved ? 'yes' : 'no';
    gr.setWorkflow(false);
    gr.update();
}
gs.info('Backfill complete');

Minimum training rows: ≥ 1,000 historical requests (≥ 100 per class for classification).

Step 6.3: Create classification solution — hrlx_predict_approval_24h

URL: {BASE}/ml_solution_definition_list.do

1. New Solution Definition
2. Name: hrlx_predict_approval_24h
3. Table: x_786686_hr_leave_req_v2
4. Solution type: Classification
5. Input fields:
   - u_leave_type
   - u_days_count
   - u_department (from employee)
   - u_employee_tenure_days (calculated field or BR)
   - day_of_week (derived from u_start_date)
   - u_has_reason (boolean: u_reason length > 5)
6. Output field: u_approved_within_24h
7. Prediction fields: u_predicted_approval_24h, u_predicted_confidence_24h
8. Training window: last 18 months
9. Exclusion: u_state=draft
10. Click Train → wait (15–60 min)
11. Review accuracy report: target ≥ 0.80 accuracy, F1 ≥ 0.65 minority class
12. Activate solution

Step 6.4: Business Rule — predict on insert

(function executeRule(current, previous) {
    if (current.u_predicted_approval_24h) return;
    try {
        var ml = new sn_ml.SolutionStore().get('hrlx_predict_approval_24h');
        if (!ml || !ml.isActive()) return;

        var startDt = new GlideDateTime(current.u_start_date);
        var input = {
            u_leave_type: String(current.u_leave_type),
            u_days_count: parseInt(current.u_days_count || '0', 10),
            u_department: String(current.u_department || ''),
            u_employee_tenure_days: parseInt(current.u_employee_tenure_days || '0', 10),
            day_of_week: startDt.getDayOfWeekUTC(),
            u_has_reason: (current.u_reason && current.u_reason.length > 5) ? 1 : 0
        };
        var pred = ml.predict([input]);
        if (pred && pred[0]) {
            current.u_predicted_approval_24h = pred[0].predicted_value;
            current.u_predicted_confidence_24h = pred[0].confidence;
        }
    } catch (e) {
        gs.warn('PI predict failed: ' + e);
    }
})(current, previous);
BR setting Value
When before insert
Table x_786686_hr_leave_req_v2
Order 500

Step 6.5: Regression solution — hrlx_predict_duration

Same wizard, type = Regression, output = u_days_count (actual), prediction = u_predicted_duration.

Step 6.6: Solution Monitor

URL: {BASE}/ml_solution_monitor_list.do

KPI Threshold Action if breached
Accuracy ≥ 0.80 Re-train
Drift score < 0.20 Investigate feature changes
RMSE (regression) ≤ 1.5 days Re-train
Prediction volume track Capacity planning

Schedule monthly re-train via Scheduled Script Execution.


Part 7 — Virtual Agent + NLU (Full Topics & Flows)

7.1 Virtual Agent vs AI Agent — coexistence

Aspect Virtual Agent (VA) AI Agent (AIA)
Logic Deterministic topic blocks LLM-planned
Cost Low Per-token
Best for Slot-filling, forms Open Q&A
Handoff VA → AIA via “Transfer to AI Agent” block AIA → VA via tool

Recommended pattern: VA handles structured flows; fallback / policy Q&A routes to AI Agent.

Step 7.1: Create NLU model — hrlx_leave_nlu

URL: {BASE}/now/nlu/workbench

Field Value
Model name hrlx_leave_nlu
Language en (add ar as second model if needed)
Domain HR Leave
Application x_786686_hr_leave

Step 7.2: Intents (8 total)

Intent Description
greeting Hello, hi, start
check_balance Remaining leave days
request_leave Book time off
check_policy Policy questions
cancel_leave Withdraw request
check_status Status of existing request
speak_to_human Live agent handoff
fallback Out of scope

Step 7.3: Entities

Entity Type Values / Notes
leave_type List annual, sick, parental, unpaid
date_range SYS.DATE “next Monday”, “June 5 to 10”
days_count Number “3 days”, “two weeks”
request_number Regex HRLX\d+
leave_type_ar List سنوية, مرضية, أمومة

Step 7.4: Utterances — check_balance (30 examples)

how many leave days do I have
what is my annual leave balance
show my remaining vacation days
how much PTO do I have left
check my sick leave balance
remaining parental leave
how many days off can I take
what's my leave balance
do I have any unpaid leave left
show balance for annual leave
how many annual days remaining
tell me my vacation balance
what leave do I have available
check my time off balance
how much annual leave is left
show me sick days remaining
balance inquiry for leave
how many days of leave remain
what is my current leave entitlement
remaining days for sick leave
how much leave have I got left
annual balance please
sick leave days left
parental leave balance check
unpaid leave remaining
how many holidays can I still take
leave days available
my remaining leave
check PTO balance
how many days can I still book off

Step 7.5: Utterances — request_leave (35 examples)

I want to take leave next Monday
request 3 days annual leave
book sick leave for tomorrow
I need time off from June 5 to June 10
apply for parental leave starting next month
request vacation days
take 2 days off next week
I want to book annual leave
schedule sick leave for Friday
need unpaid leave for 5 days
book me 3 days annual starting Monday
I would like to request leave
can I take leave next Tuesday and Wednesday
request time off for a wedding
apply for 10 days annual leave in July
I need sick leave for 2 days
book parental leave from September 1
request leave for family emergency
take annual leave Dec 20 to Dec 31
I want 1 week off
schedule 4 days sick leave
request unpaid leave next month
book leave type annual for 3 days
I need to take Friday off
request half day sick leave
apply for leave starting {date_range}
book {days_count} days of {leave_type} leave
I want {leave_type} leave from {date_range}
need {days_count} days off
request leave please
take time off
book my vacation
I want to go on leave
schedule my days off
can I have next week off

Step 7.6: Utterances — check_policy (25 examples)

what is the maternity leave policy
can I carry over unused annual leave
how many sick days am I allowed per year
what is the parental leave entitlement
do I need a medical certificate for sick leave
what is the notice period for annual leave
can managers reject my leave request
what happens to unused leave at year end
is unpaid leave available
what is the maximum consecutive leave days
how does sick leave accrue
what is the leave policy for new joiners
can I take leave during probation
what documents are required for sick leave
explain the annual leave policy
how far in advance must I request leave
what is the carry forward limit
are public holidays deducted from leave
what is bereavement leave policy
can I split parental leave
what is the leave approval process
how is leave calculated for part time staff
what is the sick leave waiting period
tell me about leave encashment
what are the rules for emergency leave

Step 7.7: Utterances — cancel_leave (20 examples)

cancel my leave request
withdraw my leave application
I want to cancel HRLX0001234
cancel my upcoming vacation
withdraw the leave I submitted
delete my leave request
cancel submitted leave
I no longer need those days off
please cancel my time off request
revoke my leave request
cancel annual leave for next week
withdraw sick leave request
cancel request number {request_number}
I want to undo my leave request
cancel my pending leave
stop my leave application
cancel the leave I booked
withdraw my days off
cancel leave starting Monday
I need to cancel my vacation request

Step 7.8: Utterances — check_status (20 examples)

what is the status of my leave request
has my leave been approved
track my leave application
where is my request HRLX0001234
is my leave approved yet
check approval status
status of my vacation request
has manager approved my leave
what happened to my leave request
show status of pending leave
is my sick leave approved
check my submitted leave
approval status please
where is my annual leave request
has HR approved my leave
track request {request_number}
what state is my leave in
is my leave still pending
did my leave get rejected
update on my leave request

Step 7.9: Train and publish NLU

1. NLU Workbench > hrlx_leave_nlu
2. Add all utterances above (minimum 15 per intent; we have 20–35)
3. Annotate entities in utterances (highlight dates, types)
4. Click Train → wait for model metrics
5. Target: Intent accuracy ≥ 0.92 on test set
6. Publish model version 1.0
7. Set property x_786686_hr_leave.nlu.model = hrlx_leave_nlu

Step 7.10: Topic catalog (8 topics)

URL: {BASE}/now/virtual-agent/designer

Topic Trigger NLU intent
HRLX Greeting greeting greeting
HRLX Check Balance check_balance check_balance
HRLX Request Leave request_leave request_leave
HRLX Check Policy check_policy check_policy OR transfer to AI Agent
HRLX Cancel Leave cancel_leave cancel_leave
HRLX Check Status check_status check_status
HRLX Live Agent speak_to_human speak_to_human
HRLX Fallback no match fallback

TOPIC FLOW 1 — HRLX Check Balance (block-by-block)

Topic: HRLX Check Balance
Channel: Employee Center, Service Portal
NLU: check_balance (confidence ≥ 0.7)

BLOCK 1 — Script Action "Fetch Balance"
  Script:
(function execute() {
    var userId = vaSystem.getUserId();
    var tools = new x_786686_hr_leave.HRLXAIAgentTools();
    var bal = tools.getBalance(userId);
    if (bal.error) {
        vaInputs.has_error = true;
        vaInputs.error_msg = 'Employee profile not found. Contact HR.';
        return;
    }
    vaInputs.has_error = false;
    vaInputs.balance_text =
        'Annual: ' + bal.annual + ' days\n' +
        'Sick: ' + bal.sick + ' days\n' +
        'Parental: ' + bal.parental + ' days\n' +
        'Unpaid: ' + bal.unpaid + ' days';
})();
BLOCK 2 — Decision
  Condition: has_error == true
  True → Bot Message: "${error_msg}" → End
  False → continue

BLOCK 3 — Bot Message
  Text: "Here is your current leave balance:\n${balance_text}"

BLOCK 4 — Quick Reply
  Question: "Would you like to request leave?"
  Options: Yes | No

BLOCK 5 — Branch
  Yes → Link to Topic "HRLX Request Leave"
  No → Bot Message "Have a great day!" → End

TOPIC FLOW 2 — HRLX Request Leave (slot filling)

Topic: HRLX Request Leave
NLU: request_leave

BLOCK 1 — Collect leave_type (if not in NLU entities)
  Prompt: "Which type of leave? (annual / sick / parental / unpaid)"
  Slot: leave_type
  Validation: must be in [annual, sick, parental, unpaid]
  Max retries: 2 → on fail go to Fallback

BLOCK 2 — Collect start_date
  Prompt: "What is the start date? (YYYY-MM-DD or 'next Monday')"
  Slot: start_date
  Validation: date >= today

BLOCK 3 — Collect end_date
  Prompt: "What is the end date?"
  Slot: end_date
  Validation: end_date >= start_date

BLOCK 4 — Collect reason (optional)
  Prompt: "Reason for leave? (optional — press Skip)"
  Slot: reason
  Required: false

BLOCK 5 — Script Action "Calculate Days Preview"
(function execute() {
    var start = new GlideDateTime(vaVars.start_date);
    var end = new GlideDateTime(vaVars.end_date);
    var days = Math.ceil((end.getNumericValue() - start.getNumericValue()) / 86400000) + 1;
    vaInputs.preview_days = days;
    var tools = new x_786686_hr_leave.HRLXAIAgentTools();
    var bal = tools.getBalance(vaSystem.getUserId());
    vaInputs.enough = (bal[vaVars.leave_type] || 0) >= days;
    vaInputs.available = bal[vaVars.leave_type] || 0;
})();
BLOCK 6 — Decision insufficient balance
  Condition: enough == false
  True → Message: "You need ${preview_days} days but only have ${available}. Choose shorter dates."
         → Go to BLOCK 2 (re-collect dates)
  False → continue

BLOCK 7 — Confirmation
  Message: "Please confirm:\nType: ${leave_type}\nFrom: ${start_date} To: ${end_date}\nDays: ${preview_days}\nReason: ${reason}"
  Quick Reply: Confirm | Cancel

BLOCK 8 — Branch Cancel → End polite

BLOCK 9 — Script Action "Submit Request"
(function execute() {
    var tools = new x_786686_hr_leave.HRLXAIAgentTools();
    var res = tools.requestLeave({
        user_id: vaSystem.getUserId(),
        type: vaVars.leave_type,
        start_date: vaVars.start_date,
        end_date: vaVars.end_date,
        reason: vaVars.reason || ''
    });
    vaInputs.ok = !!res.ok;
    vaInputs.req_number = res.number || '';
    vaInputs.err = res.error || '';
})();
BLOCK 10 — Decision ok
  True → "Your leave request ${req_number} has been submitted for approval."
  False → "Sorry, submission failed: ${err}. Try again or contact HR."
  → End

TOPIC FLOW 3 — HRLX Check Policy

BLOCK 1 — Decision: use AI Agent for open questions
  If utterance length > 50 chars OR contains "?"
    → Transfer to AI Agent "HR Leave Assistant" with context
  Else
    → Script Action CheckPolicy with vaInputs.last_utterance

BLOCK 2 — Display answer + citations
BLOCK 3 — "Was this helpful?" Yes/No → log to analytics

TOPIC FLOW 4 — HRLX Cancel Leave

BLOCK 1 — Collect request_number (or pick from list)
  Script Action: getMyRequests → build choice list

BLOCK 2 — Confirm cancellation

BLOCK 3 — Script Action cancelRequest

BLOCK 4 — Success/fail message

TOPIC FLOW 5 — HRLX Live Agent Handoff

BLOCK 1 — Collect issue summary (optional)

BLOCK 2 — Live Agent Queue
  Queue: HR Leave Support
  Pre-chat fields: user_id, last_intent, last_5_messages

BLOCK 3 — Fallback if no agent available
  Script Action escalate()
  Message: "An HR partner will contact you. Case reference logged."

Step 7.11: Enable VA on channels

1. Virtual Agent > Administration > Channels
2. Employee Center: ON, Bot name from x_786686_hr_leave.va.bot_name
3. Service Portal: add Virtual Agent widget to sp_page
4. Topic recommendations: enable HR Leave topics
5. Test: {BASE}/esc

Step 7.12: VA analytics KPIs

KPI Target Source
Containment rate ≥ 70% sys_cs_conversation
Avg turns ≤ 6 sys_cs_message count
Intent recognition ≥ 90% nlu_inference_result
Handoff rate ≤ 15% live agent transfers

Part 8 — Document Intelligence (IDP)

8.1 Use case — medical certificate for sick leave

When u_leave_type = sick and u_days_count > 2, require medical certificate attachment. IDP extracts fields automatically.

Extracted field Maps to column
patient_name (validate vs employee)
certificate_date u_cert_date
days_recommended u_cert_days
doctor_name u_cert_doctor
clinic_name u_cert_clinic
condition_summary u_cert_summary (masked in UI)

Step 8.1: Create IDP template — hrlx_medical_cert

URL: {BASE}/sn_idp_template_list.do

1. New Template
2. Name: hrlx_medical_cert
3. Document type: Medical Certificate
4. Upload 8–12 sample PDFs (anonymized):
   - 3 hospital letterheads
   - 3 clinic formats
   - 2 Arabic certificates
   - 2 poor-scan quality (for robustness)
5. For each sample, annotate bounding boxes:
   - patient_name
   - certificate_date
   - doctor_name
   - days_recommended
   - clinic_name
   - condition_summary
6. Save annotations

Step 8.2: Train extraction model

URL: {BASE}/sn_idp_model_list.do

1. New Model → Template: hrlx_medical_cert
2. Train/Test split: 80/20
3. Click Train (30–90 minutes)
4. Review per-field F1 scores (target ≥ 0.90 each)
5. If condition_summary F1 low: add more samples or mark optional
6. Activate model v1.0
7. Set property x_786686_hr_leave.idp.template = hrlx_medical_cert

Step 8.3: Flow — run IDP on attachment

URL: {BASE}/now/flow-designer

Flow: HRLX IDP Medical Certificate
Trigger: Attachment added to x_786686_hr_leave_req_v2
Condition: u_leave_type=sick^u_days_count>2

Step 1 — Get attachment sys_id
Step 2 — Action: Document Intelligence Extract
  Template: hrlx_medical_cert
  Input: attachment_sys_id
Step 3 — Script (update request):
(function(inputs, outputs) {
    var fields = inputs.extraction_result.fields || {};
    var req = new GlideRecord('x_786686_hr_leave_req_v2');
    if (!req.get(inputs.request_sys_id)) return;

    req.u_cert_date = fields.certificate_date || '';
    req.u_cert_days = fields.days_recommended || '';
    req.u_cert_doctor = fields.doctor_name || '';
    req.u_cert_clinic = fields.clinic_name || '';
    // Mask sensitive summary for display
    req.u_cert_summary = (fields.condition_summary || '').substring(0, 200);
    req.update();

    var aud = new GlideRecord('x_786686_hr_leave_audit_v2');
    aud.initialize();
    aud.u_action = 'idp_extract_cert';
    aud.u_record = req.getUniqueValue();
    aud.u_payload = JSON.stringify(fields);
    aud.u_actor = gs.getUserID();
    aud.u_source = 'idp';
    aud.insert();
})(inputs, outputs);
Step 4 — Decision: days_recommended < u_days_count → notify HR for review
Step 5 — Email employee if extraction failed (manual upload retry)

Step 8.4: Standalone IDP test

1. IDP Admin > Test Extraction
2. Upload new PDF not in training set
3. Verify all fields extracted
4. Latency target: ≤ 8 seconds per document

Step 8.5: IDP metrics dashboard

Metric Target
Field-level F1 ≥ 0.90
Document success rate ≥ 0.95
Avg latency ≤ 8s
Manual correction rate ≤ 10%

Part 9 — Workflow Studio AI Actions

Step 9.1: Built-in actions to reuse

Platform action HR Leave adaptation
Summarize Record Summarize u_reason on approval
Categorize Text Classify leave type from reason
Generate Email Response Manager approval/rejection email
Sentiment Analysis Route frustrated requests
Extract Entities Parse dates from free-text reason

Step 9.2: Custom action — HRLX Summarize Leave History

URL: {BASE}/now/flow-designer → Custom Actions

1. New Custom Action: HRLX Summarize Leave History
2. Application: HR Leave
3. Inputs:
   - employee_ref (Reference: x_786686_hr_leave_employee_v2)
   - lookback_days (Integer, default 365)
4. Outputs:
   - summary_text (String)
5. Steps:
   a. Look Up Records: x_786686_hr_leave_req_v2
      Query: u_employee_ref = employee_ref AND sys_created_on >= lookback
   b. Transform Data: build history_text lines
   c. Now Assist Skill: hrlx_summarize_history
   d. Return summary_text
6. Guardrails: PII redaction ON, max_tokens 250

Step 9.3: Flow — weekly manager digest

Trigger: Scheduled weekly Monday 08:00
For Each: managers with pending approvals
  Action: HRLX Summarize Leave History (direct reports, 90 days)
  Action: Send Email with summary + link to workspace

Step 9.4: Flow — auto-classify on submit

Trigger: Record created x_786686_hr_leave_req_v2, u_state=submitted
Action: Now Assist Skill hrlx_classify_leave_type
Decision: if output != u_leave_type → set u_ai_suggested_type + notify HR
Action: PI predict approval
Decision: if confidence < 0.6 → route to senior manager

Part 10 — Now Assist for Developers

Step 10.1: Generate Script Include from prompt

In Studio ({BASE}/$studio.do):

Prompt:
"Create Script Include HRLXLeaveValidation in scope x_786686_hr_leave.
Methods: validateDates(start, end), validateBalance(userId, type, days).
Use GlideRecord on x_786686_hr_leave_bal_v2. Return {ok, error} objects.
No client callable. Include null checks."

Review → Tab accept → add audit comment → ATF test.

Step 10.2: Inline shortcuts

Action Keys
Accept suggestion Tab
Partial accept Ctrl+Right
Multiline panel Ctrl+Enter
Reject Esc

Step 10.3: Generate ATF from Script Include

1. Open HRLXAIAgentTools in Studio
2. Now Assist > Generate Tests
3. Select: getBalance, requestLeave, cancelRequest
4. Save tests under sys_atf_test scoped to HR Leave
5. Run Test Runner: {BASE}/sys_atf_test_runner.do

Step 10.4: Code review checklist for AI-generated code

[ ] No hard-coded sys_ids
[ ] Scoped table names only (x_786686_hr_leave_*)
[ ] ACL-safe (respects current user)
[ ] No gs.print in production code
[ ] Error handling with gs.error/gs.warn
[ ] Human reviewer name in header comment

Part 11 — End-to-End HR Leave AI Example

Scenario: Employee submits sick leave via chat with certificate

Actors: Employee (ESS), HR Leave Assistant (AIA), VA topics, IDP, PI, Flow

Step 1 — Employee opens {BASE}/esc
Step 2 — "I need sick leave Thu-Fri" → VA Topic Request Leave OR AIA
Step 3 — Slot fill: type=sick, dates confirmed
Step 4 — AIA calls RequestLeave → req HRLX001234 created
Step 5 — Employee uploads medical PDF on form
Step 6 — Flow HRLX IDP Medical Certificate runs → fields extracted
Step 7 — BR runs PI → u_predicted_approval_24h = yes (0.87)
Step 8 — Manager opens record → UI Action Summarize reason (AI)
Step 9 — Manager approves → Flow sends hrlx_draft_manager_email (optional)
Step 10 — Audit rows in x_786686_hr_leave_audit_v2 for ai_request_leave, idp_extract_cert

Verification queries

// All AI-touched requests last 7 days
var gr = new GlideRecord('x_786686_hr_leave_req_v2');
gr.addQuery('u_source', 'ai_agent');
gr.addQuery('sys_created_on', '>=', gs.daysAgoStart(7));
gr.query();
gs.info('AI agent requests: ' + gr.getRowCount());

var aud = new GlideRecord('x_786686_hr_leave_audit_v2');
aud.addQuery('u_source', 'IN', 'ai_agent,idp');
aud.addQuery('sys_created_on', '>=', gs.daysAgoStart(7));
aud.query();
gs.info('AI audit rows: ' + aud.getRowCount());

Part 12 — AI Governance & Safety

Step 12.1: Create AI policy — no_raw_medical_text

URL: {BASE}/now/ai/policy

{
  "policy": "hrlx_no_raw_medical_text",
  "scope": "x_786686_hr_leave",
  "rules": [
    {
      "id": "redact_diagnosis",
      "applies_to": ["input", "output"],
      "regex": "(?i)(diagnosis|condition|illness|medication):\\s*[^\\n]+",
      "action": "redact",
      "replacement": "[REDACTED-MEDICAL]"
    },
    {
      "id": "block_external_emails",
      "applies_to": ["output"],
      "regex": "\\b[A-Z0-9._%+-]+@(?!company\\.com)[A-Z0-9.-]+\\.[A-Z]{2,}\\b",
      "action": "block"
    }
  ]
}

Step 12.2: Human-in-the-loop matrix

AI action Human checkpoint
RequestLeave User confirms in chat
Auto-approve (never) Manager always approves
PI low confidence Route to senior manager
IDP mismatch days HR manual review
Generated email Manager edits before send

Step 12.3: Compliance notes

Regulation Requirement
GDPR Right to erasure on sn_aia_audit / sys_one_extend_audit
EU AI Act HR decisions = high-risk → transparency + human oversight
HIPAA Encrypt certificate attachments, restrict ACL
PDPL (GCC) Data residency → pick LLM region

Step 12.4: Audit retention

Configure 365-day retention on sn_aia_audit and sys_one_extend_audit. Domain audit x_786686_hr_leave_audit_v2 retained per HR policy (typically 7 years).


Part 13 — Performance & Cost Optimization

Step 13.1: Response cache table

Create table x_786686_hr_leave_ai_cache (hash, skill, response, expires_at).

var HRLXAICache = Class.create();
HRLXAICache.prototype = {
    initialize: function() { this.TABLE = 'x_786686_hr_leave_ai_cache'; },
    _hash: function(s) { return new GlideDigest().getSHA256Base64(s); },
    get: function(skill, input) {
        var gr = new GlideRecord(this.TABLE);
        gr.addQuery('u_hash', this._hash(skill + '|' + input));
        gr.addQuery('u_expires_at', '>', new GlideDateTime());
        gr.setLimit(1);
        gr.query();
        return gr.next() ? String(gr.u_response) : null;
    },
    put: function(skill, input, response, ttlMin) {
        var gr = new GlideRecord(this.TABLE);
        gr.initialize();
        gr.u_hash = this._hash(skill + '|' + input);
        gr.u_skill = skill;
        gr.u_response = response;
        var exp = new GlideDateTime();
        exp.addSeconds(60 * (ttlMin || 60));
        gr.u_expires_at = exp;
        gr.insert();
    },
    type: 'HRLXAICache'
};

Use for hrlx_classify_leave_type (deterministic input).

Step 13.2: Model right-sizing

Task Model
classify, sentiment gpt-4o-mini / Now LLM Generic
summarize Now LLM Generic
agent multi-step now-llm-pro-v1 / claude-sonnet-4-5
code gen Now Assist for Creator

Step 13.3: Monitoring dashboard widgets

Widget Source Alert
Skill calls/day sys_one_extend_audit > 2× baseline
p95 latency sys_one_extend_audit > 3s
Daily LLM spend system properties > budget
Agent containment sn_aia_execution < 60%
PI drift ml_solution_monitor > 0.2

Part 14 — Hands-On Labs (5 Sessions)

Lab 1 — Now Assist Skill (45 min)

Goal: Deploy hrlx_summarize_reason with UI Action.

| Time | Step |
|------|------|
| 0–5 | Verify prerequisites (§0.2) |
| 5–15 | Create skill in Now Assist Studio (§2.2) |
| 15–25 | Test 5 samples in Playground |
| 25–35 | Create UI Action on req_v2 form |
| 35–40 | Impersonate manager → click Summarize |
| 40–45 | Check sys_one_extend_audit for log row |

Pass: Summary appears ≤ 2s, no medical detail leaked.
URL: {BASE}/now/assist/studio

Lab 2 — AI Search + GenAI (45 min)

Goal: Ask “Can I carry over annual leave?” and get cited answer.

| Time | Step |
|------|------|
| 0–10 | Create 3 KB articles (topic=HR Leave) if missing |
| 10–25 | Create source hrlx_kb + profile hrlx_kb_profile (§5) |
| 25–35 | Full index → wait green |
| 35–40 | Test in AI Search Admin preview |
| 40–45 | Add sp-search widget to portal page |

Pass: GenAI answer cites KB number.
URL: {BASE}/now/ais/admin

Lab 3 — Virtual Agent topic (60 min)

Goal: Complete balance → request leave conversation.

| Time | Step |
|------|------|
| 0–15 | Import NLU utterances for check_balance + request_leave |
| 15–25 | Train + publish hrlx_leave_nlu |
| 25–45 | Build topics per §7 block diagrams |
| 45–55 | Enable on {BASE}/esc |
| 55–60 | Run conversation test script (10 utterances) |

Pass: Request created with u_source=virtual_agent (add field if needed).
URL: {BASE}/now/virtual-agent/designer

Lab 4 — AI Agent + tools (60 min)

Goal: HR Leave Assistant submits leave after confirmation.

| Time | Step |
|------|------|
| 0–15 | Deploy HRLXAIAgentTools Script Include |
| 15–30 | Create 6 tools in Agent Studio |
| 30–45 | Create agent + system prompt |
| 45–55 | Enable on Employee Center |
| 55–60 | Test: "book 2 days annual next week" → confirm → verify req |

Pass: Record in req_v2, audit row written.
URL: {BASE}/now/aia/studio

Lab 5 — IDP + PI (90 min)

Goal: Sick leave + certificate extraction + approval prediction.

| Time | Step |
|------|------|
| 0–20 | Upload samples + annotate hrlx_medical_cert |
| 20–50 | Train IDP model (parallel: backfill PI labels) |
| 50–65 | Create Flow for attachment trigger |
| 65–80 | Train hrlx_predict_approval_24h |
| 80–90 | Submit sick leave with PDF → verify cert fields + prediction |

Pass: u_cert_date populated, u_predicted_approval_24h set.
URL: {BASE}/now/idp/admin , {BASE}/ml_solution_definition_list.do

Part 15 — Best Practices

15.1 Design

✅ One skill = one job (summarize OR classify, not both)
✅ Ground skills to specific tables with field-level mapping
✅ VA for happy-path slots; AIA for long-tail questions
✅ Always show citations for policy answers
✅ Confirm destructive tool calls (RequestLeave, CancelRequest)
✅ Log every AI action to x_786686_hr_leave_audit_v2
❌ Do not send cross-employee data to LLM
❌ Do not auto-approve leave based on PI alone
❌ Do not index u_reason without PII masking
❌ Do not skip human review on AI-generated code

15.2 Prompt engineering

✅ Separate SYSTEM (rules) from USER (data)
✅ Specify output format explicitly (JSON, single label, max words)
✅ Include refusal behavior ("If unsure, say...")
✅ Test in Arabic and English if bilingual workforce
✅ Version prompts; never edit production without version bump

15.3 Operations

✅ Weekly: review zero-result AI Search queries → add KB
✅ Monthly: review skill latency + cost dashboards
✅ Quarterly: re-train PI + NLU with new utterances
✅ Per release: run 5 labs as regression suite
✅ Maintain eval set (50 questions + expected answers) per skill

15.4 Security

✅ Mask medical text in prompts sent to external LLMs
✅ Use instance ACLs — tools run as authenticated user
✅ Budget caps on BYO LLM properties
✅ Disable x_786686_hr_leave.ai.enabled kill switch tested quarterly

Part 16 — Production Deployment Checklist

Phase A — Pre-deployment (sub-prod complete)

[ ] All 5 labs passed on sub-prod
[ ] Update Set "HR Leave AI v1.0" complete + peer reviewed
[ ] ATF tests green for HRLXAIAgentTools
[ ] Eval set ≥ 90% pass rate per skill
[ ] NLU intent accuracy ≥ 0.92
[ ] IDP field F1 ≥ 0.90
[ ] PI accuracy ≥ 0.80
[ ] AI Search zero-result rate < 10%
[ ] Agent containment ≥ 70% in UAT
[ ] Security review: PII redaction verified
[ ] Cost model approved (projected RU/month)
[ ] Rollback plan documented (disable ai.enabled property)

Phase B — Deployment day

[ ] Clone Update Set to production via DevOps/CD pipeline
[ ] Set production LLM API keys (password2 properties)
[ ] Activate plugins (if not already) — maintenance window
[ ] Now Assist Admin → enable skills for production scope
[ ] AI Search → full re-index on production
[ ] NLU model published to production instance
[ ] IDP model activated
[ ] PI solutions activated (monitor only first 24h)
[ ] Enable VA on Employee Center (feature flag gradual)
[ ] Enable AI Agent on Employee Center (pilot group first)
[ ] Verify kill switch: x_786686_hr_leave.ai.enabled = true
[ ] Smoke test: 10 utterances from §3.5 + §7
[ ] Monitor logs 2 hours: syslog, sn_aia_execution, sys_one_extend_audit

Phase C — Post-deployment (week 1)

[ ] Day 1: review all sn_aia_audit for errors
[ ] Day 2: review AI Search zero-result queries
[ ] Day 3: review VA containment + handoff rate
[ ] Day 5: review LLM spend vs budget
[ ] Day 7: stakeholder sign-off meeting
[ ] Document known issues + FAQ for HR helpdesk
[ ] Schedule monthly PI re-train
[ ] Schedule quarterly prompt review

Rollback procedure

1. Set x_786686_hr_leave.ai.enabled = false (immediate stop)
2. Disable AI Agent channel in Now Assist Admin
3. Disable VA topics (set inactive)
4. Deactivate PI solutions (optional — predictions stop)
5. Revert Update Set if Script Include defects found
6. Communicate to HR: "AI assistant temporarily offline"

Appendices

Appendix A — Key tables reference

Area Tables
Skills sys_one_extend_skill, sys_one_extend_prompt_template, sys_one_extend_audit
Agents sn_aia_agent, sn_aia_tool, sn_aia_execution, sn_aia_execution_step, sn_aia_audit
AI Search ais_search_source, ais_search_profile, sys_aisearch_query_log, sys_aisearch_genai_log
PI ml_solution_definition, ml_solution, ml_solution_monitor
NLU nlu_model, nlu_intent, nlu_entity, nlu_utterance
VA sys_cs_topic, sys_cs_topic_block, sys_cs_conversation, sys_cs_message
IDP sn_idp_template, sn_idp_model, sn_idp_extraction_result
HR Leave x_786686_hr_leave_req_v2, _bal_v2, _employee_v2, _audit_v2

Appendix B — Script Includes

Script Include Purpose
HRLXAIAgentTools Agent/VA tools
HRLXAIProvider BYO LLM + fallback
HRLXRagService RAG answers
HRLXAICache Response cache
HRLXHolidayUtil Holiday JSON for date skill

Appendix C — REST Messages

Name Endpoint
Claude_API https://api.anthropic.com/v1/messages
OpenAI_API https://api.openai.com/v1/chat/completions

Appendix D — Roles

Role Use
sn_nowassist_admin Skills
sn_aia.admin Agents
ml_admin Predictive Intelligence
ai_search_admin AI Search
nlu_admin NLU
sn_idp.admin IDP
x_786686_hr_leave.manager UI Actions
x_786686_hr_leave.hr_admin Full HR AI access

Appendix E — Plugin quick search terms

Now Assist, AI Agents, AI Search, Predictive Intelligence,
Document Intelligence, Virtual Agent, NLU Workbench, Now Assist for Creator

Appendix F — Troubleshooting

Symptom Likely cause Fix
Skill returns empty Missing grounding sys_id Pass record in payload
Agent can’t call tool ACL on Script Include Check scope + roles
AI Search no results Index not built Full index in admin
NLU always fallback Model not published Publish + bind to topic
IDP low F1 Too few samples Add 5+ annotated PDFs
PI predict null Solution inactive Activate + check field map
Budget exceeded Daily cap hit Raise budget or wait
VA handoff fails Queue empty Configure HR queue hours
Doc Topic
01_DEVELOPMENT.md Tables, BRs, Script Includes
03_SERVICE_CATALOG.md Record producer + catalog VA
07_REPORTS_DASHBOARDS_PA.md AI metrics dashboards
08_ATF_TESTING.md Test HRLXAIAgentTools
External codegen
12_INTEGRATION_FULL_GUIDE.md REST + Table API

End of guide. Start at Part 0 → pick your track (Skill, Agent, VA, Search, PI, IDP) → run matching Lab → complete Deployment Checklist.

للأسئلة: ابدأ من Quick Map → نفّذ Lab المناسب → راجع Troubleshooting (Appendix F).