โ† Back to list
groeimetai

integration-hub

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: integration-hub description: This skill should be used when the user asks to "IntegrationHub", "spoke", "flow action", "integration", "subflow", "connection alias", "credential alias", "REST step", or any ServiceNow IntegrationHub development. license: Apache-2.0 compatibility: Designed for Snow-Code and ServiceNow development metadata: author: groeimetai version: "1.0.0" category: servicenow tools:

  • snow_query_table
  • snow_find_artifact
  • snow_test_rest_connection
  • snow_execute_script_with_output

IntegrationHub for ServiceNow

IntegrationHub provides reusable integration components for Flow Designer and workflows.

IntegrationHub Architecture

Spoke (sn_ih_spoke)
    โ”œโ”€โ”€ Actions (sn_ih_action)
    โ”‚   โ”œโ”€โ”€ Inputs
    โ”‚   โ”œโ”€โ”€ Steps
    โ”‚   โ””โ”€โ”€ Outputs
    โ”œโ”€โ”€ Connection Alias
    โ””โ”€โ”€ Credential Alias

Flow Designer
    โ””โ”€โ”€ Uses Spoke Actions

Key Tables

TablePurpose
sn_ih_spokeSpoke definitions
sn_ih_actionSpoke actions
sn_ih_step_configAction step configuration
sys_aliasConnection/credential aliases

Connection & Credential Aliases (ES5)

Create Connection Alias

// Create connection alias (ES5 ONLY!)
var alias = new GlideRecord('sys_alias');
alias.initialize();

alias.setValue('name', 'Jira Connection');
alias.setValue('id', 'x_myapp_jira_connection');
alias.setValue('type', 'connection');
alias.setValue('connection_type', 'http');

// Connection attributes
alias.setValue('attributes', JSON.stringify({
    base_url: 'https://mycompany.atlassian.net/rest/api/3',
    timeout: 30000
}));

alias.insert();

Create Credential Alias

// Create credential alias (ES5 ONLY!)
var credAlias = new GlideRecord('sys_alias');
credAlias.initialize();

credAlias.setValue('name', 'Jira API Token');
credAlias.setValue('id', 'x_myapp_jira_credential');
credAlias.setValue('type', 'credential');

credAlias.insert();

// Link to actual credential
var credential = new GlideRecord('basic_auth_credentials');
credential.initialize();
credential.setValue('name', 'Jira API Token Credential');
credential.setValue('user_name', 'api-user@company.com');
credential.setValue('password', '');  // Set via secure method
credential.insert();

// Create alias-credential mapping
var mapping = new GlideRecord('sys_alias_credential');
mapping.initialize();
mapping.setValue('alias', credAlias.getUniqueValue());
mapping.setValue('credential', credential.getUniqueValue());
mapping.insert();

Spoke Development (ES5)

Create Custom Spoke

// Create spoke (ES5 ONLY!)
var spoke = new GlideRecord('sn_ih_spoke');
spoke.initialize();

spoke.setValue('name', 'Custom ITSM Connector');
spoke.setValue('label', 'Custom ITSM Connector');
spoke.setValue('description', 'Integration with external ITSM system');
spoke.setValue('vendor', 'My Company');
spoke.setValue('version', '1.0.0');

// Scope
spoke.setValue('scope', 'x_myapp_itsm');

// Logo
spoke.setValue('logo', 'attachment_sys_id');

spoke.insert();

Create Spoke Action

// Create action for spoke (ES5 ONLY!)
var action = new GlideRecord('sn_ih_action');
action.initialize();

action.setValue('name', 'Create External Ticket');
action.setValue('label', 'Create External Ticket');
action.setValue('spoke', spokeSysId);
action.setValue('description', 'Creates a ticket in external ITSM system');

// Category
action.setValue('category', 'record_operations');

// Accessibility
action.setValue('accessible_from', 'flow_designer');

action.insert();

// Add inputs
addActionInput(action.getUniqueValue(), 'summary', 'String', true, 'Ticket summary');
addActionInput(action.getUniqueValue(), 'description', 'String', false, 'Ticket description');
addActionInput(action.getUniqueValue(), 'priority', 'String', false, 'Priority level');

// Add outputs
addActionOutput(action.getUniqueValue(), 'ticket_id', 'String', 'Created ticket ID');
addActionOutput(action.getUniqueValue(), 'ticket_url', 'String', 'URL to ticket');

Action Input/Output Helpers

// Add action input (ES5 ONLY!)
function addActionInput(actionSysId, name, type, mandatory, label) {
    var input = new GlideRecord('sn_ih_input');
    input.initialize();
    input.setValue('action', actionSysId);
    input.setValue('name', name);
    input.setValue('label', label);
    input.setValue('type', type);
    input.setValue('mandatory', mandatory);
    input.setValue('order', getNextOrder(actionSysId, 'input'));
    return input.insert();
}

// Add action output (ES5 ONLY!)
function addActionOutput(actionSysId, name, type, label) {
    var output = new GlideRecord('sn_ih_output');
    output.initialize();
    output.setValue('action', actionSysId);
    output.setValue('name', name);
    output.setValue('label', label);
    output.setValue('type', type);
    output.setValue('order', getNextOrder(actionSysId, 'output'));
    return output.insert();
}

Action Steps (ES5)

REST Step Configuration

// Create REST step for action (ES5 ONLY!)
var step = new GlideRecord('sn_ih_step_config');
step.initialize();

step.setValue('action', actionSysId);
step.setValue('name', 'Call External API');
step.setValue('order', 100);
step.setValue('step_type', 'rest');

// REST configuration
step.setValue('rest_config', JSON.stringify({
    connection_alias: 'x_myapp_jira_connection',
    credential_alias: 'x_myapp_jira_credential',
    http_method: 'POST',
    resource_path: '/issue',
    request_body: {
        fields: {
            project: { key: '${inputs.project_key}' },
            summary: '${inputs.summary}',
            description: '${inputs.description}',
            issuetype: { name: 'Task' }
        }
    },
    headers: {
        'Content-Type': 'application/json'
    }
}));

step.insert();

Script Step

// Create script step (ES5 ONLY!)
var scriptStep = new GlideRecord('sn_ih_step_config');
scriptStep.initialize();

scriptStep.setValue('action', actionSysId);
scriptStep.setValue('name', 'Process Response');
scriptStep.setValue('order', 200);
scriptStep.setValue('step_type', 'script');

// Script (ES5 ONLY!)
scriptStep.setValue('script',
    '(function execute(inputs, outputs) {\n' +
    '    // Get REST response from previous step\n' +
    '    var response = inputs.rest_response;\n' +
    '    \n' +
    '    if (response.status_code === 201) {\n' +
    '        var body = JSON.parse(response.body);\n' +
    '        outputs.ticket_id = body.id;\n' +
    '        outputs.ticket_url = body.self;\n' +
    '        outputs.success = true;\n' +
    '    } else {\n' +
    '        outputs.success = false;\n' +
    '        outputs.error_message = "Failed: " + response.status_code;\n' +
    '    }\n' +
    '})(inputs, outputs);'
);

scriptStep.insert();

Subflows for Reuse (ES5)

Create Integration Subflow

// Subflows encapsulate reusable integration logic
// Created via Flow Designer UI, but can be invoked via script

// Invoke subflow from script (ES5 ONLY!)
var inputs = {
    ticket_id: 'INC0010001',
    action: 'update',
    fields: {
        status: 'resolved',
        resolution: 'Fixed'
    }
};

// Start subflow
sn_fd.FlowAPI.startSubflow('x_myapp_update_external_ticket', inputs);

Execute Action from Script

// Execute spoke action from script (ES5 ONLY!)
var actionInputs = {
    summary: 'New ticket from ServiceNow',
    description: 'Created via integration',
    priority: 'Medium'
};

try {
    var result = sn_fd.FlowAPI.executeAction(
        'x_myapp_itsm.create_external_ticket',
        actionInputs
    );

    if (result.outputs.success) {
        gs.info('Created ticket: ' + result.outputs.ticket_id);
    } else {
        gs.error('Failed: ' + result.outputs.error_message);
    }
} catch (e) {
    gs.error('Action execution failed: ' + e.message);
}

Error Handling (ES5)

Action Error Handling

// Error handling in action script (ES5 ONLY!)
(function execute(inputs, outputs) {
    try {
        // Main logic
        var response = callExternalAPI(inputs);

        if (response.status_code >= 400) {
            throw new Error('API error: ' + response.status_code + ' - ' + response.body);
        }

        outputs.result = JSON.parse(response.body);
        outputs.success = true;

    } catch (e) {
        outputs.success = false;
        outputs.error_code = 'INTEGRATION_ERROR';
        outputs.error_message = e.message;

        // Log for debugging
        gs.error('IntegrationHub action failed: ' + e.message);

        // Optionally throw to trigger Flow Designer error handling
        // throw e;
    }
})(inputs, outputs);

Retry Logic

// Retry wrapper for transient failures (ES5 ONLY!)
function executeWithRetry(fn, maxRetries, delayMs) {
    var attempts = 0;
    var lastError = null;

    while (attempts < maxRetries) {
        try {
            return fn();
        } catch (e) {
            lastError = e;
            attempts++;

            if (attempts < maxRetries) {
                gs.info('Retry ' + attempts + ' of ' + maxRetries + ' after error: ' + e.message);
                gs.sleep(delayMs * attempts);  // Exponential backoff
            }
        }
    }

    throw new Error('Failed after ' + maxRetries + ' attempts: ' + lastError.message);
}

MCP Tool Integration

Available Tools

ToolPurpose
snow_query_tableQuery spokes and actions
snow_find_artifactFind integration configs
snow_test_rest_connectionTest connections
snow_execute_script_with_outputTest action scripts

Example Workflow

// 1. Find available spokes
await snow_query_table({
    table: 'sn_ih_spoke',
    query: 'active=true',
    fields: 'name,label,vendor,version'
});

// 2. Get spoke actions
await snow_query_table({
    table: 'sn_ih_action',
    query: 'spoke.name=Jira Spoke',
    fields: 'name,label,description,category'
});

// 3. Test connection
await snow_test_rest_connection({
    connection_alias: 'x_myapp_jira_connection',
    credential_alias: 'x_myapp_jira_credential'
});

Best Practices

  1. Connection Aliases - Abstract connection details
  2. Credential Security - Never hardcode credentials
  3. Error Handling - Graceful failure handling
  4. Retry Logic - Handle transient failures
  5. Logging - Comprehensive debug logging
  6. Testing - Test with mock data first
  7. Versioning - Track spoke versions
  8. ES5 Only - No modern JavaScript syntax

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