Can you add random numbers of unique tags to UDTs?

Seems the answer is no.

I have application that's been running for some time with around 10,000 tags from a handful of different UDTs representing various devices. All was fine until there was a request to add a handful of custom points to a particular device. They also want the new tag names to be unique in each device.

I had thought worst case, I could just add the tags needed to an existing UDT. Unfortunately, while the UDT looks like a folder it doesn't behave like one in that way. The GUI even gives you the option to create a tag while right clicking on the UDT instance but the new tag is sloughed off to the root where the UDT is located and not inside of it.

Not sure that it would have worked out but you also do not have the option to simply change the names of tags in a UDT instance.

Currently I'm thinking I'll make numerous UDTs representing the different number of tags that can needed and then use them as a parent data type to get the tags into the original UDT. I'll still have to add a parameter and then modify a fair amount of scripting that can reference the parameter as the tag name instead of the UDTs fixed tag name.

Doing the application from scratch I guess another option would have been to use script to create folders for each device and then add the required tags? You would lose the ability to make a change to a singular device UDT and have it update all the instances but you'd be able to add any number of tags you needed with whatever tag names you wanted.

What is their aim with this? What do these new members correlate to in your system/interface? It defeats the purpose of having a UDT (standard structure across multiple instances) and prevents you from having anything re-usable touching these members( think dynamic path generation for templates or repeated views).

You might be able to get around it if you have another member that correlates the custom Ids to their common counterpart/usage, and use that to build the paths accordingly, but that's a lot of additional work for questionable gain.

If they absolutely must have this then the folder of tags option is your only route. I would firmly push back on this.

These new points represent a subset of devices and they want descriptive tag names based on their location. They will all be different and not something that can be cobbled together from the parent device description.

There will also be different number of additional points. So I'll have to make a few different UDTs and then figure out which one to use for each instance unless there's a good way to completely hide a tag that's been configured in a UDT. You can disable them but then they're still there in your tag structure and look like they have a problem. I've already done something similar for a device that had a different number of breakers from device to device but the names were not unique. So the script that Created each of the UDT instances just picked the correct child/parent UDT for the right number of breakers.

I may try and use this script to flatten the UDT and then add the new tags to it.

def flatten_udt_instance(udt_path):
	"""
	Flattens a UDT instance into a regular folder with the same tag structure.
	The new folder will be named automatically based on the UDT name with "_Flat" appended.
	"""
	import system.tag
	
	# Determine base path and instance name
	parent_path_parts = udt_path.split("/")
	instance_name = parent_path_parts[-1]
	parent_folder = "/".join(parent_path_parts[:-1])
	new_folder_path = parent_folder + "/" + instance_name + "_Flat"

	# Step 1: Browse child tags inside the UDT instance
	browse_results = system.tag.browse(udt_path).getResults()

	tag_configs = []
	for result in browse_results:
		child_tag_path = udt_path + "/" + result['name']
		# Get tag config (shallow = False to include all properties)
		configs = system.tag.getConfiguration(child_tag_path, True)
		if configs and len(configs) > 0:
			tag_config = configs[0]
			tag_configs.append(tag_config)

	# Step 2: Ensure the folder exists (create if needed)
	system.tag.configure(new_folder_path, [], "m")  # No-op creation for path

	# Step 3: Create the tags inside the new folder
	quality = system.tag.configure(new_folder_path, tag_configs, "m")

	# Step 4: Check for success/failure
	if hasattr(quality, "isGood") and not quality.isGood():
		print("Tag creation failed with quality: {}".format(quality))
	else:
		print("Successfully created {} tag(s) in: {}".format(len(tag_configs), new_folder_path))


# Example Usage
flatten_udt_instance("[default]UDT_Devices/MyDeviceInstance")