skills/genai/spoke-generation/SKILL.md
Generate Integration Hub spokes for connecting external services including spoke actions, connection aliases, data transformations, error handling, and REST/SOAP integrations
npx skillsauth add happy-technologies-llc/happy-servicenow-skills spoke-generationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill covers generating ServiceNow Integration Hub spokes for connecting to external services:
When to use: When building reusable integrations with external APIs, creating custom connectors for third-party services, or packaging integration logic into deployable spokes.
integration_admin, flow_designer, or admincom.glide.hub.flow_designer (Flow Designer), com.glide.hub.integration (Integration Hub)genai/flow-generation for consuming spokes in flowsParse the integration request to identify:
MCP Approach:
Use SN-Query-Table on sys_spoke:
- query: active=true
- fields: sys_id,name,description,scope,logo,active
- limit: 20
Query existing spoke actions:
Use SN-Query-Table on sys_hub_action_type_definition:
- query: spoke=<spoke_sys_id>^active=true
- fields: sys_id,name,description,action_type,inputs,outputs
- limit: 20
REST Approach:
GET /api/now/table/sys_spoke
?sysparm_query=active=true
&sysparm_fields=sys_id,name,description,scope,active
&sysparm_limit=20
MCP Approach:
Use SN-Create-Record on sys_spoke:
- name: "Acme CRM Spoke"
- description: "Integration spoke for Acme CRM REST API - supports contacts, deals, and activities"
- scope: "x_acme_crm"
- logo: ""
- active: true
- version: "1.0.0"
REST Approach:
POST /api/now/table/sys_spoke
Body: {
"name": "Acme CRM Spoke",
"description": "Integration spoke for Acme CRM REST API - supports contacts, deals, and activities",
"scope": "x_acme_crm",
"active": true,
"version": "1.0.0"
}
Connection aliases provide secure, reusable credential storage.
Connection Alias Types:
| Type | Value | Use Case | |------|-------|----------| | HTTP Connection | http_connection | REST/SOAP API credentials | | JDBC Connection | jdbc_connection | Database connections | | LDAP Connection | ldap_connection | Directory services | | Custom | custom | Non-standard authentication |
MCP Approach:
Use SN-Create-Record on sys_connection_alias:
- name: "Acme CRM API"
- connection_type: "http_connection"
- description: "Connection alias for Acme CRM REST API"
- active: true
- scope: "x_acme_crm"
- spoke: "<spoke_sys_id>"
REST Approach:
POST /api/now/table/sys_connection_alias
Body: {
"name": "Acme CRM API",
"connection_type": "http_connection",
"description": "Connection alias for Acme CRM REST API",
"active": true,
"scope": "x_acme_crm",
"spoke": "<spoke_sys_id>"
}
Configure Credential (Basic Auth):
Use SN-Create-Record on sys_alias_credential:
- connection_alias: "<connection_alias_sys_id>"
- type: "basic_auth"
- user_name: "${connection.username}"
- password: "${connection.password}"
- active: true
Configure Credential (OAuth 2.0):
Use SN-Create-Record on sys_alias_credential:
- connection_alias: "<connection_alias_sys_id>"
- type: "oauth2"
- oauth_profile: "<oauth_profile_sys_id>"
- active: true
Each action represents an operation the spoke can perform.
MCP Approach:
Use SN-Create-Record on sys_hub_action_type_definition:
- name: "Create Contact"
- description: "Creates a new contact in Acme CRM"
- spoke: "<spoke_sys_id>"
- action_type: "custom"
- category: "x_acme_crm"
- access: "public"
- active: true
- annotation: "Creates a contact record in external CRM system"
Use SN-Create-Record on sys_hub_action_type_definition:
- name: "Get Contact"
- description: "Retrieves a contact by ID from Acme CRM"
- spoke: "<spoke_sys_id>"
- action_type: "custom"
- category: "x_acme_crm"
- access: "public"
- active: true
Use SN-Create-Record on sys_hub_action_type_definition:
- name: "Search Contacts"
- description: "Searches contacts in Acme CRM by criteria"
- spoke: "<spoke_sys_id>"
- action_type: "custom"
- category: "x_acme_crm"
- access: "public"
- active: true
REST Approach:
POST /api/now/table/sys_hub_action_type_definition
Body: {
"name": "Create Contact",
"description": "Creates a new contact in Acme CRM",
"spoke": "<spoke_sys_id>",
"action_type": "custom",
"category": "x_acme_crm",
"access": "public",
"active": true
}
MCP Approach:
Use SN-Create-Record on sys_hub_action_input:
- action_type: "<create_contact_action_sys_id>"
- name: "first_name"
- label: "First Name"
- type: "string"
- mandatory: true
- order: 100
Use SN-Create-Record on sys_hub_action_input:
- action_type: "<create_contact_action_sys_id>"
- name: "last_name"
- label: "Last Name"
- type: "string"
- mandatory: true
- order: 200
Use SN-Create-Record on sys_hub_action_input:
- action_type: "<create_contact_action_sys_id>"
- name: "email"
- label: "Email Address"
- type: "string"
- mandatory: true
- order: 300
Use SN-Create-Record on sys_hub_action_input:
- action_type: "<create_contact_action_sys_id>"
- name: "company_id"
- label: "Company ID"
- type: "string"
- mandatory: false
- order: 400
REST Approach:
POST /api/now/table/sys_hub_action_input
Body: {
"action_type": "<create_contact_action_sys_id>",
"name": "email",
"label": "Email Address",
"type": "string",
"mandatory": true,
"order": 300
}
REST steps define the actual HTTP calls to external services.
MCP Approach:
Use SN-Create-Record on sys_hub_rest_step:
- action_type: "<create_contact_action_sys_id>"
- name: "Call Create Contact API"
- order: 100
- connection_alias: "<connection_alias_sys_id>"
- http_method: "POST"
- resource_path: "/api/v2/contacts"
- content_type: "application/json"
- request_body: '{
"first_name": "${inputs.first_name}",
"last_name": "${inputs.last_name}",
"email": "${inputs.email}",
"company_id": "${inputs.company_id}"
}'
- headers: '[{"name":"Accept","value":"application/json"}]'
REST Approach:
POST /api/now/table/sys_hub_rest_step
Body: {
"action_type": "<create_contact_action_sys_id>",
"name": "Call Create Contact API",
"order": 100,
"connection_alias": "<connection_alias_sys_id>",
"http_method": "POST",
"resource_path": "/api/v2/contacts",
"content_type": "application/json",
"request_body": "{\"first_name\":\"${inputs.first_name}\",\"last_name\":\"${inputs.last_name}\",\"email\":\"${inputs.email}\"}"
}
GET Request Example:
Use SN-Create-Record on sys_hub_rest_step:
- action_type: "<get_contact_action_sys_id>"
- name: "Call Get Contact API"
- order: 100
- connection_alias: "<connection_alias_sys_id>"
- http_method: "GET"
- resource_path: "/api/v2/contacts/${inputs.contact_id}"
- content_type: "application/json"
- headers: '[{"name":"Accept","value":"application/json"}]'
MCP Approach:
Use SN-Create-Record on sys_hub_action_output:
- action_type: "<create_contact_action_sys_id>"
- name: "contact_id"
- label: "Contact ID"
- type: "string"
- order: 100
Use SN-Create-Record on sys_hub_action_output:
- action_type: "<create_contact_action_sys_id>"
- name: "status_code"
- label: "HTTP Status Code"
- type: "integer"
- order: 200
Use SN-Create-Record on sys_hub_action_output:
- action_type: "<create_contact_action_sys_id>"
- name: "response_body"
- label: "Response Body"
- type: "string"
- order: 300
MCP Approach:
Use SN-Create-Record on sys_hub_script_step:
- action_type: "<create_contact_action_sys_id>"
- name: "Handle Response"
- order: 200
- script: |
(function execute(inputs, outputs) {
var statusCode = inputs.rest_step_status_code;
var responseBody = inputs.rest_step_response_body;
if (statusCode == 201) {
var response = JSON.parse(responseBody);
outputs.contact_id = response.id;
outputs.status_code = statusCode;
} else if (statusCode == 409) {
throw new Error('Contact already exists: ' + responseBody);
} else if (statusCode == 429) {
throw new Error('Rate limit exceeded. Retry after cooldown.');
} else {
throw new Error('API error ' + statusCode + ': ' + responseBody);
}
})(inputs, outputs);
MCP Approach:
Use SN-Update-Record on sys_spoke:
- sys_id: "<spoke_sys_id>"
- active: true
Verify all actions are properly configured:
Use SN-Query-Table on sys_hub_action_type_definition:
- query: spoke=<spoke_sys_id>
- fields: sys_id,name,active,action_type
- limit: 50
Verify connection alias is available:
Use SN-Query-Table on sys_connection_alias:
- query: spoke=<spoke_sys_id>
- fields: sys_id,name,connection_type,active
| Tool | Purpose | When to Use | |------|---------|-------------| | SN-Query-Table | Find existing spokes and actions | Pattern discovery and validation | | SN-Create-Record | Create spokes, actions, inputs, outputs, steps | Building spoke components | | SN-Update-Record | Modify spoke settings, activate spokes | Editing and publishing | | SN-Get-Table-Schema | Discover spoke table fields | Understanding available configurations |
| Issue | Cause | Resolution | |-------|-------|------------| | Connection test fails | Invalid credentials or URL in connection alias | Verify connection alias configuration and test connectivity | | 401 Unauthorized | OAuth token expired or invalid credentials | Refresh OAuth token or update credential record | | 403 Forbidden | API key lacks required permissions | Check external service permissions for the integration user | | REST step timeout | External service slow or unreachable | Increase timeout on REST step or check network connectivity | | Response parsing error | Unexpected response format from API | Add defensive JSON parsing in script step with try/catch | | Action not visible in Flow Designer | Action access set to private or spoke inactive | Set access to "public" and verify spoke is active | | Input data truncated | String field length limits | Use multi-line text type for large payloads |
Generate a spoke for sending Slack messages:
Generate a spoke for Jira Cloud operations:
Generate a spoke for a custom internal microservice:
genai/flow-generation - Flow Designer flows that consume spoke actionsgenai/playbook-generation - Playbooks that call spoke actions as activitiescatalog/approval-workflows - Approval flows that may trigger external notificationsadmin/connection-management - Connection alias and credential configurationtesting
Manage supplier onboarding, qualification, performance monitoring, and offboarding with auditable lifecycle controls
tools
Identify emerging risks, prioritize intake signals, and route candidates into formal GRC risk assessment workflows
documentation
Screen inbound documents for completeness, policy risk, and routing readiness before extraction or case workflows
testing
Generate concise task summaries with status, timeline, blockers, SLA risk, and recommended next actions