スキル一覧に戻る
groeimetai

agent-workspace

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📅 2026年1月23日
GitHubで見るManusで実行

SKILL.md


name: agent-workspace description: This skill should be used when the user asks to "agent workspace", "workspace configuration", "workspace form", "workspace list", "agent assist", "contextual side panel", "workspace customization", or any ServiceNow Agent Workspace development. license: Apache-2.0 compatibility: Designed for Snow-Code and ServiceNow development metadata: author: groeimetai version: "1.0.0" category: servicenow tools:

  • snow_workspace_create
  • snow_query_table
  • snow_find_artifact
  • snow_execute_script_with_output

Agent Workspace for ServiceNow

Agent Workspace provides a modern, configurable interface for fulfiller productivity.

Workspace Architecture

Workspace (sys_aw_workspace)
    ├── Lists (sys_aw_list)
    ├── Forms (sys_aw_form)
    ├── Related Lists
    ├── UI Actions
    └── Contextual Side Panel
        ├── Agent Assist
        ├── Related Records
        └── Activity Stream

Key Tables

TablePurpose
sys_aw_workspaceWorkspace definitions
sys_aw_listList configurations
sys_aw_formForm configurations
sys_aw_related_listRelated list configs
sys_aw_actionWorkspace UI actions

Workspace Configuration (ES5)

Create Workspace

// Create workspace (ES5 ONLY!)
var workspace = new GlideRecord('sys_aw_workspace');
workspace.initialize();

// Basic info
workspace.setValue('name', 'IT Service Desk Workspace');
workspace.setValue('title', 'IT Service Desk');
workspace.setValue('description', 'Workspace for IT service desk agents');

// Primary table
workspace.setValue('primary_table', 'incident');

// URL path
workspace.setValue('url', 'it-service-desk');

// Icon and branding
workspace.setValue('icon', 'support');
workspace.setValue('color', '#0056B3');

// Default list
workspace.setValue('default_list', getListConfig('incident_active'));

// Enable features
workspace.setValue('agent_assist_enabled', true);
workspace.setValue('contextual_side_panel_enabled', true);
workspace.setValue('activity_stream_enabled', true);

workspace.insert();

Workspace List Configuration

// Create list configuration (ES5 ONLY!)
var list = new GlideRecord('sys_aw_list');
list.initialize();

list.setValue('name', 'My Active Incidents');
list.setValue('table', 'incident');
list.setValue('workspace', workspaceSysId);

// Filter
list.setValue('filter', 'active=true^assigned_to=javascript:gs.getUserID()');

// Columns
list.setValue('columns', 'number,short_description,priority,state,caller_id,opened_at');

// Sort
list.setValue('order_by', 'priority');
list.setValue('order_by_desc', false);

// Row actions
list.setValue('show_row_actions', true);

// Grouping (optional)
list.setValue('group_by', 'priority');

list.insert();

Workspace Form Configuration

// Create form configuration (ES5 ONLY!)
var form = new GlideRecord('sys_aw_form');
form.initialize();

form.setValue('name', 'Incident Form');
form.setValue('table', 'incident');
form.setValue('workspace', workspaceSysId);

// Form sections
var sections = [
    {
        name: 'Details',
        columns: 2,
        fields: ['number', 'state', 'caller_id', 'opened_at', 'short_description', 'priority']
    },
    {
        name: 'Assignment',
        columns: 2,
        fields: ['assignment_group', 'assigned_to', 'escalation']
    },
    {
        name: 'Resolution',
        columns: 1,
        fields: ['resolution_code', 'close_notes'],
        condition: 'state=6^ORstate=7'  // Only show for resolved/closed
    }
];

form.setValue('sections', JSON.stringify(sections));

// Related lists
form.setValue('related_lists', 'incident.task_sla,incident.sys_attachment');

// Enable Agent Assist
form.setValue('agent_assist_enabled', true);

form.insert();

Contextual Side Panel (ES5)

Configure Side Panel

// Side panel configuration (ES5 ONLY!)
var panel = new GlideRecord('sys_aw_contextual_side_panel');
panel.initialize();

panel.setValue('workspace', workspaceSysId);
panel.setValue('table', 'incident');
panel.setValue('name', 'Incident Context');

// Tabs
var tabs = [
    {
        id: 'agent_assist',
        label: 'Agent Assist',
        icon: 'lightbulb-outline',
        component: 'agent-assist'
    },
    {
        id: 'caller_info',
        label: 'Caller Info',
        icon: 'user',
        component: 'custom-caller-info'
    },
    {
        id: 'related',
        label: 'Related Records',
        icon: 'link',
        component: 'related-records'
    },
    {
        id: 'activity',
        label: 'Activity',
        icon: 'history',
        component: 'activity-stream'
    }
];

panel.setValue('tabs', JSON.stringify(tabs));
panel.setValue('default_tab', 'agent_assist');

panel.insert();

Custom Panel Component (ES5)

// Widget for side panel (ES5 ONLY!)
// Server Script
(function() {
    // Get current record from context
    var recordSysId = input.sys_id;
    var tableName = input.table;

    if (tableName === 'incident' && recordSysId) {
        var gr = new GlideRecord('incident');
        if (gr.get(recordSysId)) {
            // Get caller information
            data.caller = {
                name: gr.caller_id.getDisplayValue(),
                email: gr.caller_id.email.getDisplayValue(),
                phone: gr.caller_id.phone.getDisplayValue(),
                location: gr.caller_id.location.getDisplayValue(),
                vip: gr.caller_id.vip.getDisplayValue() === 'true'
            };

            // Get caller's open incidents
            data.openIncidents = [];
            var incidents = new GlideRecord('incident');
            incidents.addQuery('caller_id', gr.getValue('caller_id'));
            incidents.addQuery('active', true);
            incidents.addQuery('sys_id', '!=', recordSysId);
            incidents.orderByDesc('opened_at');
            incidents.setLimit(5);
            incidents.query();

            while (incidents.next()) {
                data.openIncidents.push({
                    sys_id: incidents.getUniqueValue(),
                    number: incidents.getValue('number'),
                    short_description: incidents.getValue('short_description'),
                    state: incidents.state.getDisplayValue()
                });
            }
        }
    }
})();

Agent Assist (ES5)

Configure Agent Assist

// Agent Assist configuration (ES5 ONLY!)
var config = new GlideRecord('sys_aw_agent_assist_config');
config.initialize();

config.setValue('workspace', workspaceSysId);
config.setValue('table', 'incident');
config.setValue('name', 'Incident Agent Assist');
config.setValue('active', true);

// Recommendations sources
config.setValue('show_knowledge', true);
config.setValue('show_similar_incidents', true);
config.setValue('show_solutions', true);
config.setValue('show_macros', true);

// Knowledge search configuration
config.setValue('knowledge_bases', kbSysIds);  // Comma-separated
config.setValue('knowledge_search_fields', 'short_description,description');

config.insert();

Similar Records Script (ES5)

// Find similar incidents for Agent Assist (ES5 ONLY!)
var SimilarIncidentFinder = Class.create();
SimilarIncidentFinder.prototype = {
    initialize: function() {},

    /**
     * Find similar resolved incidents
     */
    findSimilar: function(incidentSysId) {
        var current = new GlideRecord('incident');
        if (!current.get(incidentSysId)) {
            return [];
        }

        var similar = [];
        var keywords = this._extractKeywords(current.getValue('short_description'));

        // Search resolved incidents
        var gr = new GlideRecord('incident');
        gr.addQuery('state', 'IN', '6,7');  // Resolved or Closed
        gr.addQuery('sys_id', '!=', incidentSysId);

        // Match by category
        if (current.category) {
            gr.addQuery('category', current.getValue('category'));
        }

        // Match by CI
        if (current.cmdb_ci) {
            gr.addOrCondition('cmdb_ci', current.getValue('cmdb_ci'));
        }

        // Keyword matching
        for (var i = 0; i < keywords.length && i < 3; i++) {
            gr.addOrCondition('short_description', 'CONTAINS', keywords[i]);
        }

        gr.setLimit(10);
        gr.orderByDesc('resolved_at');
        gr.query();

        while (gr.next()) {
            var score = this._calculateSimilarity(current, gr);
            if (score > 0.3) {
                similar.push({
                    sys_id: gr.getUniqueValue(),
                    number: gr.getValue('number'),
                    short_description: gr.getValue('short_description'),
                    resolution_code: gr.resolution_code.getDisplayValue(),
                    close_notes: gr.getValue('close_notes'),
                    score: Math.round(score * 100)
                });
            }
        }

        // Sort by similarity score
        similar.sort(function(a, b) {
            return b.score - a.score;
        });

        return similar.slice(0, 5);
    },

    _extractKeywords: function(text) {
        var stopWords = ['the', 'is', 'at', 'which', 'on', 'a', 'an', 'and', 'or', 'not', 'to', 'for'];
        var words = text.toLowerCase().split(/\s+/);
        var keywords = [];

        for (var i = 0; i < words.length; i++) {
            var word = words[i].replace(/[^a-z0-9]/g, '');
            if (word.length > 3 && stopWords.indexOf(word) === -1) {
                keywords.push(word);
            }
        }

        return keywords;
    },

    _calculateSimilarity: function(source, target) {
        var score = 0;

        // Category match
        if (source.getValue('category') === target.getValue('category')) {
            score += 0.3;
        }

        // Subcategory match
        if (source.getValue('subcategory') === target.getValue('subcategory')) {
            score += 0.2;
        }

        // CI match
        if (source.getValue('cmdb_ci') === target.getValue('cmdb_ci')) {
            score += 0.3;
        }

        // Keyword overlap
        var sourceKeywords = this._extractKeywords(source.getValue('short_description'));
        var targetKeywords = this._extractKeywords(target.getValue('short_description'));
        var overlap = 0;

        for (var i = 0; i < sourceKeywords.length; i++) {
            if (targetKeywords.indexOf(sourceKeywords[i]) !== -1) {
                overlap++;
            }
        }

        if (sourceKeywords.length > 0) {
            score += 0.2 * (overlap / sourceKeywords.length);
        }

        return score;
    },

    type: 'SimilarIncidentFinder'
};

Workspace UI Actions (ES5)

Create Workspace Action

// Create workspace-specific UI action (ES5 ONLY!)
var action = new GlideRecord('sys_aw_action');
action.initialize();

action.setValue('name', 'Quick Resolve');
action.setValue('label', 'Quick Resolve');
action.setValue('workspace', workspaceSysId);
action.setValue('table', 'incident');

// Action type
action.setValue('action_type', 'form');  // form, list, both
action.setValue('order', 100);

// Condition
action.setValue('condition', 'current.active == true && current.state != 6');

// Client action (opens modal)
action.setValue('client_script',
    'function onClick() {\n' +
    '    spModal.open({\n' +
    '        title: "Quick Resolve",\n' +
    '        widget: "quick-resolve-modal",\n' +
    '        widgetInput: { table: g_form.getTableName(), sys_id: g_form.getUniqueValue() }\n' +
    '    }).then(function(result) {\n' +
    '        if (result) {\n' +
    '            g_form.setValue("state", 6);\n' +
    '            g_form.setValue("resolution_code", result.code);\n' +
    '            g_form.setValue("close_notes", result.notes);\n' +
    '            g_form.save();\n' +
    '        }\n' +
    '    });\n' +
    '}'
);

// Icon and style
action.setValue('icon', 'check-circle');
action.setValue('button_class', 'btn-success');

action.insert();

MCP Tool Integration

Available Tools

ToolPurpose
snow_find_artifactFind workspace configs
snow_query_tableQuery workspace tables
snow_deployDeploy workspace widgets
snow_execute_script_with_outputTest workspace scripts

Example Workflow

// 1. Find workspaces
await snow_query_table({
    table: 'sys_aw_workspace',
    query: 'active=true',
    fields: 'name,title,primary_table,url'
});

// 2. Get list configurations
await snow_query_table({
    table: 'sys_aw_list',
    query: 'workspace.name=IT Service Desk Workspace',
    fields: 'name,table,filter,columns'
});

// 3. Test similar incident finder
await snow_execute_script_with_output({
    script: `
        var finder = new SimilarIncidentFinder();
        var similar = finder.findSimilar('incident_sys_id');
        gs.info('Found: ' + similar.length);
    `
});

Best Practices

  1. Role-Based - Design for specific roles
  2. Efficient Lists - Optimized filters and columns
  3. Context Panel - Relevant information accessible
  4. Agent Assist - Enable knowledge/similar records
  5. Actions - Streamline common tasks
  6. Performance - Lazy load components
  7. Mobile Ready - Test responsive layouts
  8. ES5 Only - No modern JavaScript syntax

スコア

総合スコア

75/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新

+5
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

レビュー

💬

レビュー機能は近日公開予定です