How to generalize this script to include all tags in a UDT instead of listing it one by one

def calc_avg():
	paths = ["[default]Machines/20902_L9_OD_GRINDER_1/Cycle_Time", "[default]Machines/20903_L9_OD_GRINDER_2/Cycle_Time", "[default]Machines/20904_L9_OD_GRINDER_3/Cycle_Time", "[default]Machines/20905_L9_OD_GRINDER_4/Cycle_Time"]
	value = [0] * len(paths)
	for x in range(len(paths)):
		endTime = system.date.now()
		startTime = system.date.addMinutes(endTime, -30)
		dataSet = system.tag.queryTagCalculations(paths=[paths[x]], startDate=startTime, endDate=endTime, calculations=["Average"])
		value[x] = dataSet.getValueAt(0, 1)
	outpaths =["[default]Machines/20902_L9_OD_GRINDER_1/CycleTimeAverage","[default]Machines/20903_L9_OD_GRINDER_2/CycleTimeAverage","[default]Machines/20904_L9_OD_GRINDER_3/CycleTimeAverage","[default]Machines/20905_L9_OD_GRINDER_4/CycleTimeAverage"]
	system.tag.writeBlocking(outpaths, value, 1000)

I’d like to know how to link the paths to a UDT property so that I don’t have to list individual path and value tags.

you can try something with this i guess
https://docs.inductiveautomation.com/display/DOC81/system.tag.browse

wildcard on the name *Machines/20903_L9_OD_GRINDER_* or something

There are a few things that can be improved here.

for x in range(len(paths)):

Whenever you find yourself using range(len(something)), there’s a better way.

for path in paths:

is the pythonic way of looping through an iterable (list, set, dict…)

	endTime = system.date.now()
	startTime = system.date.addMinutes(endTime, -30)

Why do this in a loop ? Do you need to recalculate the start and end time each and every time ?

		dataSet = system.tag.queryTagCalculations(paths=[paths[x]], startDate=startTime, endDate=endTime, calculations=["Average"])

system.tag.queryTagCalculations can take a list of paths, to avoid having to call it for each tag you need calculations on.

If we put all this together:

def calc_avg():
	paths = [...]
	outpaths = [...]
	end_time = system.date.now()
	start_time = system.date.addMinutes(end_time, -30)
	calculations = system.tag.queryTagCalculations(paths, startDate=start_time, endDate=end_time, calculations=["Average"])
	# I don't use datasets directly and I don't have ignition on this machine to test this, so it might need some adjusting.
	values = [calculations.getValueAt(0, col) for col in range(calculations.getColumnCount())][1:]
	system.tag.writeBlocking(outpaths, values, 1000)

Now, if you need to makes the paths dynamic, system.tag.browse can help you as @victordcq suggested, but I’m not sure you can get UDT properties with it, you’ll have to try.
If it doesn’t work, system.tag.getConfiguration might be what you need.