AiAgenticWorkflow
Configure an AI Agentic Workflow using the Fluent API. This API provides a structured interface for creating AI Agentic Workflows in ServiceNow's AI Agent Studio, automatically handling all underlying complexity and relationships between multiple tables.
Overview
The AiAgenticWorkflow API enables you to define intelligent workflows that can:
- Orchestrate Multiple Agents: Coordinate multiple AI agents working together as a team
- Process Context: Apply custom scripts to transform context before execution
- Control Access: Define role-based security and data access controls
- Trigger Automatically: Configure triggers for automatic workflow invocation
- Manage Versions: Support multiple versions with different configurations
- Execute Dynamically: Run with dynamic user identity based on role-based access
The plugin automatically generates all required ServiceNow records (~7 tables) with proper relationships and defaults.
Default Value Suppression
The plugin follows a "only specify what differs from defaults" pattern. During transform (ServiceNow → Fluent), fields that match their default values are automatically omitted from the generated code. This keeps Fluent files clean and minimal. For example:
active: true→ omitted (default for workflow)executionMode: 'copilot'→ omitted (default)sysDomain: 'global'→ omitted (default)enableDiscovery: false→ omitted (default for trigger config)portal: ''→ omitted (empty string default)
Only specify fields when their values differ from the defaults listed in this document.
Supported Record Types
Based on the metadata files generated by this plugin:
| Record Type | Table | Description |
|---|---|---|
| AI Agentic Workflow | sn_aia_usecase | Primary workflow definition |
| AI Team | sn_aia_team | Team configuration for the workflow |
| AI Team Member | sn_aia_team_member | Team member associations (agents in the team) |
| AI Version | sn_aia_version | Version information for the workflow |
| Use Case Config Override | sn_aia_usecase_config_override | Configuration overrides for the workflow |
| Trigger Configuration | sn_aia_trigger_configuration | Automated trigger definitions |
| Trigger Agent Usecase M2M | sn_aia_trigger_agent_usecase_m2m | Mapping between triggers, workflows, and use cases |
| Agent Access Role Configuration | sys_agent_access_role_configuration | Role-based data access controls |
API Parameters
Main Configuration
| Field Name | Type | Mandatory | Default | Description |
|---|---|---|---|---|
$id | Now.ID[string] | Yes | Unique identifier for the workflow | |
name | string | Yes | Display name of the AI Agentic Workflow | |
description | string | Yes | Brief description of what the workflow does | |
securityAcl | SecurityAclUserAccessConfig | Yes | MANDATORY - Automatically generates sys_security_acl and sys_security_acl_role records. Uses discriminated union on type: 'Any authenticated user', 'Specific role', or 'Public' | |
team | TeamType | No | Team configuration with nested members array | |
versions | AIAVersion[] | No | Array of version configurations | |
runAs | string | No | Field name for run-as user (dynamic resolution). Omit for dynamic user identity | |
dataAccess | DataAccessConfigWorkflowType | No | Data access controls (required when runAs is not set) | |
triggerConfig | TriggerConfigType[] | No | Array of trigger configurations for automatic invocation | |
recordType | 'custom' | 'template' | 'aia_internal' | No | 'template' | Record type |
executionMode | 'copilot' | 'autopilot' | No | 'copilot' | Execution mode for the workflow |
active | boolean | No | true | Whether the workflow is active |
sysDomain | string | No | 'global' | Domain ID |
contextProcessingScript | function | string | No | Script to process context - supports inline or Now.include() | |
memoryScope | string | No | 'global' | Memory scope for team members |
Note: The following fields are auto-generated by the plugin and should not be specified by users:
internalName: Auto-generated fromdomain.scope.name- Trigger
useCase: Auto-populated with parent workflow ID
Team Configuration (team)
Team configuration for organizing multiple agents. The team has a nested members array.
Key Fields:
$id— Unique identifier (MANDATORY for teams)name— Team namesysDomain— Domain ID (default: 'global', omit if global)members— Array of agent sys_ids or Record references
Note: Team
descriptionis auto-populated from the workflow'sdescriptionfield. Do not specify it.
Team Members (team.members)
Simple array of agent sys_ids or Record references nested within the team configuration.
Example:
import { AiAgenticWorkflow, Record } from '@servicenow/sdk/core'
const summaryAgent = Record({
table: 'sn_aia_agent',
$id: Now.ID['summary_agent'],
data: { name: 'Record Summary Agent' },
})
const searchAgent = Record({
table: 'sn_aia_agent',
$id: Now.ID['search_agent'],
data: { name: 'Search Q&A Agent' },
})
AiAgenticWorkflow({
name: 'Dynamic User Workflow',
description: 'Workflow with dynamic user identity',
securityAcl: {
$id: Now.ID['dynamic_user_workflow_acl'],
type: 'Any authenticated user',
},
dataAccess: {
roleList: [
itilRole, // Role reference
userAdminRole, // Role reference
],
description: 'Data access for itil and user_admin roles',
},
team: {
$id: Now.ID['my_team'],
name: 'Analysis Team',
members: [summaryAgent, searchAgent],
},
})
Important Notes:
- Using the
RecordAPI is recommended for better readability and portability across instances - When using sys_id strings, they must be valid GUIDs (32-character hex strings)
- Non-GUID strings will trigger validation errors
Version Configuration (versions)
Version information for the workflow.
Key Fields:
name— Version namenumber— Version numberinstructions— Version-specific instructionsstate— Version state:'published','draft','committed', or'withdrawn'(default: 'draft', omit if draft)
Run As User (runAs)
Specifies which user the Agentic Workflow runs as.
Important Notes:
- If
runAsis set to a user sys_id, the workflow runs as that specific user - If
runAsis omitted, the workflow uses dynamic user identity anddataAccessbecomes mandatory - Dynamic user identity means the workflow inherits roles from the invoking user based on
dataAccess.roleList
Security ACL Configuration (securityAcl)
MANDATORY - Automatically generates sys_security_acl and sys_security_acl_role records for this workflow. Controls who can invoke the workflow.
Access Types
'Any authenticated user' — Any logged-in user can invoke this workflow.
'Specific role' — Only users who hold at least one of the listed roles can access. roles is required.
'Public' — No authentication required.
Important Notes:
securityAclcontrols who can invoke the workflow (access control)runAs/dataAccesscontrols which user identity the workflow runs under (execution context) — these are separate concerns- The plugin automatically creates
sys_security_aclandsys_security_acl_rolerecords - The ACL name is derived from the workflow's internal name:
{domain}.{scope}.{workflowName}
Data Access Controls (dataAccess)
MANDATORY when runAs is omitted - Defines which roles the workflow can inherit from the invoking user during execution.
Note: The
actionfield is automatically set to'limit_to_roles'by the plugin. Fields likeagent,agentTable,name, andsysDomainare also auto-populated. The entiredataAccessobject is omitted from transform output when no roles are specified.
Example
import { AiAgenticWorkflow, Role } from '@servicenow/sdk/core'
const itilRole = Role({
$id: Now.ID['itil_role'],
name: 'x_app.itil',
description: 'ITIL role for incident management',
})
const userAdminRole = Role({
$id: Now.ID['user_admin_role'],
name: 'x_app.user_admin',
description: 'User administration role',
})
AiAgenticWorkflow({
name: 'Dynamic User Workflow',
description: 'Workflow with dynamic user identity',
securityAcl: {
$id: Now.ID['dynamic_user_workflow_acl'],
type: 'Any authenticated user',
},
// runAs is omitted — dynamic user identity
dataAccess: {
roleList: [
itilRole, // Role reference
userAdminRole, // Role reference
],
description: 'Data access for itil and user_admin roles',
},
})
When to Use:
- Use
dataAccesswhen you want the workflow to run with dynamic user identity (omitrunAs) - Omit
dataAccesswhenrunAsis set to a specific user sys_id
Trigger Configuration (triggerConfig)
Configure automatic workflow invocation based on record changes or schedules.
Trigger Types
| Trigger Type | Description |
|---|---|
record_create | Triggers when a new record is created |
record_create_or_update | Triggers when a record is created or updated |
record_update | Triggers when an existing record is updated |
email | Triggers based on email events |
scheduled | Triggers at scheduled intervals |
daily | Triggers daily at a specified time |
weekly | Triggers weekly on a specified day |
monthly | Triggers monthly on a specified day |
ui_action | Triggers from a UI action |
Complete Examples
Example 1: Workflow with Data Access (from AiAgenticWorkflow.now.ts)
This example matches the actual transform output — only non-default fields are specified.
import { AiAgenticWorkflow } from '@servicenow/sdk/core'
export const exampleAgenticWorkflow = AiAgenticWorkflow({
$id: Now.ID['employee_record_summarization_workflow'],
name: 'Employee Record Summarization',
description: 'Analyzes employee records and generates summaries',
recordType: 'custom',
securityAcl: {
$id: Now.ID['employee_summarization_workflow_acl'],
type: 'Any authenticated user',
},
team: {
$id: Now.ID['employee_summarization_team'],
name: 'Employee Summarization Team',
members: [
'274b465a7d5f42e581664209557b2b18', // Record Summary Agent sys_id
'2dfb22af3351f2101ea99d273e5c7ba3', // Search Q&A Agent sys_id
],
},
versions: [
{
name: 'V1',
number: 1,
state: 'published',
instructions: 'Fetch employee record, analyze key fields, and generate summary',
},
{
name: 'V2',
number: 2,
instructions: 'Enhanced version with validation and department analysis',
},
],
triggerConfig: [
// Record based trigger
{
name: 'Employee Record Created',
targetTable: 'x_snc_cust_app_age_employee',
triggerFlowDefinitionType: 'record_create',
triggerCondition: 'first_nameISNOTEMPTY',
objectiveTemplate: 'Summarize employee record ${sys_id}',
runAsScript: Now.include('./run-as-script.js'),
showNotifications: true,
channel: 'Now Assist Panel',
},
// Schedule based trigger
{
name: 'Weekly Employee Review',
active: true,
targetTable: 'x_snc_cust_app_age_employee',
triggerFlowDefinitionType: 'scheduled',
objectiveTemplate: 'Review all employee records for the week',
schedule: {
runDayOfWeek: 2, // Monday
runDayOfMonth: 2,
starting: '1970-01-01 09:00:00', // 9:00 AM
time: '1970-01-01 09:00:00', // 9:00 AM
},
channel: 'Now Assist Panel',
},
],
dataAccess: {
roleList: ['2831a114c611228501d4ea6c309d626d'], // admin role sys_id
description: 'Restrict workflow access to admin role',
},
})
Example 2: Workflow with Dynamic User Identity (from DynamicUserWorkflow.now.ts)
import { AiAgenticWorkflow } from '@servicenow/sdk/core'
export const dynamicUserWorkflow = AiAgenticWorkflow({
$id: Now.ID['incident_management_workflow'],
name: 'Incident Management Workflow',
description:
'This workflow analyzes incident records, identifies patterns, and provides resolution recommendations',
recordType: 'custom',
runAs: '<sys_user_id>'
team: {
$id: Now.ID['incident_workflow_team'],
name: 'Incident Management Team',
members: [],
},
versions: [
{
name: 'V1',
number: 1,
state: 'published',
instructions:
'Analyze incident ${number} with priority ${priority}. Identify potential root causes and suggest resolution steps based on similar past incidents.',
},
],
// Security ACL — controls who can invoke this workflow
securityAcl: {
$id: Now.ID['incident_management_workflow_acl'],
type: 'Any authenticated user',
},
})
Best Practices
1. Security Configuration
- Always set
securityAcl— it is mandatory and auto-generates thesys_security_aclrecord securityAcl.typecontrols who can invoke the workflow:'Any authenticated user','Specific role', or'Public'securityAcl.$idis required — it identifies the generated ACL recordrunAsis separate fromsecurityAcl: it is a field name used for dynamic user resolution (not who can invoke the workflow)- Use
dataAccess.roleListwhenrunAsis not set, to restrict which roles the workflow can inherit from the invoking user
2. Team Configuration
- Always provide
team.$idwhen creating a team (mandatory for teams) - Use meaningful team names that describe the purpose
- Use simple array of strings for
team.members- just agent sys_ids or Record references - Do not set team
description- it is auto-populated from the workflow's description - No need to specify
sysDomain- it defaults to'global' - No need to specify
memoryScope- it defaults to'global'
3. Version Management
- Omit
statefor draft versions (default is'draft') - Use
state: 'published'for production - Increment
numberfor new versions (e.g., 1, 2, 3) - Use meaningful
name(e.g., "V1", "V2")
4. Trigger Configuration
- Only specify non-default fields - defaults are automatically suppressed during transform
- Use
'Now Assist Panel'for channel - auto-mapped to sys_id - Use specific
triggerConditionto avoid unnecessary invocations - Include
objectiveTemplatein trigger config for the objective message - Validate
startingfield format: YYYY-MM-DD HH:MM:SS - Trigger mappings are auto-generated - no need to specify them manually
- Default values to omit:
active: false,enableDiscovery: false,showNotifications: false,description: '',portal: '',profile: '',runAs: '',runAsUser: '',businessRule: '',domain: 'global'
5. Script Fields
- Use module imports for external script files (or
Now.include()for legacy scripts) - Keep scripts concise and focused
- Handle errors gracefully in scripts
- Return proper values from context processing scripts
- CDATA tags are handled automatically - don't add them manually
6. Schedule Configuration
- Use nested
scheduleobject for scheduled triggers - Set
triggerFlowDefinitionTypeto'scheduled','daily','weekly', or'monthly' runDayOfWeek: 1=Sunday, 2=Monday, ..., 7=SaturdayrunDayOfMonth: 1-31 for monthly schedules- Date/time format: YYYY-MM-DD HH:MM:SS (e.g.,
'1970-01-01 09:00:00') - Duration format for
repeatInterval: YYYY-MM-DD HH:MM:SS (e.g.,'1970-01-05 12:00:00'for 5 days) - Omit empty schedule fields — only specify fields with actual values
7. Record References
- All
String | Record<table>fields support both sys_id strings and Record references - Use Record references for better portability across instances
- Supported fields:
runAs,runAsUser,channel,profile,portal,businessRule businessRulealso accepts FluentBusinessRule()objects defined in the same project- Channel supports names: Use
'Now Assist Panel'directly (auto-mapped to sys_id)
Common Patterns
Pattern 1: Workflow with Triggers
AiAgenticWorkflow({
$id: Now.ID['triggered_workflow'],
name: 'Triggered Workflow',
description: 'Workflow with automatic triggers',
securityAcl: { $id: Now.ID['triggered_workflow_acl'], type: 'Any authenticated user' },
runAs: 'user_sys_id',
team: {
$id: Now.ID['triggered_team'],
members: ['agent_sys_id_1'],
},
triggerConfig: [
{
name: 'Record Trigger',
targetTable: 'incident',
triggerFlowDefinitionType: 'record_create',
triggerCondition: 'priority=1',
objectiveTemplate: 'Process incident ${number}',
channel: 'Now Assist Panel',
},
],
})
Pattern 2: Workflow with Scheduled Triggers
AiAgenticWorkflow({
name: 'Scheduled Review Workflow',
description: 'Workflow that runs on a schedule',
acl: '',
runAs: 'user_sys_id',
team: {
$id: Now.ID['scheduled_team'],
members: ['6816f79cc0a8016401c5a33be04be441'],
},
triggerConfig: [
{
name: 'Weekly Review',
targetTable: 'incident',
triggerFlowDefinitionType: 'scheduled',
objectiveTemplate: 'Review all incidents for the week',
channel: 'Now Assist Panel',
schedule: {
runDayOfWeek: 2, // Monday
time: '1970-01-01 09:00:00', // 9:00 AM
triggerStrategy: 'every',
},
},
{
name: 'Monthly Report',
targetTable: 'incident',
triggerFlowDefinitionType: 'scheduled',
objectiveTemplate: 'Generate monthly incident report',
channel: 'Now Assist Panel',
schedule: {
runDayOfMonth: 1, // First day of month
time: '1970-01-01 08:00:00', // 8:00 AM
repeatInterval: '1970-01-05 12:00:00',
},
},
],
})
Troubleshooting
Team Not Created
Problem: Team configuration provided but team record not generated.
Solution:
- Ensure
team.$idis provided (mandatory for teams) - Use
Now.ID['team_name']format for the ID - Check that
team.membersarray is provided (nested within team object)
Data Access Validation Error
Problem: Error: "dataAccess.roleList is mandatory when runAs is empty"
Solution:
- Either set
runAsto a user sys_id - Or provide
dataAccess.roleListwith at least one role
Trigger Not Firing
Problem: Trigger configured but workflow not invoked automatically.
Solution:
- Verify
triggerConfig.activeistrue - Check
triggerConditionmatches your records - Ensure
targetTableis correct - Verify
objectiveTemplateis set in trigger config - Validate
startingfield format: YYYY-MM-DD HH:MM:SS
Script Fields Not Working
Problem: Scripts showing as [object Object] or not executing.
Solution:
- Use string format for scripts:
`(function() { ... })()` - Or use module imports for external files (preferred), or
Now.include('./script-file.js')for legacy scripts - Ensure CDATA tags are NOT manually added (handled automatically)
- Check script parameter names match expected values
Workflow Not Using Coalesce
Problem: Workflow $id is optional but workflow not found.
Solution:
- Workflows use coalesce on
namefield - ensure unique names $idis optional for workflows (unlike teams which require it)- If you need explicit IDs, you can still provide
$id
Table Schema
sn_aia_usecase
| Column Name | Type | Mandatory | Default Value | Description |
|---|---|---|---|---|
| advanced_mode | True/False | FALSE | false | Whether advanced mode is enabled |
| applicability_script | Script | FALSE | javascript:new sn_aia.AgentExecutionUtil().getApplicabilityDefaultScript(); | Script that determines when workflow is applicable |
| base_plan | Translated Text | FALSE | Base plan instructions | |
| condition | Conditions | FALSE | Condition table reference | |
| context_processing_script | Script | FALSE | javascript:sn_aia.agents.USECASE_CONTEXT_PROCESSING_SCRIPT_TEMPLATE; | Script for processing context |
| description | Translated Text | TRUE | Description of the workflow | |
| execution_mode | Choice | FALSE | copilot | Execution mode (copilot/autopilot) |
| internal_name | String | FALSE | Internal name (domain.scope.name) | |
| name | Translated Text | TRUE | Display name of the workflow | |
| parent | Reference | FALSE | Reference to parent use case | |
| record_type | Choice | FALSE | custom | Record type (template/custom etc.) |
| source_id | Reference | FALSE | Reference to source workflow | |
| strategy | Reference | FALSE | Reference to workflow strategy | |
| sys_domain | Domain ID | FALSE | Domain identifier | |
| team | Reference | FALSE | Reference to team |
sn_aia_team
| Column Name | Type | Mandatory | Default Value | Description |
|---|---|---|---|---|
| description | Translated Text | FALSE | Description of the team | |
| name | Translated Text | FALSE | Name of the team | |
| sys_domain | Domain ID | FALSE | Domain identifier |
sn_aia_team_member
| Column Name | Type | Mandatory | Default Value | Description |
|---|---|---|---|---|
| agent | Reference | FALSE | Reference to the AI Agent | |
| memory_scope | Choice | FALSE | global | Memory scope for the agent |
| sys_domain | Domain ID | FALSE | Domain identifier | |
| team | Reference | FALSE | Reference to the team |
sn_aia_version
| Column Name | Type | Mandatory | Default Value | Description |
|---|---|---|---|---|
| condition | Condition String | FALSE | Condition for version activation | |
| instructions | Translated Text | FALSE | Version-specific instructions | |
| state | Choice | FALSE | draft | State of the version (draft/published etc.) |
| sys_domain | Domain ID | FALSE | global | Domain identifier |
| sys_overrides | Reference | FALSE | Reference to override version | |
| target_id | Document ID | TRUE | Reference to target record | |
| target_table | Table Name | TRUE | Name of the target table | |
| version_name | Translated Text | TRUE | Display name of the version | |
| version_number | Integer | FALSE | Version number |
sn_aia_usecase_config_override
| Column Name | Type | Mandatory | Default Value | Description |
|---|---|---|---|---|
| active | True/False | FALSE | Whether the configuration is active | |
| run_as_user | Reference | FALSE | User to run the workflow as | |
| sys_domain | Domain ID | FALSE | Domain identifier | |
| sys_overrides | Reference | FALSE | Reference to override configuration | |
| usecase_configuration | Reference | TRUE | Reference to the workflow |
sys_agent_access_role_configuration
| Column Name | Type | Mandatory | Default Value | Description |
|---|---|---|---|---|
| action | Choice | TRUE | limit_to_roles | Action to perform for access control |
| agent | Document ID | TRUE | Reference to the workflow | |
| agent_table | Table Name | TRUE | sn_aia_usecase | Table name of the workflow |
| description | String | FALSE | Description of the access configuration | |
| name | String | TRUE | Name of the access configuration | |
| role_list | List | FALSE | List of roles that have access | |
| sys_domain | Domain ID | FALSE | global | Domain identifier |
sn_aia_trigger_configuration
| Column Name | Type | Mandatory | Default Value | Description |
|---|---|---|---|---|
| active | True/False | FALSE | false | Whether the trigger is active |
| business_rule | Reference | FALSE | Reference to business rule | |
| channel | Reference | TRUE | Channel for the trigger | |
| condition | Conditions | TRUE | Condition for triggering | |
| description | String | FALSE | Description of the trigger | |
| enable_discovery | True/False | FALSE | false | Whether to enable discovery |
| internal_name | String | FALSE | Internal name of the trigger | |
| name | String | TRUE | Name of the trigger | |
| notification_script | Reference | FALSE | Reference to notification script | |
| objective_template | Email Script | TRUE | Template for objective message | |
| portal | Reference | FALSE | Reference to portal | |
| profile | Reference | FALSE | Reference to profile | |
| run_as | Field Name | FALSE | Field name for run-as user | |
| run_as_script | Script | FALSE | Script to determine run-as user | |
| run_as_user | Reference | FALSE | Reference to run-as user | |
| run_dayofmonth | Integer | FALSE | Day of month to run | |
| run_dayofweek | Day of Week | FALSE | Day of week to run (1=Sunday, 7=Saturday) | |
| run_period | Duration | FALSE | Run period/interval | |
| run_start | Basic DateTime | FALSE | Start date/time (YYYY-MM-DD HH:MM:SS) | |
| run_time | Basic Time | FALSE | Time to run | |
| show_notifications | True/False | FALSE | false | Whether to show notifications |
| sys_domain | Domain ID | FALSE | global | Domain identifier |
| sys_overrides | Reference | FALSE | Reference to override trigger | |
| target_table | Table Name | TRUE | Table to monitor for triggers | |
| trigger_flow | Reference | FALSE | Reference to flow | |
| trigger_flow_definition_type | Choice | FALSE | Type of flow definition | |
| trigger_strategy | Choice | FALSE | Strategy for triggering | |
| usecase | Reference | FALSE | Reference to use case | |
| usecase_discovery | True/False | FALSE | false | Whether to enable usecase discovery |
sn_aia_trigger_agent_usecase_m2m
| Column Name | Type | Mandatory | Default Value | Description |
|---|---|---|---|---|
| active | True/False | FALSE | true | Whether the mapping is active |
| objective_template | Email Script | FALSE | Template for objective message | |
| related_resource_record | Document ID | TRUE | Reference to the related record (workflow) | |
| related_resource_table | Table Name | TRUE | sn_aia_usecase | Name of the related table |
| sys_domain | Domain ID | FALSE | global | Domain identifier |
| sys_overrides | Reference | FALSE | Reference to override mapping | |
| trigger_configuration | Reference | TRUE | Reference to trigger configuration |