Represent complex data with a custom resource

Limited Preview:Extending Google Workspace Studio with add-ons is in limited preview.Learn more

This guide explains how to define custom resources for Google Workspace Studio.

Custom resources are custom data structures that you can define to groupmultiple variables together. When a step's output has a static structure,represent it with a custom resource.For example, to create a CRM lead, your output requires multiple variables:

  • Email address
  • Street address
  • Name

To ensure the presence of all data required to create aCRM lead, output a custom resource containing an email address, street address,and name.

Output a custom resource as a reference

By outputting a custom resource as a reference, you can return the customresource by its ID instead of the full custom resource object. If a customresource is large or complex, passing only the ID improves performance byreducing the data transferred between steps.

To output a custom resource as a reference, edit the step's manifest file andcode.

Edit the manifest file

In the manifest file:

  1. Specify aworkflowResourceDefinitions and assign it anid, afields[]array, and aproviderFunction. TheworkflowResourceDefinitions is astructure that defines data types and contents of the custom resource.

  2. Within thefields[] array, you specify the individual fields that make upthe custom resource, in this example calledfield_1 andfield_2.

  3. TheproviderFunction's value must match the name of a function in thestep's code. TheproviderFunction retrieves actual custom resource contentwhen needed.

    JSON

    {"workflowResourceDefinitions":[{"id":"resource_id","name":"Custom Resource","fields":[{"selector":"field_1","name":"Field 1","dataType":{"basicType":"STRING"}},{"selector":"field_2","name":"Field 2","dataType":{"basicType":"STRING"}}],"providerFunction":"onMessageResourceFunction"}]}
  4. Inoutputs[], specify an output variable that returns a dynamic set ofoutput variables. The output variable has adataType with the propertyresourceType. The value ofcardinality must beSINGLE.

    JSON

    {"outputs":[{"id":"resource_data","description":"Resource Data","cardinality":"SINGLE","dataType":{"resourceType":{"workflowResourceDefinitionId":"resource_id"}}}],}

Here's a complete manifest file that defines a custom resource:

JSON

{"timeZone":"America/Los_Angeles","exceptionLogging":"STACKDRIVER","runtimeVersion":"V8","addOns":{"common":{"name":"Custom Resource (as reference)","logoUrl":"https://www.gstatic.com/images/icons/material/system/1x/pets_black_48dp.png","useLocaleFromApp":true},"flows":{"workflowElements":[{"id":"getResourceDataReference","state":"ACTIVE","name":"Custom Resource (as reference)","description":"Output a custom resource as a reference","workflowAction":{"outputs":[{"id":"resource_data","description":"Resource Data","cardinality":"SINGLE","dataType":{"resourceType":{"workflowResourceDefinitionId":"resource_id"}}}],"onConfigFunction":"onConfigResourceFunction","onExecuteFunction":"onExecuteResourceFunction"}}],"workflowResourceDefinitions":[{"id":"resource_id","name":"Custom Resource","fields":[{"selector":"field_1","name":"Field 1","dataType":{"basicType":"STRING"}},{"selector":"field_2","name":"Field 2","dataType":{"basicType":"STRING"}}],"providerFunction":"onMessageResourceFunction"}]}}}

Edit the code

In the application code:

  1. Implement theproviderFunction, calledonMessageResourceFunction() inthis example, which retrieves custom resource content when needed. It takesthe inpute which is the step'sevent object JSON payload, andfrom it sets the custom resource ID.

    Apps Script

    functiononMessageResourceFunction(e){console.log("Payload in onMessageResourceFunction: "+JSON.stringify(e));varresource_id=e.workflow.resourceRetrieval.resourceReference.resourceId;letfieldValue_1;letfieldValue_2;// Using a if-condition to mock a database call.if(resource_id=="sample_resource_reference_id"){fieldValue_1=AddOnsResponseService.newVariableData().addStringValue("value1");fieldValue_2=AddOnsResponseService.newVariableData().addStringValue("value2");}else{fieldValue_1=AddOnsResponseService.newVariableData().addStringValue("field_1 value not found");fieldValue_2=AddOnsResponseService.newVariableData().addStringValue("field_2 value not found");}letresourceData=AddOnsResponseService.newResourceData().addVariableData("field_1",fieldValue_1).addVariableData("field_2",fieldValue_2)letworkflowAction=AddOnsResponseService.newResourceRetrievedAction().setResourceData(resourceData)lethostAppAction=AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);returnAddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();}
  2. The provider function must return the value of the custom resource byretrieving it with an appropriate mechanism, like calling an API or readinga database.

  3. To retrieve and return a custom resource by its ID, return it asreturnOutputVariablesAction, as shown inonExecuteResourceFunction().

    Apps Script

    functiononExecuteResourceFunction(e){console.log("Payload in onExecuteResourceFunction: "+JSON.stringify(e));letoutputVariables=AddOnsResponseService.newVariableData().addResourceReference("sample_resource_reference_id");letworkflowAction=AddOnsResponseService.newReturnOutputVariablesAction().addVariableData("resource_data",outputVariables);lethostAppAction=AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);returnAddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();}

Here's a complete example:

Apps Script

functiononConfigResourceFunction(){letsection=CardService.newCardSection().addWidget(CardService.newTextParagraph().setText("This is the Custom Resource Demo card"));constcard=CardService.newCardBuilder().addSection(section).build();returncard;}functiononMessageResourceFunction(e){console.log("Payload in onMessageResourceFunction: "+JSON.stringify(e));varresource_id=e.workflow.resourceRetrieval.resourceReference.resourceId;letfieldValue_1;letfieldValue_2;// Using a if-condition to mock a database call.if(resource_id=="sample_resource_reference_id"){fieldValue_1=AddOnsResponseService.newVariableData().addStringValue("value1");fieldValue_2=AddOnsResponseService.newVariableData().addStringValue("value2");}else{fieldValue_1=AddOnsResponseService.newVariableData().addStringValue("field_1 value not found");fieldValue_2=AddOnsResponseService.newVariableData().addStringValue("field_2 value not found");}letresourceData=AddOnsResponseService.newResourceData().addVariableData("field_1",fieldValue_1).addVariableData("field_2",fieldValue_2)letworkflowAction=AddOnsResponseService.newResourceRetrievedAction().setResourceData(resourceData)lethostAppAction=AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);returnAddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();}functiononExecuteResourceFunction(e){console.log("Payload in onExecuteResourceFunction: "+JSON.stringify(e));letoutputVariables=AddOnsResponseService.newVariableData().addResourceReference("sample_resource_reference_id");letworkflowAction=AddOnsResponseService.newReturnOutputVariablesAction().addVariableData("resource_data",outputVariables);lethostAppAction=AddOnsResponseService.newHostAppAction().setWorkflowAction(workflowAction);returnAddOnsResponseService.newRenderActionBuilder().setHostAppAction(hostAppAction).build();}

Related topics

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-11 UTC.