โ† Back to list
groeimetai

virtual-agent

by groeimetai

๐Ÿค– AI-powered ServiceNow development with 400+ MCP tools. Works with Claude, GPT, Gemini, Ollama & 75+ providers. Deploy widgets, manage incidents, automate workflows - all through natural language. Open-source Build Agent alternative.

โญ 42๐Ÿด 9๐Ÿ“… Jan 23, 2026

SKILL.md


name: virtual-agent description: This skill should be used when the user asks to "create chatbot", "virtual agent", "VA topic", "NLU", "conversation", "chat flow", "topic block", or any ServiceNow Virtual Agent development. license: Apache-2.0 compatibility: Designed for Snow-Code and ServiceNow development metadata: author: groeimetai version: "1.0.0" category: servicenow tools:

  • snow_va_topic_create
  • snow_va_nlu_train
  • snow_query_table
  • snow_find_artifact

Virtual Agent for ServiceNow

Virtual Agent (VA) provides conversational AI capabilities for self-service through chat interfaces.

Virtual Agent Architecture

Topic Structure

Topic: Password Reset
โ”œโ”€โ”€ NLU Model
โ”‚   โ”œโ”€โ”€ Utterances: "reset my password", "forgot password"
โ”‚   โ””โ”€โ”€ Entities: application_name
โ”œโ”€โ”€ Topic Blocks (Flow)
โ”‚   โ”œโ”€โ”€ Greeting
โ”‚   โ”œโ”€โ”€ Ask for Application
โ”‚   โ”œโ”€โ”€ Verify User
โ”‚   โ”œโ”€โ”€ Process Reset
โ”‚   โ””โ”€โ”€ Confirmation
โ””โ”€โ”€ Variables
    โ”œโ”€โ”€ user_email
    โ””โ”€โ”€ application

Key Tables

TablePurpose
sys_cs_topicTopic definitions
sys_cs_topic_blockConversation flow blocks
sys_cs_intentNLU intents
sys_cs_utteranceTraining phrases
sys_cs_entityCustom entities

Topics

Creating a Topic (ES5)

// Create Password Reset topic
var topic = new GlideRecord('sys_cs_topic');
topic.initialize();
topic.setValue('name', 'Password Reset');
topic.setValue('description', 'Help users reset their passwords');
topic.setValue('active', true);

// NLU configuration
topic.setValue('goal', 'I want to reset my password');
topic.setValue('nlu_enabled', true);

// Category
topic.setValue('category', 'IT Support');

var topicSysId = topic.insert();

Topic Variables

// Add variable to topic
var variable = new GlideRecord('sys_cs_topic_variable');
variable.initialize();
variable.setValue('topic', topicSysId);
variable.setValue('name', 'user_email');
variable.setValue('label', 'Email Address');
variable.setValue('type', 'string');
variable.setValue('mandatory', true);
variable.insert();

Topic Blocks

Block Types

TypePurposeExample
TextDisplay message"I can help with that!"
PromptAsk question"What's your email?"
ScriptRun server codeLookup user, create ticket
DecisionBranching logicIf VIP then...
LinkExternal linkOpen portal page
HandoffAgent transferConnect to live agent

Text Block

// Greeting block
var block = new GlideRecord('sys_cs_topic_block');
block.initialize();
block.setValue('topic', topicSysId);
block.setValue('name', 'greeting');
block.setValue('type', 'text');
block.setValue('order', 100);
block.setValue('message', 'Hello! I can help you reset your password. Let me gather some information.');
block.insert();

Prompt Block

// Ask for email
var promptBlock = new GlideRecord('sys_cs_topic_block');
promptBlock.initialize();
promptBlock.setValue('topic', topicSysId);
promptBlock.setValue('name', 'ask_email');
promptBlock.setValue('type', 'prompt');
promptBlock.setValue('order', 200);
promptBlock.setValue('message', 'What is your email address?');
promptBlock.setValue('variable_name', 'user_email');
promptBlock.setValue('validation_type', 'email');
promptBlock.insert();

Script Block (ES5)

// Script block to verify user
var scriptBlock = new GlideRecord('sys_cs_topic_block');
scriptBlock.initialize();
scriptBlock.setValue('topic', topicSysId);
scriptBlock.setValue('name', 'verify_user');
scriptBlock.setValue('type', 'script');
scriptBlock.setValue('order', 300);

// Server-side script (ES5 only!)
scriptBlock.setValue('script',
    '(function execute(inputs, outputs) {\n' +
    '    var email = inputs.user_email;\n' +
    '    var user = new GlideRecord("sys_user");\n' +
    '    user.addQuery("email", email);\n' +
    '    user.query();\n' +
    '    \n' +
    '    if (user.next()) {\n' +
    '        outputs.user_found = true;\n' +
    '        outputs.user_name = user.getValue("name");\n' +
    '        outputs.user_sys_id = user.getUniqueValue();\n' +
    '    } else {\n' +
    '        outputs.user_found = false;\n' +
    '    }\n' +
    '})(inputs, outputs);'
);
scriptBlock.insert();

Decision Block

// Decision based on user found
var decisionBlock = new GlideRecord('sys_cs_topic_block');
decisionBlock.initialize();
decisionBlock.setValue('topic', topicSysId);
decisionBlock.setValue('name', 'check_user');
decisionBlock.setValue('type', 'decision');
decisionBlock.setValue('order', 400);

// Decision branches configured separately
decisionBlock.insert();

// Add decision branches
var branch1 = new GlideRecord('sys_cs_topic_block_branch');
branch1.initialize();
branch1.setValue('block', decisionBlock.getUniqueValue());
branch1.setValue('condition', 'user_found == true');
branch1.setValue('next_block', processResetBlockSysId);
branch1.insert();

var branch2 = new GlideRecord('sys_cs_topic_block_branch');
branch2.initialize();
branch2.setValue('block', decisionBlock.getUniqueValue());
branch2.setValue('condition', 'user_found == false');
branch2.setValue('next_block', userNotFoundBlockSysId);
branch2.insert();

Handoff Block

// Transfer to live agent
var handoffBlock = new GlideRecord('sys_cs_topic_block');
handoffBlock.initialize();
handoffBlock.setValue('topic', topicSysId);
handoffBlock.setValue('name', 'transfer_agent');
handoffBlock.setValue('type', 'handoff');
handoffBlock.setValue('order', 900);
handoffBlock.setValue('message', 'Let me connect you with a live agent who can help further.');
handoffBlock.setValue('queue', liveSupportQueueSysId);
handoffBlock.insert();

NLU Training

Adding Utterances

// Add training utterances for intent
function addUtterance(topicId, text) {
    var utt = new GlideRecord('sys_cs_utterance');
    utt.initialize();
    utt.setValue('topic', topicId);
    utt.setValue('utterance', text);
    utt.insert();
}

// Training phrases for password reset
addUtterance(topicSysId, 'reset my password');
addUtterance(topicSysId, 'I forgot my password');
addUtterance(topicSysId, 'change my password');
addUtterance(topicSysId, 'password not working');
addUtterance(topicSysId, 'can\'t log in');
addUtterance(topicSysId, 'locked out of my account');
addUtterance(topicSysId, 'need to reset password for @application');

Custom Entities

// Create custom entity for applications
var entity = new GlideRecord('sys_cs_entity');
entity.initialize();
entity.setValue('name', 'application_name');
entity.setValue('description', 'Enterprise application names');
entity.setValue('type', 'list');
entity.insert();

// Add entity values
var values = ['SAP', 'Salesforce', 'Workday', 'ServiceNow', 'Email'];
for (var i = 0; i < values.length; i++) {
    var val = new GlideRecord('sys_cs_entity_value');
    val.initialize();
    val.setValue('entity', entity.getUniqueValue());
    val.setValue('value', values[i]);
    val.setValue('synonyms', '');  // comma-separated synonyms
    val.insert();
}

Quick Replies

Configuring Quick Replies

// Add quick reply options to prompt
var promptWithReplies = new GlideRecord('sys_cs_topic_block');
promptWithReplies.initialize();
promptWithReplies.setValue('topic', topicSysId);
promptWithReplies.setValue('name', 'select_application');
promptWithReplies.setValue('type', 'prompt');
promptWithReplies.setValue('order', 150);
promptWithReplies.setValue('message', 'Which application do you need to reset?');
promptWithReplies.setValue('variable_name', 'application');
promptWithReplies.setValue('quick_replies', JSON.stringify([
    { label: 'Email', value: 'email' },
    { label: 'SAP', value: 'sap' },
    { label: 'ServiceNow', value: 'servicenow' },
    { label: 'Other', value: 'other' }
]));
promptWithReplies.insert();

Integration Actions

Create Incident from VA (ES5)

// Script block to create incident
var createIncidentScript =
'(function execute(inputs, outputs) {\n' +
'    var inc = new GlideRecord("incident");\n' +
'    inc.initialize();\n' +
'    inc.setValue("caller_id", inputs.user_sys_id);\n' +
'    inc.setValue("short_description", "Password Reset Request: " + inputs.application);\n' +
'    inc.setValue("description", "User requested password reset via Virtual Agent.");\n' +
'    inc.setValue("category", "software");\n' +
'    inc.setValue("subcategory", "password reset");\n' +
'    inc.setValue("priority", 3);\n' +
'    \n' +
'    var sysId = inc.insert();\n' +
'    \n' +
'    outputs.incident_number = inc.getValue("number");\n' +
'    outputs.incident_sys_id = sysId;\n' +
'})(inputs, outputs);';

Lookup Records (ES5)

// Script to lookup knowledge articles
var lookupKBScript =
'(function execute(inputs, outputs) {\n' +
'    var query = inputs.user_question;\n' +
'    var articles = [];\n' +
'    \n' +
'    var kb = new GlideRecord("kb_knowledge");\n' +
'    kb.addQuery("workflow_state", "published");\n' +
'    kb.addQuery("short_description", "CONTAINS", query);\n' +
'    kb.setLimit(3);\n' +
'    kb.query();\n' +
'    \n' +
'    while (kb.next()) {\n' +
'        articles.push({\n' +
'            number: kb.getValue("number"),\n' +
'            title: kb.getValue("short_description"),\n' +
'            sys_id: kb.getUniqueValue()\n' +
'        });\n' +
'    }\n' +
'    \n' +
'    outputs.articles = JSON.stringify(articles);\n' +
'    outputs.article_count = articles.length;\n' +
'})(inputs, outputs);';

MCP Tool Integration

Available VA Tools

ToolPurpose
snow_create_va_topicCreate topic
snow_create_va_topic_blockAdd conversation block
snow_discover_va_topicsFind topics
snow_send_va_messageTest conversation
snow_get_va_conversationGet conversation history
snow_handoff_to_agentTransfer to agent

Example Workflow

// 1. Create topic
var topicId = await snow_create_va_topic({
    name: 'IT Equipment Request',
    description: 'Help users request new equipment',
    category: 'IT Support'
});

// 2. Add greeting block
await snow_create_va_topic_block({
    topic: topicId,
    name: 'greeting',
    type: 'text',
    order: 100,
    message: 'I can help you request new IT equipment!'
});

// 3. Add prompt block
await snow_create_va_topic_block({
    topic: topicId,
    name: 'equipment_type',
    type: 'prompt',
    order: 200,
    message: 'What type of equipment do you need?',
    quick_replies: ['Laptop', 'Monitor', 'Keyboard', 'Mouse']
});

// 4. Test conversation
await snow_send_va_message({
    topic: topicId,
    message: 'I need a new laptop'
});

Best Practices

  1. Clear Intents - One purpose per topic
  2. Rich Training - Many varied utterances
  3. Graceful Fallback - Handle unknown inputs
  4. Quick Replies - Reduce typing
  5. Confirmation - Verify before actions
  6. Handoff Path - Always allow agent transfer
  7. Test Thoroughly - Many conversation paths
  8. Persona - Consistent friendly tone

Score

Total Score

75/100

Based on repository quality metrics

โœ“SKILL.md

SKILL.mdใƒ•ใ‚กใ‚คใƒซใŒๅซใพใ‚Œใฆใ„ใ‚‹

+20
โœ“LICENSE

ใƒฉใ‚คใ‚ปใƒณใ‚นใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹

+10
โœ“่ชฌๆ˜Žๆ–‡

100ๆ–‡ๅญ—ไปฅไธŠใฎ่ชฌๆ˜ŽใŒใ‚ใ‚‹

+10
โ—‹ไบบๆฐ—

GitHub Stars 100ไปฅไธŠ

0/15
โœ“ๆœ€่ฟ‘ใฎๆดปๅ‹•

1ใƒถๆœˆไปฅๅ†…ใซๆ›ดๆ–ฐ

+10
โ—‹ใƒ•ใ‚ฉใƒผใ‚ฏ

10ๅ›žไปฅไธŠใƒ•ใ‚ฉใƒผใ‚ฏใ•ใ‚Œใฆใ„ใ‚‹

0/5
โœ“Issue็ฎก็†

ใ‚ชใƒผใƒ—ใƒณIssueใŒ50ๆœชๆบ€

+5
โœ“่จ€่ชž

ใƒ—ใƒญใ‚ฐใƒฉใƒŸใƒณใ‚ฐ่จ€่ชžใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹

+5
โœ“ใ‚ฟใ‚ฐ

1ใคไปฅไธŠใฎใ‚ฟใ‚ฐใŒ่จญๅฎšใ•ใ‚Œใฆใ„ใ‚‹

+5

Reviews

๐Ÿ’ฌ

Reviews coming soon