Repository: kurtosis-tech/kurtosis
Pull request #322 (2023-03-24 11:38:57)

fix: Fix starlark value reference bug
## Description:
Running:
```
def run(plan):
	my_dict = {}
	plan.print(my_dict)
	my_dict["hello"] = "world"
```

right now returns:
```
> print msg={"hello": "world"}
{"hello": "world"}
```

This is because of the 3 steps execution, combined with the fact that "complex" starlark.Value object are passed as pointers to our instructions. This PR fixes it by copying the arg value into each instruction at the interpretation phase.

## Is this change user facing?
NO
<!-- If yes, please add the "user facing" label to the PR -->
<!-- If yes, don't forget to include docs changes where relevant -->

## References (if applicable):
<!-- Add relevant Github Issues, Discord threads, or other helpful information. -->


cloudflare-pages[bot]: ## Deploying with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>dbfad24</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>🚫&nbsp; Build failed.</td></tr>
</table>

[View logs](https://dash.cloudflare.com/?to=/:account/pages/view/kurtosis-docs/8a4b2a14-0011-40ea-8610-70fadefa4f22)


Patch:
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_value_copier.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_value_copier.go
new file mode 100644
index 000000000..e35139217
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_value_copier.go
@@ -0,0 +1,110 @@
+package builtin_argument
+
+import (
+	"fmt"
+	"github.com/sirupsen/logrus"
+	starlarktime "go.starlark.net/lib/time"
+	"go.starlark.net/starlark"
+	"go.starlark.net/starlarkstruct"
+	"reflect"
+)
+
+func DeepCopyArgumentValue[StarlarkValueType starlark.Value](genericArgValue StarlarkValueType) (StarlarkValueType, error) {
+	var copiedValue StarlarkValueType
+	genericCopiedValue, err := deepCopyArgumentValueInternal(genericArgValue)
+	if err != nil {
+		return copiedValue, err
+	}
+	copiedValue, ok := genericCopiedValue.(StarlarkValueType)
+	if !ok {
+		return copiedValue, fmt.Errorf("Error copying argument value '%s'. Unexpected type returned (original type: '%s', returned type: '%s')", genericArgValue, reflect.TypeOf(genericArgValue), reflect.TypeOf(genericCopiedValue))
+	}
+	return copiedValue, nil
+}
+
+func deepCopyArgumentValueInternal(genericArgValue starlark.Value) (starlark.Value, error) {
+	var valueCopy starlark.Value
+	var err error
+	switch argValue := genericArgValue.(type) {
+	case starlark.Bytes,
+		starlark.Bool,
+		starlark.Float,
+		starlark.Int,
+		starlark.NoneType,
+		starlark.String,
+		starlarktime.Time,
+		starlarktime.Duration:
+		valueCopy = argValue
+	case *starlark.List:
+		copiedList := make([]starlark.Value, argValue.Len())
+		for idx := 0; idx < argValue.Len(); idx++ {
+			copiedItem, err := deepCopyArgumentValueInternal(argValue.Index(idx))
+			if err != nil {
+				return nil, fmt.Errorf("Cannot copy starlark.List object: '%s'. Item at index '%d' failed to be copied. Error was: %s", argValue.String(), idx, err.Error())
+			}
+			copiedList[idx] = copiedItem
+		}
+		valueCopy = starlark.NewList(copiedList)
+	case *starlark.Set:
+		copiedSet := starlark.NewSet(argValue.Len())
+		iterator := argValue.Iterate()
+		defer iterator.Done()
+		var item starlark.Value
+		for idx := 0; iterator.Next(&item); idx++ {
+			copiedItem, err := deepCopyArgumentValueInternal(item)
+			if err != nil {
+				return nil, fmt.Errorf("Cannot copy starlark.Set object: '%s'. Item '%s' failed to be copied. Error was: %s", argValue.String(), item, err.Error())
+			}
+			if err = copiedSet.Insert(copiedItem); err != nil {
+				return nil, fmt.Errorf("Cannot copy starlark.Set object: '%s'. Item '%s' could not be persisted to the copy. Error was: %s", argValue.String(), item, err.Error())
+			}
+		}
+		valueCopy = copiedSet
+	case starlark.Tuple:
+		copiedTuple := make([]starlark.Value, argValue.Len())
+		iterator := argValue.Iterate()
+		defer iterator.Done()
+		var item starlark.Value
+		for idx := 0; iterator.Next(&item); idx++ {
+			copiedItem, err := deepCopyArgumentValueInternal(item)
+			if err != nil {
+				return nil, fmt.Errorf("Cannot copy starlark.Tuple object: '%s'. Item '%s' failed to be copied. Error was: %s", argValue.String(), item, err.Error())
+			}
+			copiedTuple[idx] = copiedItem
+		}
+		valueCopy = starlark.Tuple(copiedTuple)
+	case *starlark.Dict:
+		allKeys := argValue.Keys()
+		dictCopy := starlark.NewDict(argValue.Len())
+		for _, key := range allKeys {
+			value, found, err := argValue.Get(key)
+			if err != nil || !found {
+				return nil, fmt.Errorf("Iterating over all keys from the dictionary: '%s', the key '%s' could not be found. Error was: '%s'", argValue, key, err.Error())
+			}
+			copiedKey, err := deepCopyArgumentValueInternal(key)
+			if err != nil {
+				return nil, fmt.Errorf("Iterating over all keys from the dictionary: '%s', the key '%s' could not be copied. Error was: '%s'", argValue, key, err.Error())
+			}
+			copiedValue, err := deepCopyArgumentValueInternal(value)
+			if err != nil {
+				return nil, fmt.Errorf("Iterating over all keys from the dictionary: '%s', the value '%s' associated with key '%s' could not be copied. Error was: '%s'", argValue, value, key, err.Error())
+			}
+			err = dictCopy.SetKey(copiedKey, copiedValue)
+			if err != nil {
+				return nil, fmt.Errorf("Iterating over all keys from the dictionary: '%s', the value '%s' associated with key '%s' could not be persisted to the copied object. Error was: '%s'", argValue, value, key, err.Error())
+			}
+		}
+		valueCopy = dictCopy
+	case *starlarkstruct.Struct:
+		copiedStructDict := starlark.StringDict{}
+		argValue.ToStringDict(copiedStructDict)
+		valueCopy = starlarkstruct.FromStringDict(argValue.Constructor(), copiedStructDict)
+	case KurtosisValueType:
+		valueCopy, err = argValue.Copy()
+	default:
+		logrus.Warnf("Cannot copy value of argument '%s' as the type is not handled, returning the original "+
+			"object but it might provoke unexpected behaviour downstream", argValue.String())
+		valueCopy = argValue
+	}
+	return valueCopy, err
+}
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_values_set.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_values_set.go
index 6d9198565..bd3e0125b 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_values_set.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_values_set.go
@@ -89,7 +89,14 @@ func (arguments *ArgumentValuesSet) ExtractArgumentValue(argumentName string, ar
 	if !reflect.TypeOf(arguments.values[argumentIdx]).AssignableTo(paramVar.Type()) {
 		return fmt.Errorf("Unable to extract value for argument '%s'. Types were not assignable (got '%s', expecting '%s')", argumentName, paramVar.Type(), reflect.TypeOf(arguments.values[argumentIdx]))
 	}
-	paramVar.Set(reflect.ValueOf(arguments.values[argumentIdx]))
+
+	// Deep copy the value to avoid having the value modified downstream in the script execution
+	copiedVal, err := DeepCopyArgumentValue(arguments.values[argumentIdx])
+	if err != nil {
+		return fmt.Errorf("Argument '%s' could not be copied to a separate value", argumentName)
+	}
+
+	paramVar.Set(reflect.ValueOf(copiedVal))
 	return nil
 }
 
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/kurtosis_value_type.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/kurtosis_value_type.go
new file mode 100644
index 000000000..0f203291e
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/kurtosis_value_type.go
@@ -0,0 +1,11 @@
+package builtin_argument
+
+import (
+	"go.starlark.net/starlark"
+)
+
+type KurtosisValueType interface {
+	starlark.HasAttrs
+
+	Copy() (KurtosisValueType, error)
+}
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_type_constructor.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_type_constructor.go
index 577f59c8f..fdddb1a02 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_type_constructor.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_type_constructor.go
@@ -7,7 +7,7 @@ import (
 	"go.starlark.net/starlark"
 )
 
-type Instantiate func(arguments *builtin_argument.ArgumentValuesSet) (KurtosisValueType, *startosis_errors.InterpretationError)
+type Instantiate func(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError)
 
 // KurtosisTypeConstructor is the type for creating builtin used to instantiate a Kurtosis type
 type KurtosisTypeConstructor struct {
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_value_type.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_value_type.go
deleted file mode 100644
index 0dabdf6fd..000000000
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_value_type.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package kurtosis_type_constructor
-
-import "go.starlark.net/starlark"
-
-type KurtosisValueType interface {
-	starlark.HasAttrs
-}
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_value_type_default.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_value_type_default.go
index 92bbf4bf0..92a08193c 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_value_type_default.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor/kurtosis_value_type_default.go
@@ -12,7 +12,7 @@ import (
 // KurtosisValueTypeDefault is a helper type to easily build a type that implements the KurtosisValueType interface
 // straight from a builtin_argument.ArgumentValuesSet, without having to manually implement all the functions
 type KurtosisValueTypeDefault struct {
-	KurtosisValueType
+	*starlarkstruct.Struct
 
 	typeName  string
 	arguments *builtin_argument.ArgumentValuesSet
@@ -24,15 +24,15 @@ func CreateKurtosisStarlarkTypeDefault(name string, arguments *builtin_argument.
 		return nil, interpretationErr
 	}
 	return &KurtosisValueTypeDefault{
-		KurtosisValueType: underlyingStruct,
-		typeName:          name,
-		arguments:         arguments,
+		Struct:    underlyingStruct,
+		typeName:  name,
+		arguments: arguments,
 	}, nil
 }
 
 func ExtractAttrValue[AttrValueType starlark.Value](value *KurtosisValueTypeDefault, attrName string) (AttrValueType, bool, *startosis_errors.InterpretationError) {
 	var result AttrValueType
-	attrValue, err := value.KurtosisValueType.Attr(attrName)
+	attrValue, err := value.Struct.Attr(attrName)
 	if err != nil {
 		// starlarkstruct.Struct.Attr() throws an error only when the attribute does not exist. Therefore, we know here
 		// this is not a real error, it's just that the attribute name could not be found.
@@ -49,6 +49,29 @@ func ExtractAttrValue[AttrValueType starlark.Value](value *KurtosisValueTypeDefa
 	return result, true, nil
 }
 
+func (value *KurtosisValueTypeDefault) Copy() (*KurtosisValueTypeDefault, error) {
+	copiedStructDict := starlark.StringDict{}
+	value.Struct.ToStringDict(copiedStructDict)
+	copiedStruct := starlarkstruct.FromStringDict(value.Struct.Constructor(), copiedStructDict)
+
+	argumentValues := make([]starlark.Value, len(value.arguments.GetDefinition()))
+	for idx, argumentDefinition := range value.arguments.GetDefinition() {
+		if value.arguments.IsSet(argumentDefinition.Name) {
+			argumentValue := argumentDefinition.ZeroValueProvider()
+			err := value.arguments.ExtractArgumentValue(argumentDefinition.Name, &argumentValue)
+			if err != nil {
+				return nil, err
+			}
+			argumentValues[idx] = argumentValue
+		}
+	}
+	return &KurtosisValueTypeDefault{
+		Struct:    copiedStruct,
+		typeName:  value.typeName,
+		arguments: value.arguments,
+	}, nil
+}
+
 func (value *KurtosisValueTypeDefault) Type() string {
 	return value.typeName
 }
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/connection_config/connection_config.go b/core/server/api_container/server/startosis_engine/kurtosis_types/connection_config/connection_config.go
index 17e34301f..42e1bedcf 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/connection_config/connection_config.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/connection_config/connection_config.go
@@ -44,7 +44,7 @@ func NewConnectionConfigType() *kurtosis_type_constructor.KurtosisTypeConstructo
 	}
 }
 
-func instantiate(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) {
+func instantiate(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
 	kurtosisValueType, err := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(ConnectionConfigTypeName, arguments)
 	if err != nil {
 		return nil, err
@@ -75,6 +75,16 @@ func CreateConnectionConfig(packetLossPercentage starlark.Float) (*ConnectionCon
 	}, nil
 }
 
+func (connectionConfig *ConnectionConfig) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := connectionConfig.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &ConnectionConfig{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
 func (connectionConfig *ConnectionConfig) ToKurtosisType() (*partition_topology.PartitionConnection, *startosis_errors.InterpretationError) {
 	packetLossPctStarlark, _, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.Float](
 		connectionConfig.KurtosisValueTypeDefault, PacketLossPercentageAttr)
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/normal_packet_delay_distribution.go b/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/normal_packet_delay_distribution.go
index 6edb5203c..7f0fa5177 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/normal_packet_delay_distribution.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/normal_packet_delay_distribution.go
@@ -56,7 +56,7 @@ func NewNormalPacketDelayDistributionType() *kurtosis_type_constructor.KurtosisT
 	}
 }
 
-func instantiateNormalPacketDelayDistribution(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) {
+func instantiateNormalPacketDelayDistribution(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
 	kurtosisValueType, err := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(NormalPacketDelayDistributionTypeName, arguments)
 	if err != nil {
 		return nil, err
@@ -70,6 +70,16 @@ type NormalPacketDelayDistribution struct {
 	*kurtosis_type_constructor.KurtosisValueTypeDefault
 }
 
+func (packetDelayDistribution *NormalPacketDelayDistribution) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := packetDelayDistribution.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &NormalPacketDelayDistribution{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
 func (packetDelayDistribution *NormalPacketDelayDistribution) ToKurtosisType() (*partition_topology.PacketDelayDistribution, *startosis_errors.InterpretationError) {
 	meanStarlark, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.Int](
 		packetDelayDistribution.KurtosisValueTypeDefault, MeanAttr)
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/packet_delay_distribution.go b/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/packet_delay_distribution.go
index 467b7bdb8..536378c34 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/packet_delay_distribution.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/packet_delay_distribution.go
@@ -2,12 +2,12 @@ package packet_delay_distribution
 
 import (
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/partition_topology"
-	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors"
 )
 
 type PacketDelayDistribution interface {
-	kurtosis_type_constructor.KurtosisValueType
+	builtin_argument.KurtosisValueType
 
 	ToKurtosisType() (*partition_topology.PacketDelayDistribution, *startosis_errors.InterpretationError)
 }
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/uniform_packet_delay_distribution.go b/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/uniform_packet_delay_distribution.go
index e23e1726b..6b2931819 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/uniform_packet_delay_distribution.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution/uniform_packet_delay_distribution.go
@@ -37,7 +37,7 @@ func NewUniformPacketDelayDistributionType() *kurtosis_type_constructor.Kurtosis
 	}
 }
 
-func instantiateUniformPacketDelayDistribution(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) {
+func instantiateUniformPacketDelayDistribution(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
 	kurtosisValueType, err := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(UniformPacketDelayDistributionTypeName, arguments)
 	if err != nil {
 		return nil, err
@@ -51,6 +51,16 @@ type UniformPacketDelayDistribution struct {
 	*kurtosis_type_constructor.KurtosisValueTypeDefault
 }
 
+func (packetDelayDistribution *UniformPacketDelayDistribution) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := packetDelayDistribution.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &UniformPacketDelayDistribution{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
 func (packetDelayDistribution *UniformPacketDelayDistribution) ToKurtosisType() (*partition_topology.PacketDelayDistribution, *startosis_errors.InterpretationError) {
 	delayMsStarlark, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.Int](
 		packetDelayDistribution.KurtosisValueTypeDefault, DelayAttr)
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/port_spec/port_spec.go b/core/server/api_container/server/startosis_engine/kurtosis_types/port_spec/port_spec.go
index b7d865ad6..242f7495e 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/port_spec/port_spec.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/port_spec/port_spec.go
@@ -61,7 +61,7 @@ func NewPortSpecType() *kurtosis_type_constructor.KurtosisTypeConstructor {
 	}
 }
 
-func instantiate(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) {
+func instantiate(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
 	kurtosisValueType, interpretationErr := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(PortSpecTypeName, arguments)
 	if interpretationErr != nil {
 		return nil, interpretationErr
@@ -97,6 +97,16 @@ func CreatePortSpec(portNumber uint32, transportProtocol kurtosis_core_rpc_api_b
 	}, nil
 }
 
+func (portSpec *PortSpec) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := portSpec.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &PortSpec{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
 func (portSpec *PortSpec) ToKurtosisType() (*kurtosis_core_rpc_api_bindings.Port, *startosis_errors.InterpretationError) {
 	portNumber, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.Int](
 		portSpec.KurtosisValueTypeDefault, PortNumberAttr)
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_conditions.go b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_conditions.go
index d13c44964..d5cf54a77 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_conditions.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_conditions.go
@@ -81,7 +81,7 @@ func NewReadyConditionsType() *kurtosis_type_constructor.KurtosisTypeConstructor
 	}
 }
 
-func instantiateReadyConditions(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) {
+func instantiateReadyConditions(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
 	kurtosisValueType, err := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(ReadyConditionsTypeName, arguments)
 	if err != nil {
 		return nil, err
@@ -96,6 +96,16 @@ type ReadyConditions struct {
 	*kurtosis_type_constructor.KurtosisValueTypeDefault
 }
 
+func (readyConditions *ReadyConditions) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := readyConditions.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &ReadyConditions{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
 func (readyConditions *ReadyConditions) GetRecipe() (recipe.Recipe, *startosis_errors.InterpretationError) {
 	var genericRecipe recipe.Recipe
 
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go
index f6b76f96e..a6dce18a9 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/service_config.go
@@ -125,7 +125,7 @@ func NewServiceConfigType() *kurtosis_type_constructor.KurtosisTypeConstructor {
 	}
 }
 
-func instantiateServiceConfig(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) {
+func instantiateServiceConfig(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
 	kurtosisValueType, err := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(ServiceConfigTypeName, arguments)
 	if err != nil {
 		return nil, err
@@ -140,6 +140,16 @@ type ServiceConfig struct {
 	*kurtosis_type_constructor.KurtosisValueTypeDefault
 }
 
+func (config *ServiceConfig) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := config.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &ServiceConfig{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
 func (config *ServiceConfig) ToKurtosisType() (*kurtosis_core_rpc_api_bindings.ServiceConfig, *startosis_errors.InterpretationError) {
 	image, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](config.KurtosisValueTypeDefault, ImageAttr)
 	if interpretationErr != nil {
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/update_service_config/update_service_config.go b/core/server/api_container/server/startosis_engine/kurtosis_types/update_service_config/update_service_config.go
index 654fe6ba8..b64edb4a3 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/update_service_config/update_service_config.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/update_service_config/update_service_config.go
@@ -36,7 +36,7 @@ func NewUpdateServiceConfigType() *kurtosis_type_constructor.KurtosisTypeConstru
 	}
 }
 
-func instantiate(arguments *builtin_argument.ArgumentValuesSet) (kurtosis_type_constructor.KurtosisValueType, *startosis_errors.InterpretationError) {
+func instantiate(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
 	kurtosisValueType, err := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(UpdateServiceConfigTypeName, arguments)
 	if err != nil {
 		return nil, err
@@ -50,6 +50,16 @@ type UpdateServiceConfig struct {
 	*kurtosis_type_constructor.KurtosisValueTypeDefault
 }
 
+func (config *UpdateServiceConfig) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := config.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &UpdateServiceConfig{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
 func (config *UpdateServiceConfig) ToKurtosisType() (*kurtosis_core_rpc_api_bindings.UpdateServiceConfig, *startosis_errors.InterpretationError) {
 	subnetworkStarlarkValue, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](
 		config.KurtosisValueTypeDefault, SubnetworkAttr)
diff --git a/core/server/go.mod b/core/server/go.mod
index ef6e16f3c..c63b97f19 100644
--- a/core/server/go.mod
+++ b/core/server/go.mod
@@ -5,6 +5,7 @@ go 1.18
 replace (
 	github.com/kurtosis-tech/kurtosis/api/golang => ../../api/golang
 	github.com/kurtosis-tech/kurtosis/container-engine-lib => ../../container-engine-lib
+	github.com/kurtosis-tech/kurtosis/contexts-config-store => ../../contexts-config-store
 	github.com/kurtosis-tech/kurtosis/core/files_artifacts_expander => ../files_artifacts_expander
 	github.com/kurtosis-tech/kurtosis/core/launcher => ../launcher
 	github.com/kurtosis-tech/kurtosis/kurtosis_version => ../../kurtosis_version
diff --git a/core/server/go.sum b/core/server/go.sum
index f9a65a7e4..8e04a11d4 100644
--- a/core/server/go.sum
+++ b/core/server/go.sum
@@ -3,7 +3,6 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
 github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w=
@@ -55,7 +54,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
-github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
 github.com/gammazero/deque v0.1.0 h1:f9LnNmq66VDeuAlSAapemq/U7hJ2jpIWa4c09q8Dlik=
 github.com/gammazero/deque v0.1.0/go.mod h1:KQw7vFau1hHuM8xmI9RbgKFbAsQFWmBpqQ2KenFLk6M=
 github.com/gammazero/workerpool v1.1.2 h1:vuioDQbgrz4HoaCi2q1HLlOXdpbap5AET7xu5/qj87g=
@@ -124,9 +122,8 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0
 github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -159,8 +156,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
-github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
@@ -257,7 +252,6 @@ golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -317,12 +311,10 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
 google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=


Test patch:
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_value_copier_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_value_copier_test.go
new file mode 100644
index 000000000..632a678e1
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument/argument_value_copier_test.go
@@ -0,0 +1,134 @@
+package builtin_argument
+
+import (
+	"github.com/stretchr/testify/require"
+	starlarktime "go.starlark.net/lib/time"
+	"go.starlark.net/starlark"
+	"go.starlark.net/starlarkstruct"
+	"math"
+	"testing"
+	"time"
+)
+
+func TestCopyValueBool(t *testing.T) {
+	value := starlark.Bool(true)
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+}
+
+func TestCopyValueBytes(t *testing.T) {
+	value := starlark.Bytes("Hello")
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+}
+
+func TestCopyValueFloat(t *testing.T) {
+	value := starlark.Float(math.Pi)
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+}
+
+func TestCopyValueInt(t *testing.T) {
+	value := starlark.MakeInt(42)
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+}
+
+func TestCopyValueNoneType(t *testing.T) {
+	value := starlark.None
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+}
+
+func TestCopyValueString(t *testing.T) {
+	value := starlark.String("Hello")
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+}
+
+func TestCopyValueTime(t *testing.T) {
+	value := starlarktime.Time(time.Now())
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+}
+
+func TestCopyValueDuration(t *testing.T) {
+	value := starlarktime.Duration(42 & time.Second)
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+}
+
+func TestCopyValueList(t *testing.T) {
+	value := starlark.NewList([]starlark.Value{
+		starlark.String("hello"),
+		starlark.MakeInt(42),
+		starlark.None,
+	})
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+	require.NotSame(t, valueCopy, value)
+}
+
+func TestCopyValueSet(t *testing.T) {
+	value := starlark.NewSet(3)
+	require.NoError(t, value.Insert(starlark.String("hello")))
+	require.NoError(t, value.Insert(starlark.MakeInt(42)))
+	require.NoError(t, value.Insert(starlark.None))
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+	require.NotSame(t, valueCopy, value)
+}
+
+func TestCopyValueTuple(t *testing.T) {
+	value := starlark.Tuple([]starlark.Value{
+		starlark.String("hello"),
+		starlark.MakeInt(42),
+		starlark.None,
+	})
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+	require.NotSame(t, valueCopy, value)
+}
+
+func TestCopyValueDict(t *testing.T) {
+	value := starlark.NewDict(3)
+	require.NoError(t, value.SetKey(starlark.String("hello"), starlark.Float(math.Pi)))
+	require.NoError(t, value.SetKey(starlark.MakeInt(42), starlark.None))
+	require.NoError(t, value.SetKey(starlark.String("nested"), starlark.Tuple([]starlark.Value{
+		starlark.String("hello"),
+		starlark.MakeInt(42),
+		starlark.None,
+	})))
+
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+	require.NotSame(t, valueCopy, value)
+}
+
+func TestCopyValueStruct(t *testing.T) {
+	valueDict := starlark.StringDict{}
+	valueDict["hello"] = starlark.String("world")
+	valueDict["bonjour"] = starlark.MakeInt(42)
+	valueDict["nested"] = starlark.NewList([]starlark.Value{
+		starlark.String("Hello"),
+		starlark.MakeInt(42),
+	})
+	value := starlarkstruct.FromStringDict(starlarkstruct.Default, valueDict)
+
+	valueCopy, err := DeepCopyArgumentValue(value)
+	require.NoError(t, err)
+	require.Equal(t, valueCopy, value)
+	require.NotSame(t, valueCopy, value)
+}
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_full_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_full_test.go
index ad9da6a53..9018837e3 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_full_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_full_test.go
@@ -3,11 +3,11 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/partition_topology"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/connection_config"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -34,7 +34,7 @@ func (t *connectionConfigFullTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%s, %s=%s)", connection_config.ConnectionConfigTypeName, connection_config.PacketLossPercentageAttr, "50.0", connection_config.PacketDelayDistributionAttr, packetDelayArg)
 }
 
-func (t *connectionConfigFullTestCase) Assert(typeValue starlark.Value) {
+func (t *connectionConfigFullTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	connectionConfigStarlark, ok := typeValue.(*connection_config.ConnectionConfig)
 	require.True(t, ok)
 	connectionConfig, err := connectionConfigStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_with_packet_delay_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_with_packet_delay_test.go
index 02ac86be9..e54d87422 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_with_packet_delay_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_with_packet_delay_test.go
@@ -3,11 +3,11 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/partition_topology"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/connection_config"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -34,7 +34,7 @@ func (t *connectionConfigWithPacketDelayTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%s)", connection_config.ConnectionConfigTypeName, connection_config.PacketDelayDistributionAttr, packetDelayArg)
 }
 
-func (t *connectionConfigWithPacketDelayTestCase) Assert(typeValue starlark.Value) {
+func (t *connectionConfigWithPacketDelayTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	connectionConfigStarlark, ok := typeValue.(*connection_config.ConnectionConfig)
 	require.True(t, ok)
 	connectionConfig, err := connectionConfigStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_with_packet_loss_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_with_packet_loss_test.go
index e379f105c..2828b8513 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_with_packet_loss_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/connection_config_with_packet_loss_test.go
@@ -3,10 +3,10 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/partition_topology"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/connection_config"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -32,7 +32,7 @@ func (t *connectionConfigWithPacketLossTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%s)", connection_config.ConnectionConfigTypeName, connection_config.PacketLossPercentageAttr, "50.0")
 }
 
-func (t *connectionConfigWithPacketLossTestCase) Assert(typeValue starlark.Value) {
+func (t *connectionConfigWithPacketLossTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	connectionConfigStarlark, ok := typeValue.(*connection_config.ConnectionConfig)
 	require.True(t, ok)
 	connectionConfig, err := connectionConfigStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_print_framework_test_case.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_print_framework_test.go
similarity index 100%
rename from core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_print_framework_test_case.go
rename to core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_print_framework_test.go
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_type_constructor_base_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_type_constructor_base_test.go
index f742d746c..67cf626d9 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_type_constructor_base_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/kurtosis_type_constructor_base_test.go
@@ -1,8 +1,8 @@
 package test_engine
 
 import (
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
-	"go.starlark.net/starlark"
 )
 
 type KurtosisTypeConstructorBaseTest interface {
@@ -17,5 +17,5 @@ type KurtosisTypeConstructorBaseTest interface {
 
 	// Assert is called after the Starlark code returned by GetStarlarkCode has been sent to the interpreter
 	// The typeValue argument corresponds to the value that was instantiated based on the starlark code provided
-	Assert(typeValue starlark.Value)
+	Assert(typeValue builtin_argument.KurtosisValueType)
 }
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/normal_packet_delay_distribution_full_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/normal_packet_delay_distribution_full_test.go
index a02a4a337..a2a6cc516 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/normal_packet_delay_distribution_full_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/normal_packet_delay_distribution_full_test.go
@@ -3,10 +3,10 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/partition_topology"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -32,7 +32,7 @@ func (t *normalPacketDelayDistributionFullTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%d, %s=%d, %s=%s)", packet_delay_distribution.NormalPacketDelayDistributionTypeName, packet_delay_distribution.MeanAttr, 110, packet_delay_distribution.StdDevAttr, 16, packet_delay_distribution.CorrelationAttr, "13.4")
 }
 
-func (t *normalPacketDelayDistributionFullTestCase) Assert(typeValue starlark.Value) {
+func (t *normalPacketDelayDistributionFullTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	normalPacketDelayDistributionStarlark, ok := typeValue.(*packet_delay_distribution.NormalPacketDelayDistribution)
 	require.True(t, ok)
 	normalPacketDelayDistribution, err := normalPacketDelayDistributionStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/normal_packet_delay_distribution_minimal_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/normal_packet_delay_distribution_minimal_test.go
index 26cfd1490..8ac86796a 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/normal_packet_delay_distribution_minimal_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/normal_packet_delay_distribution_minimal_test.go
@@ -3,10 +3,10 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/partition_topology"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -32,7 +32,7 @@ func (t *normalPacketDelayDistributionMinimalTestCase) GetStarlarkCode() string
 	return fmt.Sprintf("%s(%s=%d, %s=%d)", packet_delay_distribution.NormalPacketDelayDistributionTypeName, packet_delay_distribution.MeanAttr, 110, packet_delay_distribution.StdDevAttr, 16)
 }
 
-func (t *normalPacketDelayDistributionMinimalTestCase) Assert(typeValue starlark.Value) {
+func (t *normalPacketDelayDistributionMinimalTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	normalPacketDelayDistributionStarlark, ok := typeValue.(*packet_delay_distribution.NormalPacketDelayDistribution)
 	require.True(t, ok)
 	normalPacketDelayDistribution, err := normalPacketDelayDistributionStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/port_spec_full_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/port_spec_full_framework_test.go
index 2f6c16fb5..ab57010ac 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/port_spec_full_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/port_spec_full_framework_test.go
@@ -3,10 +3,10 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/binding_constructors"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/port_spec"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -32,7 +32,7 @@ func (t *portSpecFullTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%d, %s=%q, %s=%q)", port_spec.PortSpecTypeName, port_spec.PortNumberAttr, TestPrivatePortNumber, port_spec.TransportProtocolAttr, TestPrivatePortProtocolStr, port_spec.PortApplicationProtocolAttr, TestPrivateApplicationProtocol)
 }
 
-func (t *portSpecFullTestCase) Assert(typeValue starlark.Value) {
+func (t *portSpecFullTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	portSpecStarlark, ok := typeValue.(*port_spec.PortSpec)
 	require.True(t, ok)
 	portSpec, err := portSpecStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/port_spec_minimal_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/port_spec_minimal_framework_test.go
index fcd701b5b..dc86435f7 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/port_spec_minimal_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/port_spec_minimal_framework_test.go
@@ -4,10 +4,10 @@ import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/kurtosis_core_rpc_api_bindings"
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/binding_constructors"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/port_spec"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -33,7 +33,7 @@ func (t *portSpecMinimalTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%d)", port_spec.PortSpecTypeName, port_spec.PortNumberAttr, TestPrivatePortNumber)
 }
 
-func (t *portSpecMinimalTestCase) Assert(typeValue starlark.Value) {
+func (t *portSpecMinimalTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	portSpecStarlark, ok := typeValue.(*port_spec.PortSpec)
 	require.True(t, ok)
 	portSpec, err := portSpecStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/ready_conditions_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/ready_conditions_framework_test.go
index 9711be4bb..e7cb50878 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/ready_conditions_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/ready_conditions_framework_test.go
@@ -2,6 +2,7 @@ package test_engine
 
 import (
 	"fmt"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/recipe"
@@ -54,7 +55,7 @@ func (t *readyConditionsTestCase) GetStarlarkCode() string {
 	)
 }
 
-func (t *readyConditionsTestCase) Assert(typeValue starlark.Value) {
+func (t *readyConditionsTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	receivedReadyConditions, ok := typeValue.(*service_config.ReadyConditions)
 	require.True(t, ok)
 
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_test.go
index 7bddbbd4c..65055931b 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_full_framework_test.go
@@ -5,10 +5,10 @@ import (
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/kurtosis_core_rpc_api_bindings"
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/binding_constructors"
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/services"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -50,7 +50,7 @@ func (t *serviceConfigFullTestCase) GetStarlarkCode() string {
 	return starlarkCode
 }
 
-func (t *serviceConfigFullTestCase) Assert(typeValue starlark.Value) {
+func (t *serviceConfigFullTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	serviceConfigStarlark, ok := typeValue.(*service_config.ServiceConfig)
 	require.True(t, ok)
 
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_minimal_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_minimal_framework_test.go
index 7a5aa076b..86591c9d5 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_minimal_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/service_config_minimal_framework_test.go
@@ -3,10 +3,10 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/services"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/service_config"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -34,7 +34,7 @@ func (t *serviceConfigMinimalTestCase) GetStarlarkCode() string {
 		service_config.ImageAttr, TestContainerImageName)
 }
 
-func (t *serviceConfigMinimalTestCase) Assert(typeValue starlark.Value) {
+func (t *serviceConfigMinimalTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	serviceConfigStarlark, ok := typeValue.(*service_config.ServiceConfig)
 	require.True(t, ok)
 
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/starlark_framework_engine_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/starlark_framework_engine_test.go
index 615568493..b0fbf0e81 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/starlark_framework_engine_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/starlark_framework_engine_test.go
@@ -6,6 +6,7 @@ import (
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/builtins"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_plan_instruction"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_constants"
 	"github.com/stretchr/testify/require"
@@ -13,6 +14,7 @@ import (
 	"go.starlark.net/starlark"
 	"go.starlark.net/starlarkjson"
 	"go.starlark.net/starlarkstruct"
+	"reflect"
 	"testing"
 )
 
@@ -124,7 +126,16 @@ func testKurtosisTypeConstructor(t *testing.T, builtin KurtosisTypeConstructorBa
 	require.Nil(t, err, "Error interpreting Starlark code for builtin '%s'. Code was: \n%v", testId, starlarkCodeToExecute)
 	result := extractResultValue(t, globals)
 
-	builtin.Assert(result)
+	kurtosisValue, ok := result.(builtin_argument.KurtosisValueType)
+	require.True(t, ok, "Error casting the Kurtosis Type to a KurtosisValueType. This is unexpected as all "+
+		"typed defined in Kurtosis should implement KurtosisValueType. Its type was: '%s'", reflect.TypeOf(kurtosisValue))
+
+	builtin.Assert(kurtosisValue)
+
+	copiedKurtosisValue, copyErr := kurtosisValue.Copy()
+	require.NoError(t, copyErr)
+	require.Equal(t, kurtosisValue, copiedKurtosisValue)
+	require.NotSame(t, kurtosisValue, copiedKurtosisValue)
 
 	serializedType := result.String()
 	require.Equal(t, starlarkCode, serializedType)
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/uniform_packet_delay_distribution_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/uniform_packet_delay_distribution_framework_test.go
index a3195ab88..7a242e70d 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/uniform_packet_delay_distribution_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/uniform_packet_delay_distribution_framework_test.go
@@ -3,10 +3,10 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network/partition_topology"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/packet_delay_distribution"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -32,7 +32,7 @@ func (t *uniformPacketDelayDistributionTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%d)", packet_delay_distribution.UniformPacketDelayDistributionTypeName, packet_delay_distribution.DelayAttr, 110)
 }
 
-func (t *uniformPacketDelayDistributionTestCase) Assert(typeValue starlark.Value) {
+func (t *uniformPacketDelayDistributionTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	uniformPacketDelayDistributionStarlark, ok := typeValue.(*packet_delay_distribution.UniformPacketDelayDistribution)
 	require.True(t, ok)
 	uniformPacketDelayDistribution, err := uniformPacketDelayDistributionStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/update_service_config_framework_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/update_service_config_framework_test.go
index 4ad54bd5d..fb46dfa52 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/update_service_config_framework_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/update_service_config_framework_test.go
@@ -3,10 +3,10 @@ package test_engine
 import (
 	"fmt"
 	"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/binding_constructors"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/builtin_argument"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/kurtosis_type_constructor"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types/update_service_config"
 	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
 	"testing"
 )
 
@@ -32,7 +32,7 @@ func (t *updateServiceConfigTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%q)", update_service_config.UpdateServiceConfigTypeName, update_service_config.SubnetworkAttr, TestSubnetwork)
 }
 
-func (t *updateServiceConfigTestCase) Assert(typeValue starlark.Value) {
+func (t *updateServiceConfigTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
 	updateServiceConfigStarlark, ok := typeValue.(*update_service_config.UpdateServiceConfig)
 	require.True(t, ok)
 	updateServiceConfig, err := updateServiceConfigStarlark.ToKurtosisType()
diff --git a/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go b/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go
index ef038ca81..833d6f81c 100644
--- a/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go
+++ b/core/server/api_container/server/startosis_engine/startosis_interpreter_test.go
@@ -48,14 +48,38 @@ def run(plan):
 `
 
 	_, instructions, interpretationError := interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, script, startosis_constants.EmptyInputArgs)
-	require.Len(t, instructions, 1) // Only the print statement
 	require.Nil(t, interpretationError)
+	require.Len(t, instructions, 1) // Only the print statement
 
 	expectedOutput := testString + `
 `
 	validateScriptOutputFromPrintInstructions(t, instructions, expectedOutput)
 }
 
+func TestStartosisInterpreter_Test(t *testing.T) {
+	packageContentProvider := mock_package_content_provider.NewMockPackageContentProvider()
+	runtimeValueStore := runtime_value_store.NewRuntimeValueStore()
+	defer packageContentProvider.RemoveAll()
+	startosisInterpreter := NewStartosisInterpreter(testServiceNetwork, packageContentProvider, runtimeValueStore)
+	interpreter := startosisInterpreter
+	script := `
+def run(plan):
+	my_dict = {}
+	plan.print(my_dict)
+	my_dict["hello"] = "world"
+	plan.print(my_dict)
+`
+
+	_, instructions, interpretationError := interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, script, startosis_constants.EmptyInputArgs)
+	require.Len(t, instructions, 2) // Only the print statement
+	require.Nil(t, interpretationError)
+
+	expectedOutput := `{}
+{"hello": "world"}
+`
+	validateScriptOutputFromPrintInstructions(t, instructions, expectedOutput)
+}
+
 func TestStartosisInterpreter_DefineFactAndWait(t *testing.T) {
 	packageContentProvider := mock_package_content_provider.NewMockPackageContentProvider()
 	defer packageContentProvider.RemoveAll()