*** title: Configure Moveworks Approvals Engine excerpt: >- Detail regarding configuration information for Moveworks Native Approvals Engine deprecated: false hidden: false metadata: title: '' description: '' robots: index next: description: '' --------------- ## What is Approval Engine? Approvals Engine is a platform that orchestrates approvals, built into the Moveworks platform. These are workflows designed to automate the approval process for tasks and functions within a system. Approvals Engine provides a sequence of validations for different actions or requests, such as permissions to a resource or additions to a distribution list. These processes can be tailored according to specific roles, tasks, and predefined conditions. **Key Use Cases:** * [Agent Studio Actions](/agent-studio/agent-studio/actions/compound-actions/overview) * [Access Software](/service-management/provision-management/software-access/overview) * [Access Groups](/service-management/provision-management/group-access/overview) By employing conditions and rules, these approval workflows filter and sort requests to eliminate unnecessary steps and find the most efficient path to resolution. ## Overview Approval workflows control who needs to approve software access requests, group memberships, and other privileged actions before they're granted. Moveworks provides pre-built approval workflows for common scenarios, and allows you to create custom workflows for complex requirements. **The Goal:** Get the right approvals from the right people, automatically, without slowing down users or creating unnecessary bottlenecks. *** ## Quick Navigation * [How Approval Workflows Work](#how-approval-workflows-work) * [Choosing an Approval Workflow](#choosing-an-approval-workflow) * [Built-In Approval Workflows](#built-in-approval-workflows) * [Custom Approval Workflows](#custom-approval-workflows) * [Common Use Cases](#common-use-cases) *** ## How Approval Workflows Work ### The Approval Flow 1. **User requests access** (e.g., "I need Salesforce access") 2. **Moveworks evaluates** the approval workflow configured for that resource 3. **Approval requests sent** to the appropriate people based on the workflow 4. **Approvers receive notification** in their chat platform (Slack, Teams, etc.) 5. **Approvers approve or deny** with one click 6. **Access is granted** automatically if approved (or denied if rejected) ### Who Can Be an Approver? * **Manager** - The requester's direct manager * **App Admin** - Designated administrators for specific applications * **Group Owner** - Owners of distribution lists or security groups * **Specific Users** - Named individuals (e.g., Security team lead) * **Group Members** - Any member of a designated approval group * **Automatic** - No approval needed (auto-approve) or auto-deny *** ## Choosing an Approval Workflow ### Decision Guide Ask yourself these questions: **1. How sensitive is this resource?** * **Low risk** (e.g., Slack, Zoom Basic) → Auto-approve or Manager approval * **Medium risk** (e.g., Salesforce, internal tools) → Manager or App Admin * **High risk** (e.g., production systems, financial tools) → Sequential approvals (Manager + App Admin) **2. Who knows if this person should have access?** * **Their manager knows** → Manager approval * **IT/App owner knows** → App Admin approval * **Both should agree** → Sequential approval (Manager then App Admin) * **No one needs to decide** → Auto-approve **3. Are there special cases?** * **Different rules for contractors?** → Conditional approval based on employee type * **Different rules by department?** → Conditional approval based on department * **Different rules by role level?** → Role-based approval *** ## Built-In Approval Workflows These are pre-configured workflows ready to use immediately. ### 🟢 Self-Service | Workflow | Who Approves | When to Use | Example Use Case | | ----------------------------------------------- | --------------------------------------------- | ------------------------------------------------ | ------------------------------------- | | **AUTO\_APPROVE** | No one (automatic) | Low-risk software everyone should have access to | Slack, Zoom Basic, company wiki | | **AUTO\_APPROVE\_FULL\_TIME\_ELSE\_MANAGER** | Auto for employees, Manager for contractors | Standard tools but contractors need review | Microsoft Office, standard SaaS tools | | **AUTO\_APPROVE\_FULL\_TIME\_ELSE\_APP\_ADMIN** | Auto for employees, App Admin for contractors | IT-managed tools, contractors need special setup | VPN access, dev tools | **Example scenario:** > "Everyone should have Slack, so we use AUTO\_APPROVE. For VPN though, employees get it automatically but contractors need IT approval, so we use AUTO\_APPROVE\_FULL\_TIME\_ELSE\_APP\_ADMIN." *** ### 🟡 Standard Approval | Workflow | Who Approves | When to Use | Example Use Case | | -------------- | -------------------------- | ---------------------------------------------------------- | ----------------------------------- | | **MANAGER** | User's direct manager | Manager knows if user needs this for their job | Salesforce, Jira, specialized tools | | **APP\_ADMIN** | Application administrators | IT/app owner needs to provision or has technical knowledge | Admin panels, specialized software | **Example scenario:** > "For Salesforce, managers know who on their team needs it, so we use MANAGER approval. For our internal admin tool, IT needs to set up accounts, so we use APP\_ADMIN approval." *** ### 🔴 Multi-Level Approval | Workflow | Who Approves | When to Use | Example Use Case | | ----------------------------- | ------------------------------- | -------------------------------------------------- | ------------------------------------------ | | **APP\_ADMIN\_THEN\_MANAGER** | App Admin first, then Manager | Both IT and manager need to agree, IT checks first | Production access, elevated permissions | | **MANAGER\_THEN\_DL\_OWNER** | Manager first, then Group Owner | Adding to sensitive groups | Executive mailing lists, privileged groups | **Example scenario:** > "For production database access, IT (APP\_ADMIN) confirms the person is technically qualified, then their manager confirms they need it for their role." *** ### 🔵 Group-Specific Workflows (Trust Models) These workflows apply to distribution lists and group memberships. They use "trust models" that make approval decisions based on the group's configuration in your identity system (Okta, Azure AD, Google Workspace, etc.). #### Understanding Trust Models Trust models check the group's settings to determine if approval is needed: **Key Group Properties:** * **Access Type/Join Policy**: How users can join (Open, Owner Approval Required, Closed, etc.) * **Self-Managed**: Whether the group allows self-service membership * **Visibility**: Public vs Private groups * **Owner Settings**: Whether owner approval is required #### STANDARD\_TRUST\_MODEL **Who Approves:** Automatic if group allows self-service, else Group Owner **Conditions for Auto-Approval:** * Group is marked as "self-managed" OR * Group access type is "Open" or "Anyone can join" OR * Group explicitly allows members to add themselves **Otherwise:** Group Owner must approve **When to Use:** * Standard distribution lists * Team mailing lists * Department groups with normal security requirements **Example:** > "For team distribution lists, if the group is configured as 'open' in Azure AD, anyone can join automatically. If it requires owner approval, the group owner must approve." *** #### MOST\_RESTRICTIVE\_TRUST\_MODEL **Who Approves:** Group Owner unless very specific auto-approval conditions are met **Conditions for Auto-Approval (ALL must be true):** 1. Requester is already a member of a parent group OR 2. Group explicitly allows self-service membership AND 3. Group is public/visible AND 4. Group access type is "Open" or "Anyone can join" **Otherwise:** Group Owner must approve **When to Use:** * Executive distribution lists * Sensitive information groups * Compliance-required groups * Security team lists **Example:** > "For the Executive Team mailing list, the group owner must approve every request, even if someone's manager requests access for them. Only if the group is explicitly configured as 'open' and 'self-service' would it auto-approve." **Why "Most Restrictive":** * Requires Group Owner approval by default * Only auto-approves when multiple conditions align * Protects sensitive groups from accidental access * Ensures conscious approval decisions *** #### LEAST\_RESTRICTIVE\_TRUST\_MODEL **Who Approves:** Automatic for most groups, Group Owner only for explicitly restricted groups **Conditions for Auto-Approval:** * Group is NOT marked as "Closed" or "Private" AND * Group does NOT explicitly require owner approval for all joins **Otherwise:** Group Owner must approve **When to Use:** * All-company announcements * Public distribution lists * Open collaboration groups * Social/interest groups **Example:** > "For the 'All Company' mailing list, anyone can join automatically unless the group is specifically configured as closed or private." *** #### Trust Model Variants with Fallbacks Some trust models have "fallback" options that change the approval behavior when conditions aren't met: | Workflow | Approval Logic | Use Case | | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------- | | **STANDARD\_WITH\_FALLBACK\_TO\_MANAGER** | Standard trust check, but if Group Owner approval needed and owner is unavailable → Manager approves | Groups where manager can substitute for owner | | **MOST\_RESTRICTIVE\_WITH\_FALLBACK\_TO\_MANAGER** | Most restrictive check, but Manager can approve if Group Owner unavailable | Sensitive groups with manager backup | | **MANAGER\_THEN\_DL\_OWNER** | Manager approves first, then Group Owner (sequential) | Dual approval for sensitive groups | | **MANAGER\_THEN\_DL\_OWNER\_WITH\_FALLBACK\_TO\_AUTO\_APPROVE** | Manager then Group Owner, but auto-approve if both unavailable | Flexible group access with backup | *** #### Google Workspace Specific | Workflow | Who Approves | When to Use | | --------------------------- | ------------------------------------------------ | ----------------------- | | **GSUITE\_OPEN\_OR\_OWNER** | Auto if Google group is "Open", else Group Owner | Google Workspace groups | **Google-Specific Conditions:** * Checks Google Groups "Who can join" setting * "Anyone can join" → Auto-approve * "Invited users" or "Can request" → Group Owner approves *** #### Choosing the Right Trust Model **Use LEAST\_RESTRICTIVE when:** * Group should be easily accessible * Low-security concern * Broad collaboration needed * Example: [company-news@company.com](mailto:company-news@company.com) **Use STANDARD when:** * Normal security requirements * Want to respect group's self-service settings * Balance between access and control * Example: [engineering-team@company.com](mailto:engineering-team@company.com) **Use MOST\_RESTRICTIVE when:** * Sensitive information shared * Compliance requirements * Executive or leadership groups * Want explicit approval for every request * Example: [board-of-directors@company.com](mailto:board-of-directors@company.com), [security-incidents@company.com](mailto:security-incidents@company.com) **Example scenario:** > "For our all-company mailing list, anyone can join (LEAST\_RESTRICTIVE). For our executive team list, the group owner must approve everyone (MOST\_RESTRICTIVE). For department teams, we trust the group's configuration (STANDARD)." *** ### 📋 Complete Built-In Workflows Reference | Workflow Name | Approval Flow | Best For | | --------------------------------------------------------------- | --------------------------------------- | ------------------------------------------- | | **AUTO\_APPROVE** | Automatic approval | Low-risk, widely available software | | **MANAGER** | Direct manager approves | Standard business applications | | **APP\_ADMIN** | App administrators approve | IT-managed or specialized tools | | **APP\_ADMIN\_THEN\_MANAGER** | App admin → Manager (sequential) | High-risk software, dual approval needed | | **AUTO\_APPROVE\_FULL\_TIME\_ELSE\_MANAGER** | Auto for FTE, Manager for contractors | Standard tools with contractor restrictions | | **AUTO\_APPROVE\_FULL\_TIME\_ELSE\_APP\_ADMIN** | Auto for FTE, App Admin for contractors | IT tools with contractor restrictions | | **STANDARD\_TRUST\_MODEL** | Conditional auto-approve or Group Owner | Standard distribution lists | | **STANDARD\_WITH\_FALLBACK\_TO\_MANAGER** | Conditional auto-approve or Manager | Distribution lists, manager fallback | | **MOST\_RESTRICTIVE\_TRUST\_MODEL** | Strict conditions or Group Owner | Sensitive distribution lists | | **MOST\_RESTRICTIVE\_WITH\_FALLBACK\_TO\_MANAGER** | Strict conditions or Manager | Sensitive groups, manager fallback | | **MOST\_RESTRICTIVE\_WITH\_FALLBACK\_TO\_DL\_MANAGER** | Strict conditions → DL Manager | Sensitive groups, DL manager fallback | | **LEAST\_RESTRICTIVE\_TRUST\_MODEL** | Flexible auto-approve or Group Owner | Open/public distribution lists | | **MANAGER\_THEN\_DL\_OWNER** | Manager → Group Owner (sequential) | Sensitive groups, dual approval | | **MANAGER\_THEN\_DL\_OWNER\_WITH\_FALLBACK\_TO\_AUTO\_APPROVE** | Manager → Group Owner, or auto | Flexible group access | | **GSUITE\_OPEN\_OR\_OWNER** | Auto if open, else Group Owner | Google Workspace groups | | **ADD\_TO\_DL\_APPROVAL** | Most restrictive → Manager fallback | Adding users to distribution lists | | **REMOVE\_FROM\_DL\_APPROVAL** | Most restrictive → Manager fallback | Removing users from distribution lists | | **CREATE\_DL\_APPROVAL** | Automatic approval | Creating new distribution lists | | **GET\_DL\_MANAGER\_APPROVAL** | Distribution List Manager | DL management operations | *** ## Custom Approval Workflows When built-in workflows don't fit your needs, create custom workflows. ### When to Create Custom Workflows * **Complex approval chains** (e.g., Manager → VP → Security team) * **Conditional approvals** based on user attributes (department, seniority, location) * **Role-specific approvals** (different approvers for different software roles) * **Approval groups** (any 2 of 5 people can approve) * **Special business rules** (e.g., "sales VPs can approve any sales tool request") *** ### Custom Workflow Types #### 1. **Sequential Approval** (One After Another) Approvals happen in order. Second approver only notified after first approves. **When to use:** * Manager needs to approve before IT sets up the account * Multiple levels of approval needed (Manager → Director → VP) * Progressive escalation **Example: Manager then App Admin** ```json { "sequential_expression": { "expressions": [ { "manager_expression": {} }, { "app_admin_expression": {} } ] } } ``` **User Experience:** 1. Manager gets approval request 2. Manager approves 3. *Then* App Admin gets approval request 4. App Admin approves 5. Access is granted *** #### 2. **Parallel Approval** (Multiple People at Once) All approvers notified at the same time. Can require all to approve or just some. **When to use:** * Any one of several people can approve (1 of 3 required) * All approvers must agree (3 of 3 required) * Faster than sequential when order doesn't matter **Example: Any 1 of 3 VPs can approve** ```json { "parallel_expression": { "expressions": [ { "user_constant_expression": { "user": "vp1@company.com" } }, { "user_constant_expression": { "user": "vp2@company.com" } }, { "user_constant_expression": { "user": "vp3@company.com" } } ], "number_required": 1 } } ``` **User Experience:** 1. All 3 VPs get approval request simultaneously 2. First VP to approve completes the approval 3. Other VPs' requests are auto-dismissed 4. Access is granted *** #### 3. **Conditional Approval** (Based on User Attributes) Different approval paths based on who is requesting or what they're requesting. **When to use:** * Different rules for employees vs contractors * Different approvers by department * Different approvers by seniority level * Role-based approval flows **Example: Auto-approve for senior staff, Manager approval for others** ```json { "condition_expression": { "clauses": [ { "condition": { "rule_v2": "users_requested_for[0].custom_attributes.seniority_level IN [\"Director\", \"VP\", \"SVP\", \"EVP\"]" }, "expression": { "auto_approve_expression": {} } } ], "default_expression": { "manager_expression": {} } } } ``` **User Experience:** * Directors and above: Access auto-approved * Everyone else: Manager must approve *** #### 4. **Approval Group** (Any Member of a Group) Send approval to everyone in a specific group. Can require 1 or more to approve. **When to use:** * Approval from "Security Team" (any member can approve) * IT helpdesk approval (any available admin) * On-call rotation (whoever is available) * Distributed approval responsibility **How It Works:** 1. Define a group in your identity system (Okta, Azure AD, etc.) containing all potential approvers 2. Configure how many group members must approve (`number_required`) 3. All group members receive the approval request simultaneously 4. Once the required number approve, access is granted 5. Remaining approval requests are auto-dismissed **Key Parameters:** | Parameter | Description | Example Values | | ----------------- | -------------------------------------- | ---------------------------------------------------------------------------------- | | `external_id` | The group ID from your identity system | `00gq0p1j6jGsb0ZCO2p8` (Okta), `sg-12345678` (AWS), `group-id@domain.com` (Google) | | `integration_id` | Your identity system integration ID | `okta`, `azure_ad`, `google_workspace` | | `number_required` | How many members must approve | `1` (any one), `2` (any two), `3` (any three) | | `role` | Which group role can approve | `MEMBER` (any member), `OWNER` (only owners) | **Example: Any 2 members of IT Security team must approve** ```json { "parallel_group_expression": { "group": { "external_id": "00gq0p1j6jGsb0ZCO2p8", "integration_id": "okta" }, "number_required": 2, "role": "MEMBER" } } ``` **User Experience:** 1. User requests production database access 2. All 8 IT Security team members get approval request in Slack/Teams 3. First 2 team members to approve complete the requirement 4. Other 6 team members' requests are auto-dismissed 5. Access is granted automatically **Finding Your Group's external\_id:** Different systems use different formats: **Okta:** * Navigate to: Directory → Groups → \[Select Group] * Look for "Group ID" in the group details * Format: `00gABCDEF123456789` **Azure AD:** * Navigate to: Azure Active Directory → Groups → \[Select Group] * Look for "Object ID" * Format: `12345678-1234-1234-1234-123456789012` **Google Workspace:** * Navigate to: Admin Console → Groups → \[Select Group] * Look for "Group Email" * Format: `security-team@company.com` **Getting Your integration\_id:** * Contact Moveworks Support with your identity system name * They will provide the correct `integration_id` for your org * This is typically your connector name in Moveworks Setup **Note:** Approval groups are powerful for distributed approval responsibility but require proper group management in your identity system. *** #### 5. **Role-Based Conditional Approval** Different approvers based on which role/license level is selected. **When to use:** * Different approvers for Basic vs Pro vs Enterprise * Different approval for read-only vs admin access * Elevated permissions need higher approval **Example: Basic role auto-approved, Admin role needs VP approval** ```json { "condition_expression": { "clauses": [ { "condition": { "rule_v2": "approval_request.approvable_entity.app_entity.role_canonical_name_to_provision.$LOWERCASE() == \"basic_user\".$LOWERCASE()" }, "expression": { "manager_expression": {} } }, { "condition": { "rule_v2": "approval_request.approvable_entity.app_entity.role_canonical_name_to_provision.$LOWERCASE() == \"admin\".$LOWERCASE()" }, "expression": { "sequential_expression": { "expressions": [ { "manager_expression": {} }, { "user_constant_expression": { "user": "vp-it@company.com" } } ] } } } ], "default_expression": { "auto_deny_expression": {} } } } ``` **User Experience:** * User requests Basic role → Manager approves * User requests Admin role → Manager approves, then VP must approve * User requests any other role → Auto-denied *** ### Creating a Custom Workflow #### Step 1: Navigate to Native Approvals **Path:** Moveworks Setup → Access Management → Moveworks Native Approvals #### Step 2: Click "Create" Start a new custom approval workflow. #### Step 3: Name Your Workflow Use a descriptive name that explains what it does: ✅ Good names: * `Manager_Then_IT_Security_Team` * `Sales_VP_Approval_For_CRM_Tools` * `Director_Plus_Auto_Approve` ❌ Bad names: * `Custom_Approval_1` * `New_Flow` * `Test` #### Step 4: Build Your Workflow Expression Use the JSON format documented below. Start simple and test before adding complexity. #### Step 5: Save and Test Save your workflow, then assign it to a test application and try requesting access. #### Step 6: Assign to Software/Groups Navigate to the software or group configuration and select "Custom Approval Workflow" under Provisioning Method. *** ## Common Use Cases ### Use Case 1: Software with Free and Paid Tiers **Scenario:** Zoom has Basic (free) and Pro (paid) licenses. Basic auto-approved, Pro needs manager approval. **Solution:** Role-based conditional approval ```json { "condition_expression": { "clauses": [ { "condition": { "rule_v2": "approval_request.approvable_entity.app_entity.role_canonical_name_to_provision.$LOWERCASE() == \"zoom_basic\".$LOWERCASE()" }, "expression": { "auto_approve_expression": {} } }, { "condition": { "rule_v2": "approval_request.approvable_entity.app_entity.role_canonical_name_to_provision.$LOWERCASE() == \"zoom_pro\".$LOWERCASE()" }, "expression": { "manager_expression": {} } } ], "default_expression": { "manager_expression": {} } } } ``` *** ### Use Case 2: Contractor Restrictions **Scenario:** Employees get software automatically, contractors need manager approval for security review. **Solution:** Use built-in `AUTO_APPROVE_FULL_TIME_ELSE_MANAGER` **Or create custom based on employment type:** ```json { "condition_expression": { "clauses": [ { "condition": { "rule_v2": "users_requested_for[0].is_full_time_employee == true" }, "expression": { "auto_approve_expression": {} } } ], "default_expression": { "manager_expression": {} } } } ``` *** ### Use Case 3: Department-Specific Approvers **Scenario:** Sales tools approved by Sales VP, Engineering tools approved by CTO. **Solution:** Conditional approval by department ```json { "condition_expression": { "clauses": [ { "condition": { "rule_v2": "users_requested_for[0].department.$LOWERCASE() == \"sales\".$LOWERCASE()" }, "expression": { "user_constant_expression": { "user": "vp-sales@company.com" } } }, { "condition": { "rule_v2": "users_requested_for[0].department.$LOWERCASE() == \"engineering\".$LOWERCASE()" }, "expression": { "user_constant_expression": { "user": "cto@company.com" } } } ], "default_expression": { "manager_expression": {} } } } ``` *** ### Use Case 4: Tiered Approval Based on Seniority **Scenario:** Directors and above auto-approved, everyone else needs manager approval. **Solution:** Conditional approval by seniority ```json { "condition_expression": { "clauses": [ { "condition": { "rule_v2": "users_requested_for[0].custom_attributes.seniority_level IN [\"Director\", \"VP\", \"SVP\", \"C-Level\"]" }, "expression": { "auto_approve_expression": {} } } ], "default_expression": { "manager_expression": {} } } } ``` **Note:** Requires `seniority_level` as a custom user attribute. See [User Identity](/service-management/core-platform/user-identity/overview) for available attributes. *** ### Use Case 5: Approval from Any IT Admin **Scenario:** IT admin approval needed, but any IT admin can approve (not specific person). **Solution:** Approval group ```json { "parallel_group_expression": { "group": { "external_id": "00gIT8AdminGroup", "integration_id": "okta" }, "number_required": 1, "role": "MEMBER" } } ``` **Contact Moveworks Support** to get your `integration_id` for the identity system containing your approval group. *** ### Use Case 6: Requesting Access for Someone Else **Scenario:** Manager requests software for a team member - should auto-approve if manager is requesting for their direct report. **Solution:** Conditional approval checking relationship ```json { "condition_expression": { "clauses": [ { "condition": { "rule_v2": "users_requested_for[0].manager_email == requestor.email_addr" }, "expression": { "auto_approve_expression": {} } } ], "default_expression": { "manager_expression": {} } } } ``` *** ## Approval Expression Reference ### Basic Expressions #### Auto-Approve ```json { "auto_approve_expression": {} } ``` #### Auto-Deny ```json { "auto_deny_expression": {} } ``` #### Specific User ```json { "user_constant_expression": { "user": "approver@company.com" } } ``` #### Manager ```json { "manager_expression": {} } ``` #### App Admin ```json { "app_admin_expression": {} } ``` #### Reference Another Workflow ```json { "referenced_expression": { "name": "Name_Of_Other_Workflow" } } ``` *** ### Combining Expressions #### Sequential (one after another) ```json { "sequential_expression": { "expressions": [ { "manager_expression": {} }, { "app_admin_expression": {} } ] } } ``` #### Parallel (all at once, N required) ```json { "parallel_expression": { "expressions": [ { "user_constant_expression": { "user": "user1@company.com" } }, { "user_constant_expression": { "user": "user2@company.com" } } ], "number_required": 1 } } ``` #### Conditional (if/else logic) ```json { "condition_expression": { "clauses": [ { "condition": { "rule_v2": "CONDITION_HERE" }, "expression": { "auto_approve_expression": {} } } ], "default_expression": { "manager_expression": {} } } } ``` #### Approval Group ```json { "parallel_group_expression": { "group": { "external_id": "GROUP_ID_HERE", "integration_id": "INTEGRATION_ID_HERE" }, "number_required": 1, "role": "MEMBER" } } ``` *** ## Available User Attributes for Conditions Use these in `rule_v2` conditions: ### Standard User Attributes | Attribute | Example Value | Use Case | | ---------------------------------------------- | --------------------- | --------------------------- | | `requestor.email_addr` | `john@company.com` | Check who is requesting | | `users_requested_for[0].email_addr` | `jane@company.com` | Check who access is for | | `users_requested_for[0].department` | `Engineering` | Department-based rules | | `users_requested_for[0].role` | `Software Engineer` | Role-based rules | | `users_requested_for[0].manager_email` | `manager@company.com` | Manager relationship checks | | `users_requested_for[0].is_full_time_employee` | `true` | Employee type checks | | `users_requested_for[0].work_status` | `FULL_TIME` | Work status checks | | `users_requested_for[0].location` | `San Francisco` | Location-based rules | ### Custom Attributes | Attribute | Example | Use Case | | ---------------------------------------------------------- | ---------- | ------------------------- | | `users_requested_for[0].custom_attributes.seniority_level` | `Director` | Seniority-based approval | | `users_requested_for[0].custom_attributes.cost_center` | `8000` | Budget approval routing | | `users_requested_for[0].custom_attributes.clearance_level` | `Secret` | Security clearance checks | **See available attributes:** [User Identity Module](/service-management/core-platform/user-identity/overview) ### Request Attributes | Attribute | Example | Use Case | | -------------------------------------------------------------------------------- | ------------ | ------------------- | | `approval_request.approvable_entity.app_entity.role_canonical_name_to_provision` | `admin_role` | Role-based approval | | `approval_request.approvable_entity.app_entity.name` | `Salesforce` | App-specific rules | *** ## Condition Syntax Examples Conditions in `rule_v2` use the Moveworks DSL (Domain-Specific Language) for evaluating user attributes and request context. ### Basic Syntax Rules **Accessing Values:** * Use dot notation: `object.field` * Array access: `array[index]` * First item in array: `users_requested_for[0]` **Comparison Operators:** * Equal: `==` * Not equal: `!=` * Greater than: `>` * Less than: `<` * In list: `IN` **Functions:** * `$LOWERCASE()` - Convert to lowercase for case-insensitive comparison * `$UPPERCASE()` - Convert to uppercase *** ### String Comparison (Case-Insensitive) **Why use \$LOWERCASE():** * User data may have inconsistent casing ("Sales", "sales", "SALES") * Always use for reliable string matching ```json // Check if user is in Sales department users_requested_for[0].department.$LOWERCASE() == "sales".$LOWERCASE() // Check user's role users_requested_for[0].role.$LOWERCASE() == "software engineer".$LOWERCASE() // Check location users_requested_for[0].location.$LOWERCASE() == "san francisco".$LOWERCASE() ``` *** ### List Membership Check if a value is in a list of allowed values: ```json // Check if seniority level is senior users_requested_for[0].custom_attributes.seniority_level IN ["Director", "VP", "SVP", "C-Level"] // Check if department is technical users_requested_for[0].department IN ["Engineering", "IT", "DevOps", "Data Science"] // Check if work status qualifies users_requested_for[0].work_status IN ["FULL_TIME", "PART_TIME"] ``` **Note:** List values are case-sensitive unless you use `$LOWERCASE()`: ```json // Case-insensitive list check (NOT SUPPORTED directly) // Instead, normalize the value first: users_requested_for[0].department.$LOWERCASE() IN ["engineering", "it", "devops"] ``` *** ### Boolean Checks Check true/false values: ```json // Check if full-time employee users_requested_for[0].is_full_time_employee == true // Check if NOT a contractor users_requested_for[0].is_full_time_employee != false // Check if user is active users_requested_for[0].is_active == true ``` *** ### Email Comparisons ```json // Check specific email requestor.email_addr.$LOWERCASE() == "manager@company.com".$LOWERCASE() // Check email domain requestor.email_addr.$LOWERCASE().$CONTAINS("@company.com") // Check if requesting for self users_requested_for[0].email_addr == requestor.email_addr ``` *** ### Relationship Checks ```json // Manager requesting for their direct report users_requested_for[0].manager_email == requestor.email_addr // User requesting for themselves users_requested_for[0].email_addr == requestor.email_addr // Check if requestor is in user's reporting chain // (Requires custom attribute tracking reporting chain) requestor.email_addr IN users_requested_for[0].custom_attributes.reporting_chain ``` *** ### Role-Based Checks ```json // Check the role being requested approval_request.approvable_entity.app_entity.role_canonical_name_to_provision.$LOWERCASE() == "basic_user".$LOWERCASE() // Check if requesting admin access approval_request.approvable_entity.app_entity.role_canonical_name_to_provision.$LOWERCASE() == "admin".$LOWERCASE() // Check if requesting elevated permissions approval_request.approvable_entity.app_entity.role_canonical_name_to_provision IN ["admin", "super_admin", "owner"] ``` *** ### Combining Conditions with AND Use nested condition expressions for AND logic: ```json { "condition_expression": { "clauses": [ { "condition": { // First condition: Department is Engineering "rule_v2": "users_requested_for[0].department.$LOWERCASE() == \"engineering\".$LOWERCASE()" }, "expression": { // If engineering, check second condition "condition_expression": { "clauses": [ { "condition": { // Second condition: Seniority is senior+ "rule_v2": "users_requested_for[0].custom_attributes.seniority_level IN [\"Senior\", \"Staff\", \"Principal\"]" }, "expression": { "auto_approve_expression": {} } } ], "default_expression": { "manager_expression": {} } } } } ], "default_expression": { "manager_expression": {} } } } ``` **What this does:** * Senior+ Engineering: Auto-approve * Junior Engineering: Manager approval * All other departments: Manager approval *** ### Common Patterns #### Pattern 1: Tiered Access by Seniority ```json { "rule_v2": "users_requested_for[0].custom_attributes.seniority_level IN [\"VP\", \"SVP\", \"C-Level\"]" } // Auto-approve for executives, else require approval ``` #### Pattern 2: Contractor Restrictions ```json { "rule_v2": "users_requested_for[0].is_full_time_employee == true" } // Auto-approve for FTE, require approval for contractors ``` #### Pattern 3: Department-Specific Rules ```json { "rule_v2": "users_requested_for[0].department.$LOWERCASE() == \"sales\".$LOWERCASE()" } // Sales gets different approval flow ``` #### Pattern 4: Self-Service by Manager ```json { "rule_v2": "users_requested_for[0].manager_email == requestor.email_addr" } // Manager requesting for direct report auto-approves ``` #### Pattern 5: Role-Specific Approval ```json { "rule_v2": "approval_request.approvable_entity.app_entity.role_canonical_name_to_provision.$LOWERCASE() == \"basic\".$LOWERCASE()" } // Basic role gets manager approval, admin role gets dual approval ``` *** ### Debugging Conditions **If your condition isn't working:** 1. **Check attribute availability:** * Navigate to User Identity module * Verify the attribute exists and has data * Check exact spelling and casing 2. **Test with simple conditions first:** * Start with: `users_requested_for[0].email_addr == "test@company.com"` * Add complexity incrementally 3. **Use \$LOWERCASE() consistently:** * Always use for string comparisons * Apply to both sides: `field.$LOWERCASE() == "value".$LOWERCASE()` 4. **Check array indexing:** * `users_requested_for[0]` - First user (typical for individual requests) * If requesting for multiple people, may need different logic 5. **Verify custom attributes:** * Custom attributes require `custom_attributes.` prefix * Example: `users_requested_for[0].custom_attributes.seniority_level` 6. **Contact Support:** * Provide the condition you're trying to write * Share what behavior you expect vs what happens * Include user examples that should/shouldn't match *** ## Best Practices ### 1. Start with Built-In Workflows Before creating custom workflows, check if a built-in workflow meets your needs. Built-in workflows are: * Battle-tested and reliable * Easier to understand for other admins * Maintained by Moveworks ### 2. Keep It Simple Complex approval workflows can: * Slow down access provisioning * Confuse users * Be hard to troubleshoot **Ask yourself:** "What's the minimum approval needed to keep us secure and compliant?" ### 3. Test Thoroughly Before deploying to production: 1. Create a test application 2. Assign your custom workflow 3. Test with different user types (employee, contractor, different departments) 4. Verify notifications go to the right people 5. Check that auto-approves work as expected ### 4. Document Your Workflows In the workflow name or description, note: * What this workflow does * When to use it * Who the approvers are **Example:** `Sales_Manager_Then_VP` - "For expensive sales tools. Manager approves first, then Sales VP must also approve." ### 5. Use Descriptive Names Your future self (and other admins) will thank you. ✅ **Good:** * `Contractor_Manager_Approval` * `Engineering_Tools_CTO_Approval` * `Sensitive_Data_Dual_Approval` ❌ **Bad:** * `Custom1` * `New_Workflow_Test` * `ABC_Approval` ### 6. Monitor Approval Response Times If approvals are taking too long: * Consider auto-approval for low-risk items * Add parallel approval (1 of N) instead of sequential * Check if approval groups are too large ### 7. Regular Review Quarterly, review: * Which workflows are being used * Approval response times * Workflows that auto-deny frequently (may need adjustment) * Unused custom workflows (can be deleted) *** ## Troubleshooting ### Issue: Approvals Going to Wrong Person **Check:** 1. User's manager is correctly set in identity system 2. App Admin email addresses are configured in software settings 3. Custom workflow condition logic is correct 4. Integration ID is correct for approval groups *** ### Issue: Approvals Not Sending **Check:** 1. Workflow is assigned to the software/group 2. Approver has access to the chat platform (Slack/Teams) 3. Moveworks bot can message the approver 4. No typos in email addresses *** ### Issue: Auto-Approve Not Working **Check:** 1. Workflow is correctly configured as `auto_approve_expression` 2. Conditions are evaluating to true (check user attributes) 3. No conflicting approval requirements 4. Workflow is saved and assigned *** ### Issue: Sequential Approval Stuck **Check:** 1. First approver completed their approval 2. Second approver is reachable 3. Workflow JSON is correctly formatted 4. No errors in workflow evaluation (check logs) *** ## Getting Help **Need assistance with custom workflows?** Contact Moveworks Support with: * Description of your desired approval flow * User scenarios (who should approve in what situations) * Current workflow JSON (if you have one) * Specific error messages or unexpected behavior *** ## Related Documentation * [Moveworks DSL Reference](/service-management/core-platform/configuration-languages/dsl-reference/overview) * [Access Groups](/service-management/provision-management/group-access/overview)