Features
This page highlights the main features of the AI Accelerator module. Each feature section provides:
- 
Everyone : An overview of the feature 
- 
Developers : How to activate the feature 
- 
Authors : A brief look at what the feature looks like inside Magnolia Check out our AI Image Editor. 
| Magnolia’s AI modules send any processed content to the external AI provider that you configure. Magnolia does not store or analyze this content. You are responsible for reviewing the provider’s terms of service, data-handling practices, and legal compliance, and for configuring the integration to meet your requirements. | 
Migration overview
The table below is an overview of the components that use the new Model and Task registry as of version 3.0.0-rc1.
| Feature | Now | Soon | Discontinued | 
|---|---|---|---|
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 | |||
| 
 DALL-E discontinued; included in the AI Image generation | |||
| 
 | 
AI prompts engineering (Hyper Prompt)
To achieve content that perfectly matches your brand’s values, while also being optimized for the right audience and for search engines, simple prompts won’t cut it.
Hyper Prompt offers a flexible engine to create tone perfect, SEO optimized and scalable content in a breeze.
The app stores customizable prompts that can be used in [AI powered component generation], [AI powered variant generation] and [AI powered stories generation]. It offers a convenient way to create a consistent corporate identity and tone of voice across all content that is generated via the AI accelerator.
The prompt picker field allows developers to integrate Hyper Prompts, created using Hyper Prompt app into their own dialogs and custom AI workflows.
From version 1.1.1, we support Retrieval-Augmented Generation (RAG) to improve the relevance and accuracy of AI-generated content.
RAG combines the power of prompt-based generation with information retrieved from external sources, ensuring that the generated content is not only coherent but also enriched with up-to-date and contextually relevant information from Magnolia content apps.
This feature is currently in the developer preview state. The feature will be further enhanced in the near future to make it more convenient to use as a prompt engineer.
References to Magnolia content apps can be enabled using a special syntax variable name: Note fro version 1.2.0 these special reference templates can be configured (see smartInjectTemplates Configuration)
${ref:<workspaceName>:<variable name>.<jcr property name>} (1)
${pagesRef:(<variable name>.<jcr property name>)} (2)
${ecommerceRef::<variable name>.<product property name>} (3)
${jsonRef:<variable name>.<rest property name>} (4)| 1 | JCR example: ${ref:personas:Person.jcrName} | 
| 2 | Page link example: ${pagesRef:Page.title} | 
| 3 | Product picker example: ${ecommerceRef:Product.sku} | 
| 4 | REST Datasource example: ${jsonRef:Posts.body} | 
 
To activate the prompt picker feature:
- 
Go to the <light-module-folder>/<light-module-name>/dialogs/pages/<dialog>.yamlfile in your project.
- 
Ensure that you have the following in the file: <light-module-folder>/<light-module-name>/dialogs/pages/<dialog>.yamlform: implementationClass: info.magnolia.ui.javascript.form.FormViewWithChangeListener (1) properties: #... promptPicker: (2) $type: aiPromptPicker label: Prompts #...1 Ensure you have the info.magnolia.ui.javascript.form.FormViewWithChangeListenerimplementation class.2 The prompt picker. 
The value is propagated in formFields in with the name <fieldName>.prompt (e.g promptPicker.prompt) and has the following format.
{
  "@id": "<prompt id>",
  "@name": "<prompt jcr name>",
  "@nodeType": "prompt",
  "@path": "<prompt prat>",
  "name": "<prompt name>",
  "promptTemplate": "${Title}\n${Article}", # The defined prompt template including variables in the form ${<variableName>}
  "variables": {  # Contains the resolved variables from the picker
    "Title": "test",
    "Article": "when iaa"
  }
}Authors can use the ready-made prompts to create new content pieces, as well as to fine-tune or improve existing content. Authors can also test and iterate on the prompts without the need of switching to other apps within Magnolia.
 
 
DALL-E integration
Available from version 1.0.7
The DALL-E integration makes DALL-E’s public API accessible and usable through Magnolia. The following functions are provided:
- 
Generating and storing images based on text (DALL-E 3) 
- 
Creating image variants (DALL-E 2) 
- 
Creating modified images (DALL-E 2) 
To activate the feature:
- 
Go to the <light-module-folder>/<light-module-name>/decorations/assets/apps/dam.yamlfile in your project.
- 
Ensure that you have the following in the file: <light-module-folder>/<light-module-name>/decorations/assets/apps/dam.yamlsubApps: jcrBrowser: actions: generateAsset: label: Generate Asset icon: icon-import $type: openDialogAction dialogId: ai-accelerator-ui:dall-e-create-image (1) populate: false availability: root: true writePermissionRequired: true rules: notDeleted: $type: jcrIsDeletedRule negate: true generateEdit: label: Generate Edit icon: icon-import $type: openDialogAction dialogId: ai-accelerator-ui:dall-e-edit-image (2) populate: false availability: root: true writePermissionRequired: true rules: notDeleted: $type: jcrIsDeletedRule negate: true generateVariation: label: Generate Variation icon: icon-import $type: openDialogAction dialogId: ai-accelerator-ui:dall-e-create-variation (3) populate: false availability: root: true writePermissionRequired: true rules: notDeleted: $type: jcrIsDeletedRule negate: true actionbar: sections: asset: groups: generate: items: - name: generateEdit - name: generateVariation folder: groups: generate: items: - name: generateAsset - name: generateEdit - name: generateVariation root: groups: generate: items: - name: generateAsset - name: generateEdit - name: generateVariation1 DALL-E create. 2 DALL-E edit. 3 DALL-E create variation. 
Once activated, you can go to the Generate asset subapp and enter the values you want in the prompt fields to generate amazing images.
 
AI-powered component generation
Generate page components in a flash with the AI Accelerator module.
To activate the feature:
- 
Go to the <light-module-folder>/<light-module-name>/decorations/pages-app/apps/pages-app.yamlfile in your project.
- 
Ensure that you have the following in the file: <light-module-folder>/<light-module-name>/decorations/pages-app/apps/pages-app.yamlsubApps: detail: actions: generateComponent: (1) label: Generate component $type: openDialogAction icon: icon-add-item dialogId: ai-accelerator-ui:generateComponent populate: false availability: rules: addible: class: info.magnolia.pages.app.detail.action.availability.IsAreaAddibleRuleDefinition generateComponentWithSelectedComponent: (2) label: Generate component $type: openDialogAction icon: icon-add-item dialogId: ai-accelerator-ui:generateComponentWithSelectedComponent populate: false actionbar: sections: areaActions: groups: addingActions: items: - name: generateComponent edit: items: - name: generateComponentWithSelectedComponent1 Generate components. 2 Generate components with selected component. 
Once activated, you can rapidly generate components by selecting a template and providing a topic in the dialog prompt.
 
AI-powered variant generation
Generate personalized content variants.
To activate the feature:
- 
Go to the <light-module-folder>/<light-module-name>/decorations/pages-app/apps/pages-app.yamlfile in your project.
- 
Ensure that you have the following in the file: <light-module-folder>/<light-module-name>/decorations/pages-app/apps/pages-app.yamlsubApps: detail: actions: generateVariant: (1) label: Generate component Variant $type: openDialogAction icon: icon-add-item dialogId: ai-accelerator-ui:generateVariant populate: false actionbar: sections: componentActions: groups: variant: items: - name: generateVariant (2)1 The generate variant action. 2 Ensure it is available to your action bar. 
Once activated, you can generate variants by clicking Generate component variation and selecting a segment.
 
AI-powered story generation
Generate compelling stories with the click of a button.
Story-Gen allows you to generate complete story outlines followed by a refining step in which the outlines are refined.
To activate the feature:
- 
Go to the <light-module-folder>/<light-module-name>/decorations/stories/apps/stories.yamlfile in your project.
- 
Ensure that you have the following in the file: <light-module-folder>/<light-module-name>/decorations/stories/apps/stories.yamlsubApps: browser: actions: generateBlogPost: (1) label: Generate Story icon: icon-import $type: openDialogAction dialogId: ai-accelerator-ui:generateStory populate: false availability: root: true writePermissionRequired: true nodeTypes: folder: mgnl:folder rules: notDeleted: ¬Deleted $type: jcrIsDeletedRule negate: true actionbar: (2) sections: story: groups: addActions: items: - name: generateBlogPost folder: groups: addActions: items: - name: generateBlogPost root: groups: addActions: items: - name: generateBlogPost1 Generate story action. 2 Ensure it’s available in your action bar. 
Once activated, you can provide a Story outline and then further refine your story using OpenAI straight from the dialog prompt.
 
AI-powered SEO metadata field
Automatically generates SEO and OG metadata, including page title, description, and keywords, based on the page content for search engine optimization and social media sharing.
| Supports multilingual sites. | 
- Activate the feature
- 
- 
Go to the <light-module-folder>/<light-module-name>/dialogs/pages/<dialog>.yamlfile in your project.
- 
Ensure that you have the following in the file: <light-module-folder>/<light-module-name>/dialogs/pages/<dialog>.yamlform: implementationClass: info.magnolia.ui.javascript.form.FormViewWithChangeListener (1) properties: #.... seoGenerator: (2) $type: aiSeoMetadataGenerator label: AI Seo Metadata parameters: titleField: title # value is the property name of the field in the dialog metaDescriptionField: metaDescription ogDescriptionField: ogDescription metaKeywordsField: metaKeywords # ogTitleField: ogTitle # ogDescriptionField: ogDescription metaDataFields: # note all fields here need to have a corresponding parameter title: Title metaDescription: Description # ogTitle: ogTitle # ogDescription: ogDescription metaKeywords: Meta keywords excludedProperties: # Name of a property that should not be taken into account for metadata creation noIndexPage: noIndexPage navigation: navigation hideHero: hideHero seoGenerator: seoGenerator footer: footer #...1 Ensure you’re using the info.magnolia.ui.javascript.form.FormViewWithChangeListenerimplementation class.2 The SEO generator. 
 
- 
- Define the depth of content scanned for metadata
- 
By default, the SEO generator scans only two levels of content beneath the page. This can result in incomplete metadata when key content is nested deeper, such as in layouts with multiple areas or rows. 
To include deeper content levels, decorate the pages-minimum.yaml file in your light module:
depth: 5  # set to the number of levels you need (1)| 1 | Set the depth according to the maximum nesting in your page layouts to ensure all SEO-relevant content is included. Default is 2. | 
Once activated, go to the Meta tab in your Pages app and click Generate SEO Metadata.
 
AI-powered page generation
Generate full pages based on your template sets.
| Only components and templates that are enabled using availableTemplatesandavailableComponentscan be used for generating pages. | 
To activate the feature:
- 
Go to the <light-module-folder>/<light-module-name>/decorations/pages-app/apps/pages-app.yamlfile in your project.
- 
Ensure that you have the following in the file: <light-module-folder>/<light-module-name>/decorations/pages-app/apps/pages-app.yamlsubApps: browser: actions: generatePage: label: Generate page $type: openDetailSubappAction icon: icon-add-item appName: pages-app subAppName: generatePage availability: root: true writePermissionRequired: true nodeTypes: page: mgnl:page rules: notDeleted: $type: jcrIsDeletedRule negate: true actionbar: sections: crud: groups: abTest: add-delete: items: - name: generatePage generatePage: (1) class: info.magnolia.ai.automations.ui.AiAssistedSubAppDescriptor label: Generate page fieldScript: /ai-accelerator-ui/webresources/page-generator/app.html parameters: assetsFolder: / minCharacterOfAIPrompt: 5 # optional: default 2 maxCharacterOfAIPrompt: 1000 # optional: default 5001 Generate the page. 
Once activated, go to Generate page and choose from the available templates.
 
AI-powered text fields
Available from version 1.0.5
You can generate text in a textField based on a self-defined translatable prompt which you can enrich with variable content from the dialog properties.
Generate text automatically in a text field based on a developer-defined prompt, which can include dynamic variables from the dialog’s properties.
AI-powered text fields are designed to create tailored content (e.g., descriptions) with minimal user input, streamlining content creation.
- 
Use case: Ideal for generating structured, context-specific text, like product descriptions or metadata, based on predefined rules. 
- 
Example: A field generating a 100-word description using variables from other form fields (e.g., tags). 
form:
  implementationClass: info.magnolia.ui.javascript.form.FormViewWithChangeListener
  properties:
    #....
    description:
      $type: aiTextField
      prompt: "My wonderful ${paramName} description of what the AI should generate." (1)
      words: 100 (2)
      rows: 6 (3)
      properties: (4)
        tags: tags
    #...| Callout | Parameter | Description | 
|---|---|---|
| 1 | 
 | required The  Variable substitutions are available.
In addition to self-definable variables via the property  | 
| 2 | 
 | optional, default is `50` Defines the maximum words returned. | 
| 3 | 
 | optional, default is `2` Defines the initial height of the textarea. | 
| 4 | 
 | optional Defines properties for variable substitution in the prompt. The key is used as name for the variable. The value defines the name of the field from the form definition e.g. of the dialog. | 
Authors can use AI-powered text fields by clicking the icon next to an AI-powered field and choosing the the options:
 
AI-assisted text fields
Available from version 1.1.1
Enhance existing or new text fields with AI-driven tools to assist users in editing or generating text interactively. Transform standard text fields into AI-enhanced ones, offering extensions like summarizing, expanding, or changing tone for flexible content refinement.
AI-powered forms feature allows developers to easily transform any existing text fields in a Magnolia dialog into AI enhanced text fields.
Use the AI-assisted text field in your forms or turn textField into an AI-powered textField.
- 
Use case: Best for user-driven content editing, where the AI suggests improvements or generates text based on user interaction. 
- 
Example: A title field where the user can summarize or expand text with a click, with a max length of 150 characters. 
There are two options to enable aiAssistedTextField in your forms.
- 
Single aiAssistedTextField<light-module-folder>/<light-module-name>/dialogs/<dialog>.yamlform: implementationClass: info.magnolia.ui.javascript.form.FormViewWithChangeListener properties: #.... title: $type: aiAssistedTextField label: Title placeholder: Insert title text here i18n: true #....
- 
textFieldtoaiAssistedTextField<light-module-folder>/<light-module-name>/dialogs/<dialog>.yamlform: implementationClass: info.magnolia.ai.automations.ui.AiAssistedFormView (1) properties: #.... title: $type: textField label: Title placeholder: Insert title text here i18n: true maxLength : 150 (2) description: $type: textField label: Description #....1 Using implementationClass: info.magnolia.ai.automations.ui.AiAssistedFormViewconverts all traditionaltextFieldfields toaiAssistedTextFieldfields.2 Optional, allows to limit the number of characters. Generated text will be truncated if the number of characters exceeds the limit. 
Authors can use AI-assisted text fields by clicking the icon next to an AI-assisted field and choosing the the options:
- 
Rewrite 
- 
Expand 
- 
Simplify 
- 
Change tone 
- 
Hyper prompts 
- 
Summarize 
 
Configure extension tools for AI-assisted text field
Available from version 2.1.0
By default, all enabled default extensions of the AI Accelerator module (see defaultExtensions) are available in the aiAssistedTextField.
If you choose to use different extensions, use the optional extensions property.
Only enabled extensions are displayed.
    #....
    title:
      $type: aiAssistedTextField (1)
      maxLength : 150 (2)
      extensions:
        SeoMetadataKeywordsBlockTool: (3)
          extension: SeoMetadataKeywordsBlockTool (4)
          config: (5)
            numKeywords: 7
    #....| 1 | Using extensionsrequires the type explicitly to be set toaiAssistedTextField. | 
| 2 | Optional, generated text will be truncated if the number of characters exceeds the limit. | 
| 3 | Just a key, the name does not matter | 
| 4 | Has to be a name of an enabled ai-accelerator extension | 
| 5 | Config depends on the used extension | 
The following configuration for the default tools are available for decoration.
| Config | Extension | Description | 
|---|---|---|
| 
 | 
 | Desired approximate number of words. Default is 50. | 
| 
 | 
 | Desired number of words. Default is 100. | 
| 
 | 
 | If  | 
| 
 | 
 | Prompt instructions. | 
| Some extensions make use of extension dialogs that must also be available. The list below shows the extensions and required dialogs. Required dialogs that are not present will result in an error. | 
| Extension | Dialog | 
|---|---|
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
SEO Metadata generation
Available from version 2.1.0
The following extensions are available for seo metadata generation:
- 
SeoMetadataDescriptionBlockTool
- 
SeoMetadataKeywordsBlockTool
- 
SeoMetadataTitleBlockTool
The extensions for generation of SEO metadata description and title approximate maxLength if defined on the aiAssistedTextField.
The following configurations are available for decoration:
| Config | Description | Availability | 
|---|---|---|
| 
 | Properties to exclude for metadata generation. We recommend you include metadata fields to prevent existing bias for the AI. | 
 | 
| 
 | Amount of words to be generated. For descriptions, this number is approximate. For titles, this is the maximum. | 
 | 
| 
 | Number of keywords to be generated. | 
 | 
Setting maxLength for SEO metadata
You can configure the maxLength parameter to set a maximum number of characters for the generated SEO metadata.
In this case, maxLength is used to verify that the generated text fits the requirement.
However, in rare cases, the generated text might exceed the specified character limit, in which case the text will be truncated.
| When both numWordsandmaxLengthare specified, the smaller value is used for word generation.
If the output exceeds the character limit, the number of words may be further reduced, and the generation process will be retried to fit within the constraints. | 
    metaDescription:
      $type: aiAssistedTextField
      extensions:
        SeoMetadataBlockTool:
          extension: SeoMetadataDescriptionBlockTool
          config:
            numWords: 35
      maxLength : 150 (1)| 1 | maxLengthfor theaiAssistedTextFieldis used in the same way asmaxLengthin the standardtextField. | 
AI image generation
Available from version 2.1.0
Generate images using configured AI models.
subApps:
  jcrBrowser:
    actions:
      generateAsset:
        label: Generate Asset
        icon: icon-import
        $type: aiOpenCreateImageAction
        populate: false
        availability:
          root: true
          writePermissionRequired: true
          rules:
            notDeleted:
              $type: jcrIsDeletedRule
              negate: true
    actionbar:
      sections:
        folder:
          groups:
            generate:
              items:
                - name: generateAsset
        root:
          groups:
            generate:
              items:
                - name: generateAsset 
AI-generated asset metadata
Available from version 2.2.6
Generate asset metadata with a configured AI model and task parameters. Configure a model as described in Model configuration. As with all tasks, the default model applies unless you override it for the generateAssetMetadata task by decoration.
To use the gemini-2-5-flash model:
- 
Configure the model gemini-2-5-flash.
- 
Decorate <light-module-folder>/<light-module-name>/decorations/ai-accelerator-image-io/aiTasks/generateAssetMetadata.yaml:generateAssetMetadata.yamlmodelId: gemini-2-5-flash
You can control which languages the task generates. By default, the task uses the Magnolia default language. To add or change languages, decorate the input as shown.
The example adds English (en), German (de), Simplified Chinese (zh-CN), and Swiss Standard German (de-CH).
input:
  locales:
    defaultValue:
      english: en
      german: de
      chinese: zh-CN
      swiss: de-CHTask parameters
Set defaults by decorating the input section of aiTasks/generateAssetMetadata.yaml. You can also pass parameters when invoking the action by:
* Setting the action definition’s params.taskParameters
* Setting the Groovy script’s taskParameters
| Parameter | Description | 
|---|---|
| 
 | Required Path to the DAM asset used to generate metadata. Use a Magnolia JCR DAM asset path. | 
| 
 | Required; default:  | 
| 
 | Required; default:  | 
| 
 | Optional; default: Magnolia default language
Languages to generate. Provide a map of label-to-locale code, for example  | 
| 
 | Optional; default:  | 
| 
 | Optional; default:  | 
| 
 | Optional; default:  | 
| 
 | Optional; default:  | 
Features
The generateAssetMetadata task provides:
* A configurable action using jcrCommandAction
* An observation listener that can auto-generate metadata when an asset changes
* A Groovy script to bulk-generate metadata for assets in DAM
Generate metadata by action
See Model configuration for model setup.
Ensure your module.yaml declares the dependency:
dependencies:
  dam-app-jcr:
    version: 4.0.0/*The decoration below: * Adds two actions to the DAM browser subApp to write caption or description for a single asset and overwrite existing content * Enables i18n for the caption and description fields so you can view generated values in multiple languages
<light-module-folder>/<light-module-name>/decorations/dam-assets-app/apps/dam.yamlsubApps:
  jcrBrowser:
    actions:
      generateImageCaption:
        label: Generate Image Caption
        icon: icon-import
        $type: jcrCommandAction
        command: execute-task
        catalog: ai-accelerator
        params:
          taskId: ai-accelerator-image-io:generateAssetMetadata
          taskParameters:
            fieldName: caption
            overwrite: true
            maxLength: 100
            locales:
              english: en
              german: de
        availability:
          writePermissionRequired: true
          nodeTypes:
            asset: mgnl:asset
          rules:
            notDeleted:
              $type: jcrIsDeletedRule
              negate: true
      generateImageDescription:
        label: Generate Image Description
        icon: icon-import
        $type: jcrCommandAction
        command: execute-task
        catalog: ai-accelerator
        params:
          taskId: ai-accelerator-image-io:generateAssetMetadata
          taskParameters:
            fieldName: description
            overwrite: true
            maxWords: 150
            locales:
              english: en
              german: de
        availability:
          writePermissionRequired: true
          nodeTypes:
            asset: mgnl:asset
          rules:
            notDeleted:
              $type: jcrIsDeletedRule
              negate: true
    # Add the defined actions to the action bar.
    actionbar:
      sections:
        asset:
          groups:
            generate:
              items:
                - name: generateImageDescription
                - name: generateImageCaption
  # Enable i18n for caption and description.
  jcrDetail:
    form:
      properties:
        caption:
          i18n: true
        description:
          i18n: trueThe animation shows running the action in the Assets app. The caption field is populated in English and German.
 
Generate metadata by observation
The module provides an observation listener that auto-generates metadata when an asset is added in the Assets app. The listener is disabled by default.
| As of version 2.2.8, the  | 
When enabled, the ai-accelerator-image-io:generateAssetMetadata task first uses values defined under its input properties. If none are set, it falls back to the defaultValue entries. You can view these in the Definitions app.
observationMetadataGeneration:
  enabled: false
  observationDelay: 1000
  fields:
    caption:
      enabled: false
      taskId: ai-accelerator-image-io:generateAssetMetadata
      taskParameters:
        fieldName: caption
        maxLength: 100
    description:
      enabled: true
      taskId: ai-accelerator-image-io:generateAssetMetadata
      taskParameters:
        fieldName: description
        maxWords: 150Set observationMetadataGeneration.enabled: true to enable the listener and use the defaults above. By default, caption is disabled and description is enabled. You can add fields entries for title and subject.
To configure observation, decorate <light-module-folder>/<light-module-name>/decorations/ai-accelerator-image-io/config.yaml.
observationMetadataGeneration:
  enabled: true
  observationDelay: 5000
  fields:
    caption:
      enabled: true
      taskParameters:
        maxLength: 100
        locales: &locales
          english: en
          german: de
          chinese: zh-CN
          swiss: de-CH
    description:
      enabled: true
      taskParameters:
        maxWords: 150
        locales: *locales| Property | Description | 
|---|---|
| 
 | Enable or disable the observation listener. Default:  | 
| 
 | Debounce delay in milliseconds before running the task after an event. Default:  | 
| 
 | Map of field configurations keyed by field name ( | 
| Property | Description | 
|---|---|
| 
 | Whether this field is generated by observation. Defaults:  | 
| 
 | Task to execute. Default:  | 
| 
 | Parameters forwarded to the task. See Task parameters. Common examples include:
-  | 
Generate metadata by Groovy script
The ai-accelerator-image-io module includes a Groovy script to generate description properties for all images in the DAM workspace.
Open the Groovy app at ${webapp-context-path}/.magnolia/admincentral#app:groovy:browser;/ai-accelerator/CreateDescriptionForAllAssets.
import info.magnolia.ai.task.AiTaskExecutor
import info.magnolia.objectfactory.Components
import com.google.common.collect.ImmutableMap
workspace = 'dam'
nodeType = "mgnl:asset"
folderType = "mgnl:folder"
folderPath = "/"              // Narrow the scope if needed.
excludedFolders = [ ]         // Add full folder paths to skip AI lookups.
// e.g. excludedFolders = ["/travel-demo/social-icons", "/svg-icons", "/destinations"]
def generateDescription(assetPath) {
    AiTaskExecutor taskExecutor = Components.getComponent(AiTaskExecutor.class)
    String prompt = "Create a great alt text for SEO purposes"
    Map<String, Object> taskParameters = ImmutableMap.<String, Object> builder()
            .put("prompt", prompt)
            .put("path", assetPath)
            .put("overwrite", false) // Set true to overwrite existing data.
            // .put("fieldName", "caption") // Default is "description"; allowed: "caption", "title", "subject"
            .build()
    Map<String, Object> taskContext = ImmutableMap.<String, Object> builder()
            .put("taskParameters", taskParameters)
            .build()
    try {
        Map<String, Object> execute = taskExecutor.execute("ai-accelerator-image-io:generateAssetMetadata", taskContext)
        Map<String, Object> response = ImmutableMap.<String, Object> builder().putAll(execute).put("prompt", prompt).build()
        if (response.get("error") == true) {
            println response.toString()
        } else {
            LinkedHashMap responseData = ((LinkedHashMap) response.get("data"))
            println "Retrieved Description properties for: " + assetPath
            println "\tEnglish: " + responseData.get("text_en").toString()
            println "\tGerman: " + responseData.get("text_de").toString()
        }
    } catch (Exception e) {
        println "Error generating description for: " + assetPath + " " + e.toString()
    }
}
def assessFolder(targetFolder) {
    targetNode = session.getNode(targetFolder)
    def currentPath = targetNode.getPath()
    println "Analyzing folder: " + currentPath
    // Skip excluded folders.
    if (excludedFolders.any { currentPath.startsWith(it) }) {
        println "Skipping excluded folder: " + currentPath
        return
    }
    targetNodeAssets = NodeUtil.asList(NodeUtil.getNodes(targetNode, nodeType))
    targetNodeFolders = NodeUtil.asList(NodeUtil.getNodes(targetNode, folderType))
    for (assetNode in targetNodeAssets) {
        generateDescription(assetNode.getPath())
    }
    for (folderNode in targetNodeFolders) {
        assessFolder(folderNode.getPath())
    }
}
ctx = MgnlContext.getInstance()
session = ctx.getJCRSession(workspace)
assessFolder(folderPath)