> This page is for Assistant Platform.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.moveworks.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.moveworks.com/_mcp/server.

# Optional Lab: Moveworks Bender

> **Info**
>
> ## Overview
>
> * **Learning Objectives:** Use Moveworks Bender to configure attribute mappings for users and tickets, and validate them in the DSL and Data Mapper Playground before applying them.
> * **Estimated Time:** 15 minutes
> * **Prerequisites:**
>   * [Lab #4](/ai-assistant/getting-started/labs/moveworks-setup/lab-4-user-identity-service-account) complete (its user identity configuration is the Bender mapping you test)

---

### Key Concepts

Bender is the transformation engine that sits between connected raw system data and the Moveworks UI. It is essential for formatting data correctly:

* **Bender Mapping:** The logic used to tell Moveworks how to display raw JSON values. For example, turning a technical "state" code into a human-readable word.
* **Display Value:** A ServiceNow-specific concept where `value` is a raw ID (e.g., a sys_id) and `display_value` is the actual text shown to the user.
* **Fallback Logic:** The use of the `OR` operator (e.g., `phone.display_value OR ""`) to provide a default value and prevent the Moveworks AI Assistant from breaking if a field is empty.
* **DSL & Data Mapper Playground:** A sandbox where you can paste raw JSON from the API Playground to test if your Bender mappings will work before applying them.

**Relevant Documentation:**

* [Moveworks Help: Bender Data Mapping](/api-reference/configuration-languages/moveworks-bender-language-reference)
* [Moveworks Help: DSL & Data Mapper Playground](/api-reference/configuration-languages/dsl-and-mapper-playground)
* [Moveworks Agent Marketplace: Agent Architect](https://marketplace.moveworks.com/chat/new)

---

## 🛠️ 1: Walkthrough

### 1.1: Generate a Moveworks API Key via Tool Studio

1. Open **HTTP Connectors** from the waffle menu.
   ![](/_fern-files/_img/0a48926b08848997abef6264d9d0eae76e036309fd8d82444bcc2365039880e4.webp)

2. Select the **Credentials** module
   ![](/_fern-files/_img/43a5c7edaa717c7821bf04404b0c7731c91aa36037b6490af7d03641c3aa3a9a.webp)

3. Click **Create**
   ![](/_fern-files/_img/0e361b297897a4c077d9ccf290b0b665ec4d546d52a07036b642b07272cf2a51.webp)

4. Give your credential a name, and generate it as an **API Key** and **Publish** it
   ![](/_fern-files/_img/62a32b60636f365f64364ea70a63b983fd9bb8af8a7d4ecf59acbc49d304093c.webp)

5. Select **Copy to Clipboard**, and store this API key on your machine.
   ![](/_fern-files/_img/536ec3dae0a6e3621ad7ec09d7f82a650f06a127eb910c3400fcb0db47750921.webp)

6. In a separate tab, navigate to the [Moveworks DSL and Data Mapper Playground](https://docs.moveworks.com/api-reference/configuration-languages/dsl-and-mapper-playground). Enter your API key in the `API Key` section.

> **Warning**
>
> **Switch the region to match your Moveworks instance** before entering your API key. The region selector is in the top-right corner of the page. Use the table below to find your region.

> **Note**
>
> **Which region should I use?** Your region is determined by your Moveworks login URL. Find `org_name` in your URL and match it to the table below:
>
> | Select in tool | Data Center                     | Your login URL contains                  |
> | -------------- | ------------------------------- | ---------------------------------------- |
> | `US`           | United States (default)         | `org_name.moveworks.com`                 |
> | `EU`           | EU                              | `org_name.am-eu-central.moveworks.com`   |
> | `CA`           | Canada                          | `org_name.am-ca-central.moveworks.com`   |
> | `AUS`          | Australia / Asia Pacific        | `org_name.am-ap-southeast.moveworks.com` |
> | `GovCloud`     | Government Secure Cloud         | `org_name.moveworksgov.com`              |
> | `US3`          | United States (lab environment) | `org_name.us3.moveworks.com`             |
>
> For example, if your instance URL is `acme.moveworks.com`, select **US**. If it is `acme.us3.moveworks.com`, select **US3**.

> **Note**
>
> **Note:** If you receive an error that states that an on-prem agent cannot connect, try opening the page in an incognito browser window and try again

![](/_fern-files/_img/1b783a0b0714c036b7c2a475c831c0fb2e609eab7b7061a3c5186be450131339.webp)

---

### 1.2: Get the Default Bender Mapping for Moveworks ServiceNow User Identity

1. In **Moveworks Setup,** navigate to **User Identity > Import Users > Edit**
   ![](/_fern-files/_img/bbbd44e2f83b4f13d532722a6848bb2c57c7516e60796d0e431a4d36185d460f.webp)

2. Switch to **Advanced Mode** to see the JSON configuration for ingesting users from ServiceNow.
   ![](/_fern-files/_img/efb4ae8415e093db13ce8d46e567cc8914f1d65d51e6024e5827c23510691081.webp)

3. Copy the JSON block that defines the ServiceNow user ingestion logic (also shown below).
   ![](/_fern-files/_img/c205e14a7a701ac6c4b024f8c41a5ccb88a245fa479a67670e1b81ba213b36b9.webp)

```json
{
  "internal_fields": {
    "manager_resolver": "$TRIM(IF sys_id THEN sys_id.display_value OR \"\" ELSE NULL)"
  },
  "phone_number": "$TRIM(IF phone THEN phone.display_value OR \"\" ELSE NULL)",
  "user_name": "$TRIM(IF user_name THEN user_name.display_value OR \"\" ELSE NULL)",
  "employee_id": "$TRIM(IF employee_number THEN employee_number.display_value OR \"\" ELSE NULL)",
  "department": "$TRIM(IF department THEN department.display_value OR \"\" ELSE NULL)",
  "full_name": "$TRIM(IF name THEN name.display_value OR \"\" ELSE NULL)",
  "user_id_info.user_email": "if $TRIM(IF email THEN email.display_value OR \"\" ELSE NULL) then [$TRIM($TRIM(IF email THEN email.display_value OR \"\" ELSE NULL))] else []",
  "city": "$TRIM(IF city THEN city.display_value OR \"\" ELSE NULL)",
  "country_code": "$TRIM(IF country THEN country.display_value OR \"\" ELSE NULL)",
  "email_addr": "$TRIM(IF email THEN email.display_value OR \"\" ELSE NULL)",
  "first_name": "$TRIM(IF first_name THEN first_name.display_value OR \"\" ELSE NULL)",
  "timezone": "$TRIM(IF time_zone THEN time_zone.display_value OR \"\" ELSE NULL)",
  "cost_center_name": "$TRIM(IF cost_center THEN cost_center.display_value OR \"\" ELSE NULL)",
  "role": "$TRIM(IF title THEN title.display_value OR \"\" ELSE NULL)",
  "manager_email": "(manager).value.$TRIM()",
  "user_id_info.user_itsm_id_info": [
    {
      "first_name": "$TRIM(IF first_name THEN first_name.display_value OR \"\" ELSE NULL)",
      "external_id": "$TRIM(IF sys_id THEN sys_id.display_value OR \"\" ELSE NULL)",
      "integration_id": "\"snow\"",
      "full_name": "$TRIM(IF name THEN name.display_value OR \"\" ELSE NULL)",
      "itsm_user_id": "$TRIM(IF user_name THEN user_name.display_value OR \"\" ELSE NULL)",
      "system": "\"SNOW\"",
      "last_name": "$TRIM(IF last_name THEN last_name.display_value OR \"\" ELSE NULL)"
    }
  ],
  "state": "$TRIM(IF state THEN state.display_value OR \"\" ELSE NULL)",
  "user_tags": {
    "FILTER()": {
      "items": [
        "\"BASIC_USER\"",
        {
          "CONDITIONAL()": {
            "condition": "$LOWERCASE(((vip.value OR \"\"))) == $LOWERCASE((\"TRUE\"))",
            "on_pass": "\"VIP\""
          }
        }
      ]
    }
  },
  "location": "$TRIM(IF location THEN location.display_value OR \"\" ELSE NULL)",
  "last_name": "$TRIM(IF last_name THEN last_name.display_value OR \"\" ELSE NULL)"
}
```

4. Paste it into the **Editor** section of the DSL and Data Mapper Playground
   ![](/_fern-files/_img/600925610b9563e0120279e4684a8c6621dff71dea8311b2b8fa6ef81c8d0b76.webp)

5. In API Playground, query the `sys_user` table and copy a single user record.

> **Note**
>
> Moveworks maps records one at a time, so testing against a single record previews exactly how ingested data will look.

![](/_fern-files/_img/beed98f3b78daa5de97edc3dc80639ef6c5ec8be83b9d06108060b99d4456e65.webp)

```json
        {
            "calendar_integration": {
                "display_value": "Outlook",
                "value": "1"
            },
            "country": {
                "display_value": null,
                "value": ""
            },
            "user_password": {
                "display_value": "********",
                "value": ""
            },
            "last_login_time": {
                "display_value": "2019-04-05 22:16:30",
                "value": "2019-04-05 22:16:30"
            },
            "source": {
                "display_value": "",
                "value": ""
            },
            "sys_updated_on": {
                "display_value": "2025-12-29 10:39:30",
                "value": "2025-12-29 10:39:30"
            },
            "building": {
                "display_value": "",
                "value": ""
            },
            "web_service_access_only": {
                "display_value": "false",
                "value": "false"
            },
            "notification": {
                "display_value": "Enable",
                "value": "2"
            },
            "enable_multifactor_authn": {
                "display_value": "false",
                "value": "false"
            },
            "sys_updated_by": {
                "display_value": "system",
                "value": "system"
            },
            "sys_created_on": {
                "display_value": "2019-04-05 21:09:12",
                "value": "2019-04-05 21:09:12"
            },
            "sys_domain": {
                "display_value": "global",
                "link": "https://[your-instance].service-now.com/api/now/table/sys_user_group/global",
                "value": "global"
            },
            "state": {
                "display_value": "",
                "value": ""
            },
            "fax": {
                "display_value": "",
                "value": ""
            },
            "identity_type": {
                "display_value": "-",
                "value": "unclassified"
            },
            "vip": {
                "display_value": "false",
                "value": "false"
            },
            "sys_created_by": {
                "display_value": "admin",
                "value": "admin"
            },
            "zip": {
                "display_value": "",
                "value": ""
            },
            "home_phone": {
                "display_value": "",
                "value": ""
            },
            "time_format": {
                "display_value": null,
                "value": ""
            },
            "last_login": {
                "display_value": "2019-04-05",
                "value": "2019-04-05"
            },
            "default_perspective": {
                "display_value": "",
                "value": ""
            },
            "active": {
                "display_value": "true",
                "value": "true"
            },
            "sys_domain_path": {
                "display_value": "/",
                "value": "/"
            },
            "transaction_log": {
                "display_value": "",
                "value": ""
            },
            "cost_center": {
                "display_value": "",
                "value": ""
            },
            "phone": {
                "display_value": "",
                "value": ""
            },
            "name": {
                "display_value": "survey user",
                "value": "survey user"
            },
            "employee_number": {
                "display_value": "",
                "value": ""
            },
            "password_needs_reset": {
                "display_value": "false",
                "value": "false"
            },
            "gender": {
                "display_value": null,
                "value": ""
            },
            "city": {
                "display_value": "",
                "value": ""
            },
            "hr_integration_source": {
                "display_value": "",
                "value": ""
            },
            "failed_attempts": {
                "display_value": "0",
                "value": "0"
            },
            "user_name": {
                "display_value": "survey.user",
                "value": "survey.user"
            },
            "roles": {
                "display_value": "",
                "value": ""
            },
            "manager_hp1": {
                "display_value": "/T1}C(",
                "value": "/T1}C("
            },
            "title": {
                "display_value": "",
                "value": ""
            },
            "sys_class_name": {
                "display_value": "User",
                "value": "sys_user"
            },
            "sys_id": {
                "display_value": "005d500b536073005e0addeeff7b12f4",
                "value": "005d500b536073005e0addeeff7b12f4"
            },
            "federated_id": {
                "display_value": "UU/OJDA/H2viaQb8VqlJIYSYKwmbkOCLoFDQkTPv7XM=",
                "value": "UU/OJDA/H2viaQb8VqlJIYSYKwmbkOCLoFDQkTPv7XM="
            },
            "internal_integration_user": {
                "display_value": "false",
                "value": "false"
            },
            "ldap_server": {
                "display_value": "",
                "value": ""
            },
            "mobile_phone": {
                "display_value": "",
                "value": ""
            },
            "street": {
                "display_value": "",
                "value": ""
            },
            "company": {
                "display_value": "",
                "value": ""
            },
            "department": {
                "display_value": "",
                "value": ""
            },
            "first_name": {
                "display_value": "survey",
                "value": "survey"
            },
            "email": {
                "display_value": "survey.user@email.com",
                "value": "survey.user@email.com"
            },
            "introduction": {
                "display_value": null,
                "value": ""
            },
            "preferred_language": {
                "display_value": null,
                "value": ""
            },
            "u_password_expiry_date": {
                "display_value": "",
                "value": ""
            },
            "manager": {
                "display_value": "",
                "value": ""
            },
            "locked_out": {
                "display_value": "false",
                "value": "false"
            },
            "sys_mod_count": {
                "display_value": "2",
                "value": "2"
            },
            "last_name": {
                "display_value": "user",
                "value": "user"
            },
            "photo": {
                "display_value": "",
                "value": ""
            },
            "avatar": {
                "display_value": "",
                "value": ""
            },
            "middle_name": {
                "display_value": "",
                "value": ""
            },
            "sys_tags": {
                "display_value": "",
                "value": ""
            },
            "time_zone": {
                "display_value": null,
                "value": ""
            },
            "schedule": {
                "display_value": "",
                "value": ""
            },
            "u_coe_specialization": {
                "display_value": "",
                "value": ""
            },
            "correlation_id": {
                "display_value": "",
                "value": ""
            },
            "date_format": {
                "display_value": null,
                "value": ""
            },
            "location": {
                "display_value": "",
                "value": ""
            }
        }
```

6. Copy this JSON into the Input Payload for the DSL and Mapper Playground
   ![](/_fern-files/_img/85d96596da304ea8279638ebb71dc4d2626ddf1b2299777d6e051762c32c56b1.webp)

7. Click **Process** to see the Bender mapping applied to the input payload.

> **Note**
>
> Use this loop during any build to **confirm fields populate exactly as intended**:
>
> * **Retrieve** a sample record from your external system.
> * **Configure** the Bender to map your required fields.
> * **Validate** the mapping results within the DSL and Data Mapper tool.

![](/_fern-files/_img/298eb2abf10fd1f448d363c84ed680bb7f4c7bbc2fa1e88c01dd95a1ef8793a5.webp)

---

### 1.3: Use the DSL Architect to Draft Bender Mappings

> **Note**
>
> The Moveworks Agent Architect is an AI tool connected to Moveworks documentation. Its DSL Architect drafts DSL and Bender logic.

1. Open the [Moveworks Agent Architect](https://marketplace.moveworks.com/chat) and select the DSL Architect.
   ![](/_fern-files/_img/112da2f527ae9365aee50481d21628edcc4b2b3925261fa29d9102b0ce1b53c5.webp)

2. Give the DSL Architect the input payload and your goal. Use this example prompt:

**`text`**

```plain text
Based on the following input payload, please generate a complete, valid Bender mapping in both JSON and YAML formats. I am using this for a class, so please include a brief HTML introduction explaining the concepts covered.
Specifically, I need the following 5 complex data transformation examples included in the mapping:
1. String Templating (user_summary): Use RENDER() to create a sentence combining calendar_integration.display_value and sys_updated_on.display_value.
2. Conditional Logic (security_risk_assessment): Use EVAL() with an IF/THEN/ELSE statement to return 'High Risk' if both enable_multifactor_authn.value and web_service_access_only.value are 'false', otherwise 'Standard'.
3. Risk Score (risk_score): Use the CONDITIONAL() operator to return 100 if enable_multifactor_authn.value is 'false', and 0 if it passes.
4. Time Parsing (last_login_epoch): Use EVAL() and $PARSE_TIME() to convert last_login_time.value into an epoch timestamp.
5. Data Fallbacks (location_info): Use COALESCE() to return the first available value among building.display_value, country.display_value, or a hardcoded string '"Unknown Location"'.
Please ensure the JSON is fully closed and valid. Here is the payload:
```

```json
{
  "building": { "display_value": "", "value": "" },
  "calendar_integration": { "display_value": "Outlook", "value": "1" },
  "country": { "display_value": null, "value": "" },
  "enable_multifactor_authn": { "display_value": "false", "value": "false" },
  "last_login_time": { "display_value": "2019-04-05 22:16:30", "value": "2019-04-05 22:16:30" },
  "sys_updated_on": { "display_value": "2025-12-29 10:39:30", "value": "2025-12-29 10:39:30" },
  "web_service_access_only": { "display_value": "false", "value": "false" }
}
```

3. The Architect returns a draft Bender mapping. Copy the Bender JSON.
   ![](/_fern-files/_img/33e64ad6c535b24b67b1538430370c71c80c5424fec4578ad6c338daa131ff23.webp)

4. Paste it into the **Editor** section and click **Process** to see how it changes the mapped user.
   ![](/_fern-files/_img/8ab6f920ef0225a9e6c72e7517ef21eca71b55e9bb5021827c3e97876617e38c.webp)

---

## ✅ 2: Verification & Next Steps

1. **Finalize:**
   * Confirm that the JSON mapping processes successfully without errors.
2. **Inspect:**
   * Analyze the functions and dot-walking logic used in the **Editor** section of the Data Mapping Playground. Review how these functions transform the input and why the resulting output appears the way it does.
3. **Experiment:**
   * Modify the **Input Payload** and **Editor** values to see how the output changes. Try incorporating different logic or nested fields to test the limits of the mapping.
4. **Reference:**
   * Consult the [Bender Guide on the Moveworks Help Site](https://docs.moveworks.com/api-reference/configuration-languages/moveworks-bender-language-reference) for a full list of available **Bender Functions** to expand your toolkit.
   * Use the [Moveworks DSL Architect](https://marketplace.moveworks.com/chat) for help with complex Bender configurations.

> **Success**
>
> **Next:** Return to the [Moveworks Setup labs](/ai-assistant/getting-started/labs/moveworks-setup) to continue with the core labs or pick another optional lab.

---

## 🪞 3: Reflecting on This Configuration

Through this lab, you've learned the following:

* How to use the DSL and Data Mapper Playground
* Where to pull existing configuration JSON values from to test how the configuration will be applied
  * API Playground (Resource)
  * User Identity or Ticketing Configuration (Bender Mapping)
* Where to find additional examples of the Moveworks Bender language & associated functions
* How to use the Moveworks Agent Architect to help write complex bender mappings

---

## 🧠 4: Knowledge Check

**1. Based on the ServiceNow JSON structure, why do we use `.display_value` in our Bender mappings instead of just the field name?**

* **Answer:** ServiceNow stores data in objects where `value` is often a raw ID (like a sys_id) or a code, while `display_value` contains the human-readable string.

**2. In the following Bender snippet from your lab, what is the purpose of the `OR ""`?**
`$TRIM(IF phone THEN phone.display_value OR "" ELSE NULL)`

* **Answer:** It provides a fallback to an empty string to prevent the mapping from failing or returning an error if the `display_value` property is missing.

**3. Which Moveworks tool should you use if you want to test how a specific user's raw ServiceNow data will look after being processed by your Bender configuration?**

* **Answer:** The **DSL and Data Mapper Playground**.

**4. True or False:** The `RENDER()` function is used for mathematical calculations like risk scores.

* **Answer:** **False.** `RENDER()` is used for string templating to create human-readable sentences. (Bonus: `CONDITIONAL()` or `EVAL()` would be used for scores).

---

## ⚙️ 5: Configuration Details

Use the table below to fill in the required fields accurately.

| **Field Name**                                                  | **Action / Value to Enter**                                                             |
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| **Moveworks API Key**                                           | Generated within Moveworks Setup → Waffle Menu (HTTP Connectors) → Credentials → Create |
| **API Key → Credential Name**                                   | `any_value`                                                                             |
| **API Key → Credential Type**                                   | API Key                                                                                 |
| **Data Mapper Playground → Input Payload**                      | Copy the full JSON record from the code block above (Step 1.2)                          |
| **Data Mapper Playground → Editor**                             | Copy the Bender mapping JSON from the code block above (Step 1.2)                       |
| [Agent Architect](https://marketplace.moveworks.com/chat) Query | See the example prompt in the code block in Step 1.3 above                              |