Replicate value stored in object into properties of new one I would like to duplicate, for example, a cylinder with its number of vertices stored in its properties, and tweak this value if needded.

To do this, I click on a gizmo, and a new cylinder is created, with the stored value of the previous cylinder. But when I want to change this value within the property panel, the value remains the same.

How can I change it?

Here is an example:

import bpy
from mathutils import Matrix

bpy.ops.mesh.primitive_cylinder_add(vertices = 12, enter_editmode=False, align='WORLD', location=(-2, 0, 0))
obj = bpy.context.object
obj["vertices"] = 12

class CylinderWidgetGroup(bpy.types.GizmoGroup):
    bl_idname = "OBJECT_GGT_cylinder_tweak"
    bl_label = "cylinder tweaker"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'WINDOW'
    bl_options = {'3D', 'PERSISTENT'}

    @classmethod
    def poll(cls, context):
        obj = context.object
        try:
            if "Cylinder" in obj.name:
                goodName = obj.name

            return (obj and obj.name == goodName)
        except:
            return(obj and False)


    def setup(self, context):

        obj = context.object
        mpr = self.gizmos.new("GIZMO_GT_arrow_3d")
        mpr.draw_style = 'BOX'

        self.gizmoWidget = mpr

    def refresh(self, context):
        obj = context.object
        mpr = self.gizmoWidget
        props = mpr.target_set_operator("object.cylinder_update")
        posMatrix = Matrix( ((1,0,0,obj.location.x),(0,1,0,obj.location.y),(0,0,1,obj.location.z),(0,0,0,1)) ) 
        mpr.matrix_basis = posMatrix

class CylinderUpdate(bpy.types.Operator):
    bl_idname = "object.cylinder_update" # has to be all lower case
    bl_label = "Cylinder Update"
    bl_options = {'REGISTER', 'UNDO'} 

    vertices : bpy.props.IntProperty(name="vertices", default=5, min=3, max=100)

    def execute(self, context):
        obj = context.object
        self.vertices = obj["vertices"]
        bpy.ops.mesh.primitive_cylinder_add(vertices = obj["vertices"], enter_editmode=False, align='WORLD', location=(0, 0, 0))
        obj = context.object
        obj["vertices"] = self.vertices
        return {'FINISHED'}

bpy.utils.register_class(CylinderWidgetGroup)
bpy.utils.register_class(CylinderUpdate)
Set verts in invoke method
Set the value when the operator is invoked (run once). Give the new cylinder the operators value for self.vertices.
Demonstration of that change

    def invoke(self, context, event):
        obj = context.object
        self.vertices = obj[&quot;vertices&quot;]
        return {'FINISHED'}
    
    def execute(self, context):        
        bpy.ops.mesh.primitive_cylinder_add(
            vertices=self.vertices, 
            align='WORLD', location=(0, 0, 0))
        obj = context.object
        obj[&quot;vertices&quot;] = self.vertices
        return {'FINISHED'}

Some notes.
To match new cylinder transform to old would
mw = context.object.matrix_world.copy()

before new cylinder op, and assign it to new cylinder.
The poll method could be
def poll(cls, context):
    ob = context.object
    return ob and ob.name.startswith(&quot;Cylinder&quot;)

The poll method gets fired off a lot. Good practice not to use a try clause here.
The gizmo matrix basis could be
Matrix.Translation(ob.location)

However this is using local coords to make a global matrix and will result in &quot;losing touch&quot; with the cylinder if parenting or constraints are used to locate it.  Worth investigating using
Matrix.Translation(ob.matrix_world.to_translation())

Automatically set the custom property when cylinder added
Check out the way this answer https://blender.stackexchange.com/a/163258/15543 manipulates the newly created mesh primitive.  Recommend doing something similar here.
When the active operator is the add prim cylinder add the custom property.  In this case could poll for &quot;vertices&quot; in ob.keys()  (Maybe change name to cylinder_vertices)