Repository: kurtosis-tech/kurtosis
Pull request #485 (2023-04-07 13:06:40)

refactor: Migrate Get and Post recipe to Starlark command framework
## Description:
Migrate GetHttpRequestRecipe and PostHttpRequestRecipe to Starlark command framework

## 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>0a1f24c</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>&nbsp;✅&nbsp; Deploy successful!</td></tr>
<tr><td><strong>Preview URL:</strong></td><td>
<a href='https://63213577.kurtosis-docs.pages.dev'>https://63213577.kurtosis-docs.pages.dev</a>
</td></tr>
<tr><td><strong>Branch Preview URL:</strong></td><td>
<a href='https://gbouv-http-recipe-framework.kurtosis-docs.pages.dev'>https://gbouv-http-recipe-framework.kurtosis-docs.pages.dev</a>
</td></tr>
</table>

[View logs](https://dash.cloudflare.com/?to=/:account/pages/view/kurtosis/63213577-466b-4c75-afe0-3983d4c9adbb)


Patch:
diff --git a/cli/cli/commands/lsp/resource/kurtosis_starlark.json b/cli/cli/commands/lsp/resource/kurtosis_starlark.json
index f16f0b9a0..46b5023c9 100644
--- a/cli/cli/commands/lsp/resource/kurtosis_starlark.json
+++ b/cli/cli/commands/lsp/resource/kurtosis_starlark.json
@@ -398,13 +398,13 @@
         {
           "name": "content_type",
           "type": "string",
-          "content": "content_type",
+          "content": "content_type?",
           "detail": "The content type header of the request (e.g. application/json, text/plain, etc)"
         },
         {
           "name": "body",
           "type": "string",
-          "content": "body",
+          "content": "body?",
           "detail": "The body of the request"
         },
         {
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_builtins.go b/core/server/api_container/server/startosis_engine/kurtosis_builtins.go
index a26e0fa6e..ccace7af3 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_builtins.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_builtins.go
@@ -82,8 +82,8 @@ func KurtosisHelpers(recursiveInterpret func(moduleId string, scriptContent stri
 func KurtosisTypeConstructors() []*starlark.Builtin {
 	return []*starlark.Builtin{
 		starlark.NewBuiltin(recipe.ExecRecipeTypeName, recipe.NewExecRecipeType().CreateBuiltin()),
-		starlark.NewBuiltin(recipe.GetHttpRecipeTypeName, recipe.MakeGetHttpRequestRecipe),
-		starlark.NewBuiltin(recipe.PostHttpRecipeTypeName, recipe.MakePostHttpRequestRecipe),
+		starlark.NewBuiltin(recipe.GetHttpRecipeTypeName, recipe.NewGetHttpRequestRecipeType().CreateBuiltin()),
+		starlark.NewBuiltin(recipe.PostHttpRecipeTypeName, recipe.NewPostHttpRequestRecipeType().CreateBuiltin()),
 		starlark.NewBuiltin(connection_config.ConnectionConfigTypeName, connection_config.NewConnectionConfigType().CreateBuiltin()),
 		starlark.NewBuiltin(packet_delay_distribution.NormalPacketDelayDistributionTypeName, packet_delay_distribution.NewNormalPacketDelayDistributionType().CreateBuiltin()),
 		starlark.NewBuiltin(packet_delay_distribution.UniformPacketDelayDistributionTypeName, packet_delay_distribution.NewUniformPacketDelayDistributionType().CreateBuiltin()),
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/request/request.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/request/request.go
index a012068b0..ae37e8524 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/request/request.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/request/request.go
@@ -60,7 +60,7 @@ func NewRequest(serviceNetwork service_network.ServiceNetwork, runtimeValueStore
 				{
 					Name:              RecipeArgName,
 					IsOptional:        false,
-					ZeroValueProvider: builtin_argument.ZeroValueProvider[*recipe.HttpRequestRecipe],
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[recipe.HttpRequestRecipe],
 					Validator:         nil,
 				},
 				{
@@ -102,7 +102,7 @@ type RequestCapabilities struct {
 	runtimeValueStore *runtime_value_store.RuntimeValueStore
 
 	serviceName       service.ServiceName
-	httpRequestRecipe *recipe.HttpRequestRecipe
+	httpRequestRecipe recipe.HttpRequestRecipe
 	resultUuid        string
 	acceptableCodes   []int64
 	skipCodeCheck     bool
@@ -116,7 +116,7 @@ func (builtin *RequestCapabilities) Interpret(arguments *builtin_argument.Argume
 	}
 	serviceName := service.ServiceName(serviceNameArgumentValue.GoString())
 
-	httpRequestRecipe, err := builtin_argument.ExtractArgumentValue[*recipe.HttpRequestRecipe](arguments, RecipeArgName)
+	httpRequestRecipe, err := builtin_argument.ExtractArgumentValue[recipe.HttpRequestRecipe](arguments, RecipeArgName)
 	if err != nil {
 		return nil, startosis_errors.WrapWithInterpretationError(err, "Unable to extract value for '%s' argument", RecipeArgName)
 	}
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_instruction/wait/wait.go b/core/server/api_container/server/startosis_engine/kurtosis_instruction/wait/wait.go
index ae53add45..c06f791bc 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_instruction/wait/wait.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_instruction/wait/wait.go
@@ -138,7 +138,7 @@ func (builtin *WaitCapabilities) Interpret(arguments *builtin_argument.ArgumentV
 	serviceName := service.ServiceName(serviceNameArgumentValue.GoString())
 
 	var genericRecipe recipe.Recipe
-	httpRecipe, err := builtin_argument.ExtractArgumentValue[*recipe.HttpRequestRecipe](arguments, RecipeArgName)
+	httpRecipe, err := builtin_argument.ExtractArgumentValue[recipe.HttpRequestRecipe](arguments, RecipeArgName)
 	if err != nil {
 		execRecipe, err := builtin_argument.ExtractArgumentValue[*recipe.ExecRecipe](arguments, RecipeArgName)
 		if err != nil {
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_condition.go b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_condition.go
index def3feb50..37e9054bb 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_condition.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_types/service_config/ready_condition.go
@@ -109,7 +109,7 @@ func (readyCondition *ReadyCondition) Copy() (builtin_argument.KurtosisValueType
 func (readyCondition *ReadyCondition) GetRecipe() (recipe.Recipe, *startosis_errors.InterpretationError) {
 	var genericRecipe recipe.Recipe
 
-	httpRecipe, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*recipe.HttpRequestRecipe](readyCondition.KurtosisValueTypeDefault, RecipeAttr)
+	httpRecipe, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[recipe.HttpRequestRecipe](readyCondition.KurtosisValueTypeDefault, RecipeAttr)
 	genericRecipe = httpRecipe
 	if !found {
 		return nil, startosis_errors.NewInterpretationError("Required attribute '%s' could not be found on type '%s'",
@@ -205,7 +205,7 @@ func (readyCondition *ReadyCondition) GetTimeout() (time.Duration, *startosis_er
 }
 
 func validateRecipe(value starlark.Value) *startosis_errors.InterpretationError {
-	_, ok := value.(*recipe.HttpRequestRecipe)
+	_, ok := value.(recipe.HttpRequestRecipe)
 	if !ok {
 		//TODO we should rework the recipe types to inherit a single common type, this will avoid the double parsing here.
 		_, ok := value.(*recipe.ExecRecipe)
diff --git a/core/server/api_container/server/startosis_engine/recipe/get_http_request_recipe.go b/core/server/api_container/server/startosis_engine/recipe/get_http_request_recipe.go
new file mode 100644
index 000000000..50019c577
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/recipe/get_http_request_recipe.go
@@ -0,0 +1,164 @@
+package recipe
+
+import (
+	"context"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework"
+	"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/runtime_value_store"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors"
+	"github.com/kurtosis-tech/stacktrace"
+	"github.com/sirupsen/logrus"
+	"go.starlark.net/starlark"
+)
+
+const (
+	GetHttpRecipeTypeName = "GetHttpRequestRecipe"
+
+	getMethod        = "GET"
+	emptyRequestBody = ""
+	noContentType    = ""
+)
+
+func NewGetHttpRequestRecipeType() *kurtosis_type_constructor.KurtosisTypeConstructor {
+	return &kurtosis_type_constructor.KurtosisTypeConstructor{
+		KurtosisBaseBuiltin: &kurtosis_starlark_framework.KurtosisBaseBuiltin{
+			Name: GetHttpRecipeTypeName,
+			Arguments: []*builtin_argument.BuiltinArgument{
+				{
+					Name:              PortIdAttr,
+					IsOptional:        false,
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String],
+					Validator: func(value starlark.Value) *startosis_errors.InterpretationError {
+						return builtin_argument.NonEmptyString(value, PortIdAttr)
+					},
+				},
+				{
+					Name:              EndpointAttr,
+					IsOptional:        false,
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String],
+					Validator: func(value starlark.Value) *startosis_errors.InterpretationError {
+						return nil
+					},
+				},
+				{
+					Name:              ExtractAttr,
+					IsOptional:        true,
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[*starlark.Dict],
+					Validator: func(value starlark.Value) *startosis_errors.InterpretationError {
+						_, interpretationErr := convertExtractorsToDict(true, value)
+						return interpretationErr
+					},
+				},
+			},
+		},
+		Instantiate: instantiateGetHttpRequestRecipe,
+	}
+}
+
+func instantiateGetHttpRequestRecipe(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
+	kurtosisValueType, interpretationErr := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(GetHttpRecipeTypeName, arguments)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	return &GetHttpRequestRecipe{
+		KurtosisValueTypeDefault: kurtosisValueType,
+	}, nil
+}
+
+type GetHttpRequestRecipe struct {
+	*kurtosis_type_constructor.KurtosisValueTypeDefault
+}
+
+func (recipe *GetHttpRequestRecipe) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := recipe.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &GetHttpRequestRecipe{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
+func (recipe *GetHttpRequestRecipe) Execute(
+	ctx context.Context,
+	serviceNetwork service_network.ServiceNetwork,
+	runtimeValueStore *runtime_value_store.RuntimeValueStore,
+	serviceName service.ServiceName,
+) (map[string]starlark.Comparable, error) {
+	logrus.Debugf("Running get HTTP request recipe '%s'", recipe.String())
+
+	portId, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](
+		recipe.KurtosisValueTypeDefault, PortIdAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	if !found {
+		return nil, startosis_errors.NewInterpretationError("Mandatory attribute '%s' was not set on '%s'. This is unexpected and should have been caught earlier", PortIdAttr, GetHttpRecipeTypeName)
+	}
+
+	endpoint, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](
+		recipe.KurtosisValueTypeDefault, EndpointAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	if !found {
+		return nil, startosis_errors.NewInterpretationError("Mandatory attribute '%s' was not set on '%s'. This is unexpected and should have been caught earlier", EndpointAttr, GetHttpRecipeTypeName)
+	}
+
+	rawExtractors, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*starlark.Dict](
+		recipe.KurtosisValueTypeDefault, ExtractAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	extractors, interpretationErr := convertExtractorsToDict(found, rawExtractors)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+
+	serviceNameStr := string(serviceName)
+	if serviceNameStr == "" {
+		return nil, stacktrace.NewError("The service name parameter can't be an empty string")
+	}
+
+	requestResultDict, err := executeInternal(
+		ctx,
+		serviceNetwork,
+		runtimeValueStore,
+		serviceName,
+		emptyRequestBody,
+		portId.GoString(),
+		getMethod,
+		noContentType,
+		endpoint.GoString(),
+		extractors,
+	)
+	if err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred when running HTTP request recipe '%v'", recipe.String())
+	}
+	return requestResultDict, nil
+}
+
+func (recipe *GetHttpRequestRecipe) ResultMapToString(resultMap map[string]starlark.Comparable) string {
+	return resultMapToStringInternal(resultMap)
+}
+
+func (recipe *GetHttpRequestRecipe) CreateStarlarkReturnValue(resultUuid string) (*starlark.Dict, *startosis_errors.InterpretationError) {
+	rawExtractors, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*starlark.Dict](
+		recipe.KurtosisValueTypeDefault, ExtractAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	extractors, interpretationErr := convertExtractorsToDict(found, rawExtractors)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+
+	returnValue, interpretationErr := createStarlarkReturnValueInternal(resultUuid, extractors)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	return returnValue, nil
+}
diff --git a/core/server/api_container/server/startosis_engine/recipe/http_request_recipe.go b/core/server/api_container/server/startosis_engine/recipe/http_request_recipe.go
index 99d7c1dd6..ab26120c4 100644
--- a/core/server/api_container/server/startosis_engine/recipe/http_request_recipe.go
+++ b/core/server/api_container/server/startosis_engine/recipe/http_request_recipe.go
@@ -8,7 +8,7 @@ import (
 	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_instruction/shared_helpers/magic_string_helper"
-	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_types"
+	"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/runtime_value_store"
 	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors"
 	"github.com/kurtosis-tech/stacktrace"
@@ -16,232 +16,42 @@ import (
 	"go.starlark.net/starlark"
 	"io"
 	"net/http"
+	"reflect"
 	"strings"
 )
 
 const (
-	postMethod        = "POST"
-	getMethod         = "GET"
-	emptyBody         = ""
-	unusedContentType = ""
-
 	statusCodeKey    = "code"
 	bodyKey          = "body"
-	ExtractKeyPrefix = "extract"
-
-	PortIdAttr      = "port_id"
-	serviceNameAttr = "service_name"
-	EndpointAttr    = "endpoint"
-	methodAttr      = "method"
-	contentTypeAttr = "content_type"
-
-	defaultContentType = "application/json"
+	extractKeyPrefix = "extract"
 
-	PostHttpRecipeTypeName = "PostHttpRequestRecipe"
-	GetHttpRecipeTypeName  = "GetHttpRequestRecipe"
-
-	HttpRecipeTypeName = "HttpRequestRecipe"
+	// Common attributes for both [Get|Post]HttpRequestRecipe
+	PortIdAttr   = "port_id"
+	EndpointAttr = "endpoint"
+	ExtractAttr  = "extract"
 )
 
-type HttpRequestRecipe struct {
-	portId      string
-	contentType string
-	endpoint    string
-	method      string
-	body        string
-	extractors  map[string]string
-}
-
-func NewPostHttpRequestRecipe(portId string, contentType string, endpoint string, body string, extractors map[string]string) *HttpRequestRecipe {
-	return &HttpRequestRecipe{
-		portId:      portId,
-		method:      postMethod,
-		contentType: contentType,
-		endpoint:    endpoint,
-		body:        body,
-		extractors:  extractors,
-	}
-}
-
-func NewGetHttpRequestRecipe(portId string, endpoint string, extractors map[string]string) *HttpRequestRecipe {
-	return &HttpRequestRecipe{
-		portId:      portId,
-		method:      getMethod,
-		contentType: unusedContentType,
-		endpoint:    endpoint,
-		body:        emptyBody,
-		extractors:  extractors,
-	}
-}
-
-// String the starlark.Value interface
-func (recipe *HttpRequestRecipe) String() string {
-	buffer := new(strings.Builder)
-	instanceName := recipe.GetInstanceName()
-
-	buffer.WriteString(instanceName + "(")
-	buffer.WriteString(PortIdAttr + "=")
-	buffer.WriteString(fmt.Sprintf("%q, ", recipe.portId))
-
-	buffer.WriteString(EndpointAttr + "=")
-	buffer.WriteString(fmt.Sprintf("%q, ", recipe.endpoint))
-
-	if recipe.method == postMethod {
-		buffer.WriteString(bodyKey + "=")
-		buffer.WriteString(fmt.Sprintf("%q, ", recipe.body))
-		buffer.WriteString(contentTypeAttr + "=")
-		buffer.WriteString(fmt.Sprintf("%q, ", recipe.contentType))
-	}
-
-	buffer.WriteString(ExtractKeyPrefix + "=")
-	extractors, err := convertMapToStarlarkDict(recipe.extractors)
-
-	if err != nil {
-		logrus.Errorf("Error occurred while accessing extractors")
-	}
-
-	if extractors.Len() > 0 {
-		buffer.WriteString(fmt.Sprintf("%v)", extractors))
-	} else {
-		buffer.WriteString(fmt.Sprintf("%s)", "{}"))
-	}
-	return buffer.String()
-}
-
-// Type implements the starlark.Value interface
-func (recipe *HttpRequestRecipe) Type() string {
-	return HttpRecipeTypeName
-}
-
-// Freeze implements the starlark.Value interface
-func (recipe *HttpRequestRecipe) Freeze() {
-	// this is a no-op its already immutable
-}
-
-// Truth implements the starlark.Value interface
-func (recipe *HttpRequestRecipe) Truth() starlark.Bool {
-	truth := recipe.portId != "" && recipe.endpoint != "" && recipe.method != ""
-	if recipe.method == postMethod {
-		truth = truth && recipe.body != "" && recipe.contentType != ""
-	}
-	return starlark.Bool(truth)
-}
-
-// Hash implements the starlark.Value interface
-// This shouldn't be hashed, users should use a portId instead
-func (recipe *HttpRequestRecipe) Hash() (uint32, error) {
-	return 0, startosis_errors.NewInterpretationError("unhashable type: '%v'", HttpRecipeTypeName)
-}
-
-func (recipe *HttpRequestRecipe) GetInstanceName() string {
-	instanceName := GetHttpRecipeTypeName
-	if recipe.method == postMethod {
-		instanceName = PostHttpRecipeTypeName
-	}
-	return instanceName
-}
-
-// Attr implements the starlark.HasAttrs interface.
-func (recipe *HttpRequestRecipe) Attr(name string) (starlark.Value, error) {
-	switch name {
-	case PortIdAttr:
-		return starlark.String(recipe.portId), nil
-	case ExtractKeyPrefix:
-		return convertMapToStarlarkDict(recipe.extractors)
-	case bodyKey:
-		return starlark.String(recipe.body), nil
-	case contentTypeAttr:
-		return starlark.String(recipe.contentType), nil
-	case methodAttr:
-		return starlark.String(recipe.method), nil
-	case EndpointAttr:
-		return starlark.String(recipe.endpoint), nil
-	default:
-		return nil, startosis_errors.NewInterpretationError("'%v' has no attribute '%v;", HttpRecipeTypeName, name)
-	}
-}
-
-// AttrNames implements the starlark.HasAttrs interface.
-func (recipe *HttpRequestRecipe) AttrNames() []string {
-	return []string{PortIdAttr, serviceNameAttr, ExtractKeyPrefix, EndpointAttr, contentTypeAttr, methodAttr, bodyKey}
-}
-
-func MakeGetHttpRequestRecipe(_ *starlark.Thread, builtin *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
-	var portId string
-	var endpoint string
-	var maybeExtractField starlark.Value
-
-	if err := starlark.UnpackArgs(builtin.Name(), args, kwargs,
-		PortIdAttr, &portId,
-		EndpointAttr, &endpoint,
-		kurtosis_types.MakeOptional(ExtractKeyPrefix), &maybeExtractField,
-	); err != nil {
-		return nil, startosis_errors.NewInterpretationError(err.Error())
-	}
-
-	extractedMap := map[string]string{}
-	var err *startosis_errors.InterpretationError
+type HttpRequestRecipe interface {
+	builtin_argument.KurtosisValueType
 
-	if maybeExtractField != nil {
-		extractedMap, err = kurtosis_types.SafeCastToMapStringString(maybeExtractField, ExtractKeyPrefix)
-		if err != nil {
-			return nil, err
-		}
-	}
-	recipe := NewGetHttpRequestRecipe(portId, endpoint, extractedMap)
-	return recipe, nil
+	Recipe
 }
 
-func MakePostHttpRequestRecipe(_ *starlark.Thread, builtin *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
-	var portId string
-	var endpoint string
-
-	var maybeBody starlark.Value
-	contentType := defaultContentType
-	var maybeExtractField starlark.Value
-
-	if err := starlark.UnpackArgs(builtin.Name(), args, kwargs,
-		PortIdAttr, &portId,
-		EndpointAttr, &endpoint,
-		kurtosis_types.MakeOptional(bodyKey), &maybeBody,
-		kurtosis_types.MakeOptional(contentTypeAttr), &contentType,
-		kurtosis_types.MakeOptional(ExtractKeyPrefix), &maybeExtractField,
-	); err != nil {
-		return nil, startosis_errors.NewInterpretationError("%v", err.Error())
-	}
-
-	extractedMap := map[string]string{}
-	extractedBody := ""
-	var err *startosis_errors.InterpretationError
-
-	if maybeExtractField != nil {
-		extractedMap, err = kurtosis_types.SafeCastToMapStringString(maybeExtractField, ExtractKeyPrefix)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	if maybeBody != nil {
-		extractedBody, err = kurtosis_types.SafeCastToString(maybeBody, bodyKey)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	recipe := NewPostHttpRequestRecipe(portId, contentType, endpoint, extractedBody, extractedMap)
-	return recipe, nil
-}
-
-func (recipe *HttpRequestRecipe) Execute(
+func executeInternal(
 	ctx context.Context,
 	serviceNetwork service_network.ServiceNetwork,
 	runtimeValueStore *runtime_value_store.RuntimeValueStore,
 	serviceName service.ServiceName,
+	requestBody string,
+	portId string,
+	method string,
+	contentType string,
+	endpoint string,
+	extractors map[string]string,
 ) (map[string]starlark.Comparable, error) {
 	var response *http.Response
 	var err error
-	logrus.Debugf("Running HTTP request recipe '%v'", recipe)
-	recipeBodyWithRuntimeValue, err := magic_string_helper.ReplaceRuntimeValueInString(recipe.body, runtimeValueStore)
+	recipeBodyWithRuntimeValue, err := magic_string_helper.ReplaceRuntimeValueInString(requestBody, runtimeValueStore)
 	if err != nil {
 		return nil, stacktrace.Propagate(err, "An error occurred while replacing runtime values in the body of the http recipe")
 	}
@@ -254,10 +64,10 @@ func (recipe *HttpRequestRecipe) Execute(
 	response, err = serviceNetwork.HttpRequestService(
 		ctx,
 		serviceNameStr,
-		recipe.portId,
-		recipe.method,
-		recipe.contentType,
-		recipe.endpoint,
+		portId,
+		method,
+		contentType,
+		endpoint,
 		recipeBodyWithRuntimeValue,
 	)
 	if err != nil {
@@ -269,37 +79,37 @@ func (recipe *HttpRequestRecipe) Execute(
 			logrus.Errorf("An error occurred when closing response body: %v", err)
 		}
 	}()
-	body, err := io.ReadAll(response.Body)
-	logrus.Debugf("Got response '%v'", string(body))
+	responseBody, err := io.ReadAll(response.Body)
+	logrus.Debugf("Got response '%v'", string(responseBody))
 	if err != nil {
 		return nil, stacktrace.Propagate(err, "An error occurred while reading HTTP response body")
 	}
 	resultDict := map[string]starlark.Comparable{
-		bodyKey:       starlark.String(body),
+		bodyKey:       starlark.String(responseBody),
 		statusCodeKey: starlark.MakeInt(response.StatusCode),
 	}
-	extractDict, err := recipe.extract(body)
+	extractDict, err := extractInternal(responseBody, extractors)
 	if err != nil {
 		return nil, stacktrace.Propagate(err, "An error occurred while running extractors on HTTP response body")
 	}
 	for extractorKey, extractorValue := range extractDict {
-		resultDict[fmt.Sprintf("%v.%v", ExtractKeyPrefix, extractorKey)] = extractorValue
+		resultDict[fmt.Sprintf("%v.%v", extractKeyPrefix, extractorKey)] = extractorValue
 	}
 	return resultDict, nil
 }
 
-func (recipe *HttpRequestRecipe) extract(body []byte) (map[string]starlark.Comparable, error) {
-	if len(recipe.extractors) == 0 {
+func extractInternal(responseBody []byte, extractors map[string]string) (map[string]starlark.Comparable, error) {
+	if len(extractors) == 0 {
 		return map[string]starlark.Comparable{}, nil
 	}
 	logrus.Debug("Executing extract recipe")
 	var jsonBody interface{}
-	err := json.Unmarshal(body, &jsonBody)
+	err := json.Unmarshal(responseBody, &jsonBody)
 	if err != nil {
 		return nil, stacktrace.Propagate(err, "An error occurred when parsing JSON response body")
 	}
 	extractorResult := map[string]starlark.Comparable{}
-	for extractorKey, extractor := range recipe.extractors {
+	for extractorKey, extractor := range extractors {
 		logrus.Debugf("Running against '%v' '%v'", jsonBody, extractor)
 		query, err := gojq.Parse(extractor)
 		if err != nil {
@@ -337,19 +147,19 @@ func (recipe *HttpRequestRecipe) extract(body []byte) (map[string]starlark.Compa
 			}
 		}
 		if !foundMatch {
-			return nil, stacktrace.NewError("No field '%v' was found on input '%v'", extractor, body)
+			return nil, stacktrace.NewError("No field '%s' was found on input '%s'", extractor, string(responseBody))
 		}
 	}
 	logrus.Debugf("Extractor result map '%v'", extractorResult)
 	return extractorResult, nil
 }
 
-func (recipe *HttpRequestRecipe) ResultMapToString(resultMap map[string]starlark.Comparable) string {
+func resultMapToStringInternal(resultMap map[string]starlark.Comparable) string {
 	statusCode := resultMap[statusCodeKey]
 	body := resultMap[bodyKey]
 	extractedFieldString := strings.Builder{}
 	for resultKey, resultValue := range resultMap {
-		if strings.Contains(resultKey, ExtractKeyPrefix) {
+		if strings.Contains(resultKey, extractKeyPrefix) {
 			extractedFieldString.WriteString(fmt.Sprintf("\n'%v': %v", resultKey, resultValue))
 		}
 	}
@@ -360,7 +170,7 @@ func (recipe *HttpRequestRecipe) ResultMapToString(resultMap map[string]starlark
 	}
 }
 
-func (recipe *HttpRequestRecipe) CreateStarlarkReturnValue(resultUuid string) (*starlark.Dict, *startosis_errors.InterpretationError) {
+func createStarlarkReturnValueInternal(resultUuid string, extractors map[string]string) (*starlark.Dict, *startosis_errors.InterpretationError) {
 	dict := &starlark.Dict{}
 	err := dict.SetKey(starlark.String(bodyKey), starlark.String(fmt.Sprintf(magic_string_helper.RuntimeValueReplacementPlaceholderFormat, resultUuid, bodyKey)))
 	if err != nil {
@@ -370,8 +180,8 @@ func (recipe *HttpRequestRecipe) CreateStarlarkReturnValue(resultUuid string) (*
 	if err != nil {
 		return nil, startosis_errors.NewInterpretationError("An error has occurred when creating return value for request recipe, setting field '%v'", statusCodeKey)
 	}
-	for extractorKey := range recipe.extractors {
-		fullExtractorKey := fmt.Sprintf("%v.%v", ExtractKeyPrefix, extractorKey)
+	for extractorKey := range extractors {
+		fullExtractorKey := fmt.Sprintf("%v.%v", extractKeyPrefix, extractorKey)
 		err = dict.SetKey(starlark.String(fullExtractorKey), starlark.String(fmt.Sprintf(magic_string_helper.RuntimeValueReplacementPlaceholderFormat, resultUuid, fullExtractorKey)))
 		if err != nil {
 			return nil, startosis_errors.NewInterpretationError("An error has occurred when creating return value for request recipe, setting field '%v'", fullExtractorKey)
@@ -381,14 +191,33 @@ func (recipe *HttpRequestRecipe) CreateStarlarkReturnValue(resultUuid string) (*
 	return dict, nil
 }
 
-func convertMapToStarlarkDict(inputMap map[string]string) (*starlark.Dict, *startosis_errors.InterpretationError) {
-	sizeOfExtractors := len(inputMap)
-	dict := starlark.NewDict(sizeOfExtractors)
-	for key, val := range inputMap {
-		err := dict.SetKey(starlark.String(key), starlark.String(val))
+func convertExtractorsToDict(isAttrSet bool, extractorsValue starlark.Value) (map[string]string, *startosis_errors.InterpretationError) {
+	extractorStringMap := map[string]string{}
+	if !isAttrSet {
+		return extractorStringMap, nil
+	}
+	extractorsDict, ok := extractorsValue.(*starlark.Dict)
+	if !ok {
+		return nil, startosis_errors.NewInterpretationError("Attribute '%s' on '%s' is expected to be a dictionary of strings, got '%s'", ExtractAttr, GetHttpRecipeTypeName, reflect.TypeOf(extractorsValue))
+	}
+
+	for _, extractorKey := range extractorsDict.Keys() {
+		extractorValue, found, err := extractorsDict.Get(extractorKey)
 		if err != nil {
-			return nil, startosis_errors.NewInterpretationError("Error occurred while converting extractor map to starlark type")
+			return nil, startosis_errors.WrapWithInterpretationError(err, "Unexpected error iterating on dictionary. Value associated to key '%v' could not be found", extractorKey)
+		} else if !found {
+			return nil, startosis_errors.NewInterpretationError("Unexpected error iterating on dictionary. Value associated to key '%v' could not be found", extractorKey)
 		}
+
+		extractorKeyStr, ok := extractorKey.(starlark.String)
+		if !ok {
+			return nil, startosis_errors.NewInterpretationError("Key in '%s' dictionary was expected to be a string, got '%s'", ExtractAttr, reflect.TypeOf(extractorKey))
+		}
+		extractorValueStr, ok := extractorValue.(starlark.String)
+		if !ok {
+			return nil, startosis_errors.NewInterpretationError("Value associated to key '%s' in dictionary '%s' was expected to be a string, got '%s'", extractorKeyStr, ExtractAttr, reflect.TypeOf(extractorsValue))
+		}
+		extractorStringMap[extractorKeyStr.GoString()] = extractorValueStr.GoString()
 	}
-	return dict, nil
+	return extractorStringMap, nil
 }
diff --git a/core/server/api_container/server/startosis_engine/recipe/post_http_request_recipe.go b/core/server/api_container/server/startosis_engine/recipe/post_http_request_recipe.go
new file mode 100644
index 000000000..118cfd4f8
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/recipe/post_http_request_recipe.go
@@ -0,0 +1,200 @@
+package recipe
+
+import (
+	"context"
+	"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework"
+	"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/runtime_value_store"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/startosis_errors"
+	"github.com/kurtosis-tech/stacktrace"
+	"github.com/sirupsen/logrus"
+	"go.starlark.net/starlark"
+)
+
+const (
+	PostHttpRecipeTypeName = "PostHttpRequestRecipe"
+
+	ContentTypeAttr = "content_type"
+	RequestBodyAttr = "body"
+
+	postMethod         = "POST"
+	defaultContentType = "application/json"
+)
+
+func NewPostHttpRequestRecipeType() *kurtosis_type_constructor.KurtosisTypeConstructor {
+	return &kurtosis_type_constructor.KurtosisTypeConstructor{
+		KurtosisBaseBuiltin: &kurtosis_starlark_framework.KurtosisBaseBuiltin{
+			Name: PostHttpRecipeTypeName,
+			Arguments: []*builtin_argument.BuiltinArgument{
+				{
+					Name:              PortIdAttr,
+					IsOptional:        false,
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String],
+					Validator: func(value starlark.Value) *startosis_errors.InterpretationError {
+						return builtin_argument.NonEmptyString(value, PortIdAttr)
+					},
+				},
+				{
+					Name:              EndpointAttr,
+					IsOptional:        false,
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String],
+					Validator: func(value starlark.Value) *startosis_errors.InterpretationError {
+						return nil
+					},
+				},
+				{
+					Name:              RequestBodyAttr,
+					IsOptional:        true,
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String],
+					Validator: func(value starlark.Value) *startosis_errors.InterpretationError {
+						return nil
+					},
+				},
+				{
+					Name:              ContentTypeAttr,
+					IsOptional:        true,
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[starlark.String],
+					Validator: func(value starlark.Value) *startosis_errors.InterpretationError {
+						return nil
+					},
+				},
+				{
+					Name:              ExtractAttr,
+					IsOptional:        true,
+					ZeroValueProvider: builtin_argument.ZeroValueProvider[*starlark.Dict],
+					Validator: func(value starlark.Value) *startosis_errors.InterpretationError {
+						_, interpretationErr := convertExtractorsToDict(true, value)
+						return interpretationErr
+					},
+				},
+			},
+		},
+		Instantiate: instantiatePostHttpRequestRecipe,
+	}
+}
+
+func instantiatePostHttpRequestRecipe(arguments *builtin_argument.ArgumentValuesSet) (builtin_argument.KurtosisValueType, *startosis_errors.InterpretationError) {
+	kurtosisValueType, interpretationErr := kurtosis_type_constructor.CreateKurtosisStarlarkTypeDefault(PostHttpRecipeTypeName, arguments)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	return &PostHttpRequestRecipe{
+		KurtosisValueTypeDefault: kurtosisValueType,
+	}, nil
+}
+
+type PostHttpRequestRecipe struct {
+	*kurtosis_type_constructor.KurtosisValueTypeDefault
+}
+
+func (recipe *PostHttpRequestRecipe) Copy() (builtin_argument.KurtosisValueType, error) {
+	copiedValueType, err := recipe.KurtosisValueTypeDefault.Copy()
+	if err != nil {
+		return nil, err
+	}
+	return &PostHttpRequestRecipe{
+		KurtosisValueTypeDefault: copiedValueType,
+	}, nil
+}
+
+func (recipe *PostHttpRequestRecipe) Execute(
+	ctx context.Context,
+	serviceNetwork service_network.ServiceNetwork,
+	runtimeValueStore *runtime_value_store.RuntimeValueStore,
+	serviceName service.ServiceName,
+) (map[string]starlark.Comparable, error) {
+	logrus.Debugf("Running get HTTP request recipe '%s'", recipe.String())
+
+	portId, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](
+		recipe.KurtosisValueTypeDefault, PortIdAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	if !found {
+		return nil, startosis_errors.NewInterpretationError("Mandatory attribute '%s' was not set on '%s'. This is unexpected and should have been caught earlier", PortIdAttr, GetHttpRecipeTypeName)
+	}
+
+	endpoint, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](
+		recipe.KurtosisValueTypeDefault, EndpointAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	if !found {
+		return nil, startosis_errors.NewInterpretationError("Mandatory attribute '%s' was not set on '%s'. This is unexpected and should have been caught earlier", EndpointAttr, GetHttpRecipeTypeName)
+	}
+
+	contentType, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](
+		recipe.KurtosisValueTypeDefault, ContentTypeAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	if !found {
+		contentType = defaultContentType
+	}
+
+	requestBody, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[starlark.String](
+		recipe.KurtosisValueTypeDefault, RequestBodyAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	if !found {
+		requestBody = ""
+	}
+
+	rawExtractors, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*starlark.Dict](
+		recipe.KurtosisValueTypeDefault, ExtractAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	extractors, interpretationErr := convertExtractorsToDict(found, rawExtractors)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+
+	serviceNameStr := string(serviceName)
+	if serviceNameStr == "" {
+		return nil, stacktrace.NewError("The service name parameter can't be an empty string")
+	}
+
+	requestResultDict, err := executeInternal(
+		ctx,
+		serviceNetwork,
+		runtimeValueStore,
+		serviceName,
+		requestBody.GoString(),
+		portId.GoString(),
+		postMethod,
+		contentType.GoString(),
+		endpoint.GoString(),
+		extractors,
+	)
+	if err != nil {
+		return nil, stacktrace.Propagate(err, "An error occurred when running HTTP request recipe '%v'", recipe.String())
+	}
+	return requestResultDict, nil
+}
+
+func (recipe *PostHttpRequestRecipe) ResultMapToString(resultMap map[string]starlark.Comparable) string {
+	return resultMapToStringInternal(resultMap)
+}
+
+func (recipe *PostHttpRequestRecipe) CreateStarlarkReturnValue(resultUuid string) (*starlark.Dict, *startosis_errors.InterpretationError) {
+	rawExtractors, found, interpretationErr := kurtosis_type_constructor.ExtractAttrValue[*starlark.Dict](
+		recipe.KurtosisValueTypeDefault, ExtractAttr)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	extractors, interpretationErr := convertExtractorsToDict(found, rawExtractors)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+
+	returnValue, interpretationErr := createStarlarkReturnValueInternal(resultUuid, extractors)
+	if interpretationErr != nil {
+		return nil, interpretationErr
+	}
+	return returnValue, nil
+}
diff --git a/docs/docs/starlark-reference/get-http-request-recipe.md b/docs/docs/starlark-reference/get-http-request-recipe.md
index 95eb4e487..049c0dbee 100644
--- a/docs/docs/starlark-reference/get-http-request-recipe.md
+++ b/docs/docs/starlark-reference/get-http-request-recipe.md
@@ -24,7 +24,7 @@ get_request_recipe = GetHttpRequestRecipe(
     # body that you get from the HTTP GET request.
     # 
     # To lean more about jq, please visit https://devdocs.io/jq/
-    # OPTIONAL
+    # OPTIONAL (DEFAULT:{})
     extract = {
         "extractfield" : ".name.id",
     },
diff --git a/docs/docs/starlark-reference/port-spec.md b/docs/docs/starlark-reference/port-spec.md
index f8cd47fe0..795a4c060 100644
--- a/docs/docs/starlark-reference/port-spec.md
+++ b/docs/docs/starlark-reference/port-spec.md
@@ -19,7 +19,7 @@ port_spec = PortSpec(
     # For example:
     #  "http" to get a URL of "http://..."
     #  "postgresql" to get a URL of "postgresql://..."
-    # OPTIONAL
+    # OPTIONAL (DEFAULT:"http")
     application_protocol = "http",
 )
 ```
diff --git a/docs/docs/starlark-reference/post-http-request-recipe.md b/docs/docs/starlark-reference/post-http-request-recipe.md
index c2980ac34..1481ee043 100644
--- a/docs/docs/starlark-reference/post-http-request-recipe.md
+++ b/docs/docs/starlark-reference/post-http-request-recipe.md
@@ -16,18 +16,18 @@ post_request_recipe = PostHttpRequestRecipe(
     endpoint = "/endpoint",
 
     # The content type header of the request (e.g. application/json, text/plain, etc)
-    # MANDATORY
+    # OPTIONAL (DEFAULT:"application/json")
     content_type = "application/json",
 
     # The body of the request
-    # MANDATORY
+    # OPTIONAL (DEFAULT:"")
     body = "{\"data\": \"this is sample body for POST\"}",
     
     # The extract dictionary takes in key-value pairs where:
     # Key is a way you refer to the extraction later on
     # Value is a 'jq' string that contains logic to extract from response body
     # # To lean more about jq, please visit https://devdocs.io/jq/
-    # OPTIONAL
+    # OPTIONAL (DEFAULT:{})
     extract = {
         "extractfield" : ".name.id",
     },


Test patch:
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 9018837e3..885e2594d 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
@@ -4,7 +4,6 @@ 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"
@@ -25,10 +24,6 @@ func (t *connectionConfigFullTestCase) GetId() string {
 	return fmt.Sprintf("%s_%s", connection_config.ConnectionConfigTypeName, "Full")
 }
 
-func (t *connectionConfigFullTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return connection_config.NewConnectionConfigType()
-}
-
 func (t *connectionConfigFullTestCase) GetStarlarkCode() string {
 	packetDelayArg := fmt.Sprintf("%s(%s=%d, %s=%d)", packet_delay_distribution.NormalPacketDelayDistributionTypeName, packet_delay_distribution.MeanAttr, 100, packet_delay_distribution.StdDevAttr, 10)
 	return fmt.Sprintf("%s(%s=%s, %s=%s)", connection_config.ConnectionConfigTypeName, connection_config.PacketLossPercentageAttr, "50.0", connection_config.PacketDelayDistributionAttr, packetDelayArg)
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 e54d87422..eab67ebbb 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
@@ -4,7 +4,6 @@ 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"
@@ -25,10 +24,6 @@ func (t *connectionConfigWithPacketDelayTestCase) GetId() string {
 	return fmt.Sprintf("%s_%s", connection_config.ConnectionConfigTypeName, "WithPacketDelay")
 }
 
-func (t *connectionConfigWithPacketDelayTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return connection_config.NewConnectionConfigType()
-}
-
 func (t *connectionConfigWithPacketDelayTestCase) GetStarlarkCode() string {
 	packetDelayArg := fmt.Sprintf("%s(%s=%d)", packet_delay_distribution.UniformPacketDelayDistributionTypeName, packet_delay_distribution.DelayAttr, 10)
 	return fmt.Sprintf("%s(%s=%s)", connection_config.ConnectionConfigTypeName, connection_config.PacketDelayDistributionAttr, packetDelayArg)
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 2828b8513..609d57635 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
@@ -4,7 +4,6 @@ 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"
 	"testing"
@@ -24,10 +23,6 @@ func (t *connectionConfigWithPacketLossTestCase) GetId() string {
 	return fmt.Sprintf("%s_%s", connection_config.ConnectionConfigTypeName, "WithPacketLoss")
 }
 
-func (t *connectionConfigWithPacketLossTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return connection_config.NewConnectionConfigType()
-}
-
 func (t *connectionConfigWithPacketLossTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%s)", connection_config.ConnectionConfigTypeName, connection_config.PacketLossPercentageAttr, "50.0")
 }
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_no_extractor_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_no_extractor_test.go
new file mode 100644
index 000000000..454fbf8c9
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_no_extractor_test.go
@@ -0,0 +1,82 @@
+package test_engine
+
+import (
+	"context"
+	"fmt"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
+	"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/recipe"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store"
+	"github.com/stretchr/testify/mock"
+	"github.com/stretchr/testify/require"
+	"io"
+	"net/http"
+	"strings"
+	"testing"
+)
+
+type getHttpRequestRecipeNoExtractorTestCase struct {
+	*testing.T
+	serviceNetwork    *service_network.MockServiceNetwork
+	runtimeValueStore *runtime_value_store.RuntimeValueStore
+}
+
+func newGetHttpRequestRecipeNoExtractorTestCase(t *testing.T) *getHttpRequestRecipeNoExtractorTestCase {
+	runtimeValueStore := runtime_value_store.NewRuntimeValueStore()
+
+	serviceNetwork := service_network.NewMockServiceNetwork(t)
+	serviceNetwork.EXPECT().HttpRequestService(
+		mock.Anything,
+		string(TestServiceName),
+		TestPrivatePortId,
+		"GET",
+		"",
+		"/test",
+		"",
+	).Times(1).Return(
+		&http.Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Header:           nil,
+			Body:             io.NopCloser(strings.NewReader("")),
+			ContentLength:    -1,
+			TransferEncoding: nil,
+			Close:            false,
+			Uncompressed:     false,
+			Trailer:          nil,
+			Request:          nil,
+			TLS:              nil,
+		},
+		nil,
+	)
+
+	return &getHttpRequestRecipeNoExtractorTestCase{
+		T:                 t,
+		serviceNetwork:    serviceNetwork,
+		runtimeValueStore: runtimeValueStore,
+	}
+}
+
+func (t *getHttpRequestRecipeNoExtractorTestCase) GetId() string {
+	return fmt.Sprintf("%s_%s", recipe.GetHttpRecipeTypeName, "no_extractors")
+}
+
+func (t *getHttpRequestRecipeNoExtractorTestCase) GetStarlarkCode() string {
+	return fmt.Sprintf("%s(%s=%q, %s=%q)", recipe.GetHttpRecipeTypeName, recipe.PortIdAttr, TestPrivatePortId, recipe.EndpointAttr, "/test")
+}
+
+func (t *getHttpRequestRecipeNoExtractorTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
+	getHttpRequestRecipe, ok := typeValue.(*recipe.GetHttpRequestRecipe)
+	require.True(t, ok)
+
+	_, err := getHttpRequestRecipe.Execute(context.Background(), t.serviceNetwork, t.runtimeValueStore, TestServiceName)
+	require.NoError(t, err)
+
+	returnValue, interpretationErr := getHttpRequestRecipe.CreateStarlarkReturnValue("result-fake-uuid")
+	require.Nil(t, interpretationErr)
+	expectedInterpretationResult := `{"body": "{{kurtosis:result-fake-uuid:body.runtime_value}}", "code": "{{kurtosis:result-fake-uuid:code.runtime_value}}"}`
+	require.Equal(t, expectedInterpretationResult, returnValue.String())
+}
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_test.go
new file mode 100644
index 000000000..b1ebef246
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/get_http_request_recipe_test.go
@@ -0,0 +1,87 @@
+package test_engine
+
+import (
+	"context"
+	"fmt"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
+	"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/recipe"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store"
+	"github.com/stretchr/testify/mock"
+	"github.com/stretchr/testify/require"
+	"io"
+	"net/http"
+	"strings"
+	"testing"
+)
+
+const (
+	getHttpRequestRecipeResponseJson = `{"value": "Hello world!"}`
+)
+
+type getHttpRequestRecipeTestCase struct {
+	*testing.T
+	serviceNetwork    *service_network.MockServiceNetwork
+	runtimeValueStore *runtime_value_store.RuntimeValueStore
+}
+
+func newGetHttpRequestRecipeTestCase(t *testing.T) *getHttpRequestRecipeTestCase {
+	runtimeValueStore := runtime_value_store.NewRuntimeValueStore()
+
+	serviceNetwork := service_network.NewMockServiceNetwork(t)
+	serviceNetwork.EXPECT().HttpRequestService(
+		mock.Anything,
+		string(TestServiceName),
+		TestPrivatePortId,
+		"GET",
+		"",
+		"/test",
+		"",
+	).Times(1).Return(
+		&http.Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Header:           nil,
+			Body:             io.NopCloser(strings.NewReader(getHttpRequestRecipeResponseJson)),
+			ContentLength:    -1,
+			TransferEncoding: nil,
+			Close:            false,
+			Uncompressed:     false,
+			Trailer:          nil,
+			Request:          nil,
+			TLS:              nil,
+		},
+		nil,
+	)
+
+	return &getHttpRequestRecipeTestCase{
+		T:                 t,
+		serviceNetwork:    serviceNetwork,
+		runtimeValueStore: runtimeValueStore,
+	}
+}
+
+func (t *getHttpRequestRecipeTestCase) GetId() string {
+	return fmt.Sprintf("%s_%s", recipe.GetHttpRecipeTypeName, "with_extractors")
+}
+
+func (t *getHttpRequestRecipeTestCase) GetStarlarkCode() string {
+	extractors := `{"result": ".value"}`
+	return fmt.Sprintf("%s(%s=%q, %s=%q, %s=%s)", recipe.GetHttpRecipeTypeName, recipe.PortIdAttr, TestPrivatePortId, recipe.EndpointAttr, "/test", recipe.ExtractAttr, extractors)
+}
+
+func (t *getHttpRequestRecipeTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
+	getHttpRequestRecipe, ok := typeValue.(*recipe.GetHttpRequestRecipe)
+	require.True(t, ok)
+
+	_, err := getHttpRequestRecipe.Execute(context.Background(), t.serviceNetwork, t.runtimeValueStore, TestServiceName)
+	require.NoError(t, err)
+
+	returnValue, interpretationErr := getHttpRequestRecipe.CreateStarlarkReturnValue("result-fake-uuid")
+	require.Nil(t, interpretationErr)
+	expectedInterpretationResult := `{"body": "{{kurtosis:result-fake-uuid:body.runtime_value}}", "code": "{{kurtosis:result-fake-uuid:code.runtime_value}}", "extract.result": "{{kurtosis:result-fake-uuid:extract.result.runtime_value}}"}`
+	require.Equal(t, expectedInterpretationResult, returnValue.String())
+}
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 67cf626d9..edabc3497 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
@@ -2,16 +2,12 @@ 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"
 )
 
 type KurtosisTypeConstructorBaseTest interface {
 	// GetId is a unique identifier for this test that will be used in errors when a test fails.
 	GetId() string
 
-	// GetHelper should return the helper this test is testing
-	GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor
-
 	// GetStarlarkCode should return the Starlark code corresponding to the type constructor being tested.
 	GetStarlarkCode() string
 
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 a2a6cc516..df712a36e 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
@@ -4,7 +4,6 @@ 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"
 	"testing"
@@ -24,10 +23,6 @@ func (t *normalPacketDelayDistributionFullTestCase) GetId() string {
 	return fmt.Sprintf("%s_%s", packet_delay_distribution.NormalPacketDelayDistributionTypeName, "Full")
 }
 
-func (t *normalPacketDelayDistributionFullTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return packet_delay_distribution.NewNormalPacketDelayDistributionType()
-}
-
 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")
 }
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 8ac86796a..4e07b721a 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
@@ -4,7 +4,6 @@ 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"
 	"testing"
@@ -24,10 +23,6 @@ func (t *normalPacketDelayDistributionMinimalTestCase) GetId() string {
 	return fmt.Sprintf("%s_%s", packet_delay_distribution.NormalPacketDelayDistributionTypeName, "Minimal")
 }
 
-func (t *normalPacketDelayDistributionMinimalTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return packet_delay_distribution.NewNormalPacketDelayDistributionType()
-}
-
 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)
 }
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 ab57010ac..3c6aeaa58 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
@@ -4,7 +4,6 @@ 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"
 	"testing"
@@ -24,10 +23,6 @@ func (t *portSpecFullTestCase) GetId() string {
 	return fmt.Sprintf("%s_%s", port_spec.PortSpecTypeName, "full")
 }
 
-func (t *portSpecFullTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return port_spec.NewPortSpecType()
-}
-
 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)
 }
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 dc86435f7..ad0d1237e 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
@@ -5,7 +5,6 @@ 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/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"
 	"testing"
@@ -25,10 +24,6 @@ func (t *portSpecMinimalTestCase) GetId() string {
 	return fmt.Sprintf("%s_%s", port_spec.PortSpecTypeName, "full")
 }
 
-func (t *portSpecMinimalTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return port_spec.NewPortSpecType()
-}
-
 func (t *portSpecMinimalTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%d)", port_spec.PortSpecTypeName, port_spec.PortNumberAttr, TestPrivatePortNumber)
 }
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_minimal_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_minimal_test.go
new file mode 100644
index 000000000..d42821f27
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_minimal_test.go
@@ -0,0 +1,82 @@
+package test_engine
+
+import (
+	"context"
+	"fmt"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
+	"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/recipe"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store"
+	"github.com/stretchr/testify/mock"
+	"github.com/stretchr/testify/require"
+	"io"
+	"net/http"
+	"strings"
+	"testing"
+)
+
+type postHttpRequestRecipeMinimalTestCase struct {
+	*testing.T
+	serviceNetwork    *service_network.MockServiceNetwork
+	runtimeValueStore *runtime_value_store.RuntimeValueStore
+}
+
+func newPostHttpRequestRecipeMinimalTestCase(t *testing.T) *postHttpRequestRecipeMinimalTestCase {
+	runtimeValueStore := runtime_value_store.NewRuntimeValueStore()
+
+	serviceNetwork := service_network.NewMockServiceNetwork(t)
+	serviceNetwork.EXPECT().HttpRequestService(
+		mock.Anything,
+		string(TestServiceName),
+		TestPrivatePortId,
+		"POST",
+		"application/json",
+		"/test",
+		"",
+	).Times(1).Return(
+		&http.Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Header:           nil,
+			Body:             io.NopCloser(strings.NewReader("")),
+			ContentLength:    -1,
+			TransferEncoding: nil,
+			Close:            false,
+			Uncompressed:     false,
+			Trailer:          nil,
+			Request:          nil,
+			TLS:              nil,
+		},
+		nil,
+	)
+
+	return &postHttpRequestRecipeMinimalTestCase{
+		T:                 t,
+		serviceNetwork:    serviceNetwork,
+		runtimeValueStore: runtimeValueStore,
+	}
+}
+
+func (t *postHttpRequestRecipeMinimalTestCase) GetId() string {
+	return fmt.Sprintf("%s_%s", recipe.PostHttpRecipeTypeName, "minimal")
+}
+
+func (t *postHttpRequestRecipeMinimalTestCase) GetStarlarkCode() string {
+	return fmt.Sprintf("%s(%s=%q, %s=%q)", recipe.PostHttpRecipeTypeName, recipe.PortIdAttr, TestPrivatePortId, recipe.EndpointAttr, "/test")
+}
+
+func (t *postHttpRequestRecipeMinimalTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
+	postHttpRequestRecipe, ok := typeValue.(*recipe.PostHttpRequestRecipe)
+	require.True(t, ok)
+
+	_, err := postHttpRequestRecipe.Execute(context.Background(), t.serviceNetwork, t.runtimeValueStore, TestServiceName)
+	require.NoError(t, err)
+
+	returnValue, interpretationErr := postHttpRequestRecipe.CreateStarlarkReturnValue("result-fake-uuid")
+	require.Nil(t, interpretationErr)
+	expectedInterpretationResult := `{"body": "{{kurtosis:result-fake-uuid:body.runtime_value}}", "code": "{{kurtosis:result-fake-uuid:code.runtime_value}}"}`
+	require.Equal(t, expectedInterpretationResult, returnValue.String())
+}
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_test.go
new file mode 100644
index 000000000..109fe82f5
--- /dev/null
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/post_http_request_recipe_test.go
@@ -0,0 +1,87 @@
+package test_engine
+
+import (
+	"context"
+	"fmt"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/service_network"
+	"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/recipe"
+	"github.com/kurtosis-tech/kurtosis/core/server/api_container/server/startosis_engine/runtime_value_store"
+	"github.com/stretchr/testify/mock"
+	"github.com/stretchr/testify/require"
+	"io"
+	"net/http"
+	"strings"
+	"testing"
+)
+
+const (
+	postHttpRequestRecipeResponseJson = `{"value": "Hello world!"}`
+)
+
+type postHttpRequestRecipeTestCase struct {
+	*testing.T
+	serviceNetwork    *service_network.MockServiceNetwork
+	runtimeValueStore *runtime_value_store.RuntimeValueStore
+}
+
+func newPostHttpRequestRecipeTestCase(t *testing.T) *postHttpRequestRecipeTestCase {
+	runtimeValueStore := runtime_value_store.NewRuntimeValueStore()
+
+	serviceNetwork := service_network.NewMockServiceNetwork(t)
+	serviceNetwork.EXPECT().HttpRequestService(
+		mock.Anything,
+		string(TestServiceName),
+		TestPrivatePortId,
+		"POST",
+		"application/json",
+		"/test",
+		"{}",
+	).Times(1).Return(
+		&http.Response{
+			Status:           "200 OK",
+			StatusCode:       200,
+			Proto:            "HTTP/1.0",
+			ProtoMajor:       1,
+			ProtoMinor:       0,
+			Header:           nil,
+			Body:             io.NopCloser(strings.NewReader(postHttpRequestRecipeResponseJson)),
+			ContentLength:    -1,
+			TransferEncoding: nil,
+			Close:            false,
+			Uncompressed:     false,
+			Trailer:          nil,
+			Request:          nil,
+			TLS:              nil,
+		},
+		nil,
+	)
+
+	return &postHttpRequestRecipeTestCase{
+		T:                 t,
+		serviceNetwork:    serviceNetwork,
+		runtimeValueStore: runtimeValueStore,
+	}
+}
+
+func (t *postHttpRequestRecipeTestCase) GetId() string {
+	return fmt.Sprintf("%s_%s", recipe.PostHttpRecipeTypeName, "full")
+}
+
+func (t *postHttpRequestRecipeTestCase) GetStarlarkCode() string {
+	extractors := `{"result": ".value"}`
+	return fmt.Sprintf("%s(%s=%q, %s=%q, %s=%q, %s=%q, %s=%s)", recipe.PostHttpRecipeTypeName, recipe.PortIdAttr, TestPrivatePortId, recipe.EndpointAttr, "/test", recipe.RequestBodyAttr, "{}", recipe.ContentTypeAttr, "application/json", recipe.ExtractAttr, extractors)
+}
+
+func (t *postHttpRequestRecipeTestCase) Assert(typeValue builtin_argument.KurtosisValueType) {
+	postHttpRequestRecipe, ok := typeValue.(*recipe.PostHttpRequestRecipe)
+	require.True(t, ok)
+
+	_, err := postHttpRequestRecipe.Execute(context.Background(), t.serviceNetwork, t.runtimeValueStore, TestServiceName)
+	require.NoError(t, err)
+
+	returnValue, interpretationErr := postHttpRequestRecipe.CreateStarlarkReturnValue("result-fake-uuid")
+	require.Nil(t, interpretationErr)
+	expectedInterpretationResult := `{"body": "{{kurtosis:result-fake-uuid:body.runtime_value}}", "code": "{{kurtosis:result-fake-uuid:code.runtime_value}}", "extract.result": "{{kurtosis:result-fake-uuid:extract.result.runtime_value}}"}`
+	require.Equal(t, expectedInterpretationResult, returnValue.String())
+}
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 572a8a316..8c452fae1 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
@@ -3,7 +3,6 @@ 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"
 	"github.com/stretchr/testify/assert"
@@ -27,10 +26,6 @@ func (t *readyConditionsTestCase) GetId() string {
 	return service_config.ReadyConditionTypeName
 }
 
-func (t *readyConditionsTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return service_config.NewReadyConditionType()
-}
-
 func (t *readyConditionsTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%s(%s=%q, %s=%q, %s=%s), %s=%q, %s=%q, %s=%s, %s=%q, %s=%q)",
 		service_config.ReadyConditionTypeName,
@@ -40,7 +35,7 @@ func (t *readyConditionsTestCase) GetStarlarkCode() string {
 		TestReadyConditionsRecipePortId,
 		recipe.EndpointAttr,
 		TestReadyConditionsRecipeEndpoint,
-		recipe.ExtractKeyPrefix,
+		recipe.ExtractAttr,
 		TestReadyConditionsRecipeExtract,
 		service_config.FieldAttr,
 		TestReadyConditionsField,
@@ -61,7 +56,7 @@ func (t *readyConditionsTestCase) Assert(typeValue builtin_argument.KurtosisValu
 
 	uncastedRecipe, err := receivedReadyConditions.GetRecipe()
 	if assert.Nil(t, err) {
-		castedRecipe, ok := uncastedRecipe.(*recipe.HttpRequestRecipe)
+		castedRecipe, ok := uncastedRecipe.(recipe.HttpRequestRecipe)
 		require.True(t, ok)
 
 		portIdAttrValue, err := castedRecipe.Attr(recipe.PortIdAttr)
@@ -78,7 +73,7 @@ func (t *readyConditionsTestCase) Assert(typeValue builtin_argument.KurtosisValu
 			require.Equal(t, TestReadyConditionsRecipeEndpoint, endpoint.GoString())
 		}
 
-		extractAttrValue, err := castedRecipe.Attr(recipe.ExtractKeyPrefix)
+		extractAttrValue, err := castedRecipe.Attr(recipe.ExtractAttr)
 		if assert.Nil(t, err) {
 			extract, ok := extractAttrValue.(*starlark.Dict)
 			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 65055931b..245181592 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
@@ -6,7 +6,6 @@ import (
 	"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"
 	"testing"
@@ -26,10 +25,6 @@ func (t *serviceConfigFullTestCase) GetId() string {
 	return service_config.ServiceConfigTypeName
 }
 
-func (t *serviceConfigFullTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return service_config.NewServiceConfigType()
-}
-
 func (t *serviceConfigFullTestCase) GetStarlarkCode() string {
 	starlarkCode := fmt.Sprintf("%s(%s=%q, %s=%s, %s=%s, %s=%s, %s=%s, %s=%s, %s=%s, %s=%q, %s=%q, %s=%d, %s=%d, %s=%s)",
 		service_config.ServiceConfigTypeName,
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 86591c9d5..5b171cd5c 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
@@ -4,7 +4,6 @@ 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"
 	"testing"
@@ -24,10 +23,6 @@ func (t *serviceConfigMinimalTestCase) GetId() string {
 	return service_config.ServiceConfigTypeName
 }
 
-func (t *serviceConfigMinimalTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return service_config.NewServiceConfigType()
-}
-
 func (t *serviceConfigMinimalTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%q)",
 		service_config.ServiceConfigTypeName,
diff --git a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/shared_functions_test.go b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/shared_functions_test.go
index 1716ecc93..563683121 100644
--- a/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/shared_functions_test.go
+++ b/core/server/api_container/server/startosis_engine/kurtosis_starlark_framework/test_engine/shared_functions_test.go
@@ -37,7 +37,7 @@ func getCustomReadyConditionsScripPart(
 		portStr,
 		recipe.EndpointAttr,
 		endpointStr,
-		recipe.ExtractKeyPrefix,
+		recipe.ExtractAttr,
 		extractStr,
 		service_config.FieldAttr,
 		fieldStr,
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 4022a2ec4..52b602daa 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
@@ -52,10 +52,14 @@ func TestAllRegisteredBuiltins(t *testing.T) {
 	testKurtosisTypeConstructor(t, newConnectionConfigWithPacketDelayTestCase(t))
 	testKurtosisTypeConstructor(t, newConnectionConfigWithPacketLossTestCase(t))
 	testKurtosisTypeConstructor(t, newExecRecipeTestCase(t))
+	testKurtosisTypeConstructor(t, newGetHttpRequestRecipeNoExtractorTestCase(t))
+	testKurtosisTypeConstructor(t, newGetHttpRequestRecipeTestCase(t))
 	testKurtosisTypeConstructor(t, newNormalPacketDelayDistributionFullTestCase(t))
 	testKurtosisTypeConstructor(t, newNormalPacketDelayDistributionMinimalTestCase(t))
 	testKurtosisTypeConstructor(t, newPortSpecFullTestCase(t))
 	testKurtosisTypeConstructor(t, newPortSpecMinimalTestCase(t))
+	testKurtosisTypeConstructor(t, newPostHttpRequestRecipeTestCase(t))
+	testKurtosisTypeConstructor(t, newPostHttpRequestRecipeMinimalTestCase(t))
 	testKurtosisTypeConstructor(t, newServiceConfigMinimalTestCase(t))
 	testKurtosisTypeConstructor(t, newServiceConfigFullTestCase(t))
 	testKurtosisTypeConstructor(t, newUniformPacketDelayDistributionTestCase(t))
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 7a242e70d..590a6f6a8 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
@@ -4,7 +4,6 @@ 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"
 	"testing"
@@ -24,10 +23,6 @@ func (t *uniformPacketDelayDistributionTestCase) GetId() string {
 	return packet_delay_distribution.UniformPacketDelayDistributionTypeName
 }
 
-func (t *uniformPacketDelayDistributionTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return packet_delay_distribution.NewUniformPacketDelayDistributionType()
-}
-
 func (t *uniformPacketDelayDistributionTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%d)", packet_delay_distribution.UniformPacketDelayDistributionTypeName, packet_delay_distribution.DelayAttr, 110)
 }
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 fb46dfa52..727eaa35e 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
@@ -4,7 +4,6 @@ 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"
 	"testing"
@@ -24,10 +23,6 @@ func (t *updateServiceConfigTestCase) GetId() string {
 	return update_service_config.UpdateServiceConfigTypeName
 }
 
-func (t *updateServiceConfigTestCase) GetTypeConstructor() *kurtosis_type_constructor.KurtosisTypeConstructor {
-	return update_service_config.NewUpdateServiceConfigType()
-}
-
 func (t *updateServiceConfigTestCase) GetStarlarkCode() string {
 	return fmt.Sprintf("%s(%s=%q)", update_service_config.UpdateServiceConfigTypeName, update_service_config.SubnetworkAttr, TestSubnetwork)
 }
diff --git a/core/server/api_container/server/startosis_engine/recipe/http_request_recipe_test.go b/core/server/api_container/server/startosis_engine/recipe/http_request_recipe_test.go
deleted file mode 100644
index 71d3ba35b..000000000
--- a/core/server/api_container/server/startosis_engine/recipe/http_request_recipe_test.go
+++ /dev/null
@@ -1,183 +0,0 @@
-package recipe
-
-import (
-	"github.com/stretchr/testify/require"
-	"go.starlark.net/starlark"
-	"testing"
-)
-
-var (
-	noArgs = starlark.Tuple{}
-)
-
-func TestGetHttpRequestRecipe_String(t *testing.T) {
-	builtin := &starlark.Builtin{}
-	builtin.Name()
-	kwargs := []starlark.Tuple{
-		starlark.Tuple([]starlark.Value{
-			starlark.String(EndpointAttr),
-			starlark.String("?input=output"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(PortIdAttr),
-			starlark.String("portId"),
-		}),
-	}
-	getHttpRequestRecipe, err := MakeGetHttpRequestRecipe(nil, builtin, noArgs, kwargs)
-	require.Nil(t, err, "Unexpected error occurred")
-
-	getHttpRequestRecipeString := getHttpRequestRecipe.String()
-	expectedStringOutput := `GetHttpRequestRecipe(port_id="portId", endpoint="?input=output", extract="")`
-	require.NotNil(t, expectedStringOutput, getHttpRequestRecipeString)
-
-	extractors := starlark.NewDict(1)
-	err = extractors.SetKey(starlark.String("field"), starlark.String(".input.*"))
-	require.Nil(t, err)
-	kwargsWithExtractors := []starlark.Tuple{
-		starlark.Tuple([]starlark.Value{
-			starlark.String(EndpointAttr),
-			starlark.String("?input=output"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(PortIdAttr),
-			starlark.String("portId"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(ExtractKeyPrefix),
-			extractors,
-		}),
-	}
-
-	getHttpRequestRecipeWithExtractors, err := MakeGetHttpRequestRecipe(nil, builtin, noArgs, kwargsWithExtractors)
-	require.Nil(t, err, "Unexpected error occurred")
-
-	getHttpRequestRecipeWithExtractorsString := getHttpRequestRecipeWithExtractors.String()
-	expectedStringOutputWithExtractors := `GetHttpRequestRecipe(port_id="portId", endpoint="?input=output", extract={"field": ".input.*"})`
-	require.NotNil(t, expectedStringOutputWithExtractors, getHttpRequestRecipeWithExtractorsString)
-}
-
-func TestPostHttpRequestRecipe_String(t *testing.T) {
-	builtin := &starlark.Builtin{}
-	kwargs := []starlark.Tuple{
-		starlark.Tuple([]starlark.Value{
-			starlark.String(EndpointAttr),
-			starlark.String("?input=output"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(PortIdAttr),
-			starlark.String("portId"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(bodyKey),
-			starlark.String("body"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(contentTypeAttr),
-			starlark.String("content-type"),
-		}),
-	}
-	postHttpRequestRecipe, err := MakePostHttpRequestRecipe(nil, builtin, noArgs, kwargs)
-	require.Nil(t, err, "Unexpected error occurred")
-
-	postHttpRequestRecipeString := postHttpRequestRecipe.String()
-	expectedStringOutput := `PostHttpRequestRecipe(port_id="portId", endpoint="?input=output", body="body", content_type="content-type", extract="")`
-	require.NotNil(t, expectedStringOutput, postHttpRequestRecipeString)
-
-	extractors := starlark.NewDict(1)
-	err = extractors.SetKey(starlark.String("field"), starlark.String(".input.*"))
-	require.Nil(t, err)
-	kwargsWithExtractors := []starlark.Tuple{
-		starlark.Tuple([]starlark.Value{
-			starlark.String(EndpointAttr),
-			starlark.String("?input=output"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(PortIdAttr),
-			starlark.String("portId"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(ExtractKeyPrefix),
-			extractors,
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(bodyKey),
-			starlark.String("body"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(contentTypeAttr),
-			starlark.String("content-type"),
-		}),
-	}
-
-	postHttpRequestRecipeWithExtractors, err := MakePostHttpRequestRecipe(nil, builtin, noArgs, kwargsWithExtractors)
-	require.Nil(t, err, "Unexpected error occurred")
-
-	postHttpRequestRecipeWithExtractorsString := postHttpRequestRecipeWithExtractors.String()
-	expectedStringOutputWithExtractors := `PostHttpRequestRecipe(port_id="portId", endpoint="?input=output", body="body", content_type="content-type", extract={"field": ".input.*"})`
-	require.NotNil(t, expectedStringOutputWithExtractors, postHttpRequestRecipeWithExtractorsString)
-}
-
-func TestStartosisInterpreter_HttpRequestMissingRequiredFields(t *testing.T) {
-	builtin := &starlark.Builtin{}
-	kwargs := []starlark.Tuple{
-		starlark.Tuple([]starlark.Value{
-			starlark.String(EndpointAttr),
-			starlark.String("?input=output"),
-		}),
-	}
-	getHttpRequestRecipe, err := MakeGetHttpRequestRecipe(nil, builtin, noArgs, kwargs)
-	expectedError := "missing argument for port_id"
-	require.Contains(t, err.Error(), expectedError)
-	require.Nil(t, getHttpRequestRecipe)
-}
-
-func TestStartosisInterpreter_MissingRequiredFieldForHttpRecipeWithPostMethod(t *testing.T) {
-	builtin := &starlark.Builtin{}
-	extractors := starlark.NewDict(1)
-	err := extractors.SetKey(starlark.String("field"), starlark.String(".input.*"))
-	require.Nil(t, err)
-	kwargsWithoutBody := []starlark.Tuple{
-		starlark.Tuple([]starlark.Value{
-			starlark.String(PortIdAttr),
-			starlark.String("portId"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(ExtractKeyPrefix),
-			extractors,
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(contentTypeAttr),
-			starlark.String("content-type"),
-		}),
-	}
-
-	postHttpRequestRecipe, err := MakePostHttpRequestRecipe(nil, builtin, noArgs, kwargsWithoutBody)
-	expectedError := "missing argument for endpoint"
-	require.NotNil(t, err)
-	require.Contains(t, err.Error(), expectedError)
-	require.Nil(t, postHttpRequestRecipe)
-}
-
-func TestHttpRequestRecipe_TestContentIsNotRequiredAndDefaultsToApplicationJson(t *testing.T) {
-	builtin := &starlark.Builtin{}
-	kwargs := []starlark.Tuple{
-		starlark.Tuple([]starlark.Value{
-			starlark.String(EndpointAttr),
-			starlark.String("?input=output"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(PortIdAttr),
-			starlark.String("portId"),
-		}),
-		starlark.Tuple([]starlark.Value{
-			starlark.String(bodyKey),
-			starlark.String("body"),
-		}),
-	}
-	postHttpRequestRecipe, err := MakePostHttpRequestRecipe(nil, builtin, noArgs, kwargs)
-	require.Nil(t, err, "Unexpected error occurred")
-
-	postHttpRequestRecipeString := postHttpRequestRecipe.String()
-	expectedStringOutput := `PostHttpRequestRecipe(port_id="portId", service_name="web-server", endpoint="?input=output", body="body", content_type="application/json", extract="")`
-	require.NotNil(t, expectedStringOutput, postHttpRequestRecipeString)
-}
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 299150065..31ad8fee2 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
@@ -80,28 +80,6 @@ def run(plan):
 	validateScriptOutputFromPrintInstructions(t, instructions, expectedOutput)
 }
 
-func TestStartosisInterpreter_DefineFactAndWait(t *testing.T) {
-	packageContentProvider := mock_package_content_provider.NewMockPackageContentProvider()
-	defer packageContentProvider.RemoveAll()
-	runtimeValueStore := runtime_value_store.NewRuntimeValueStore()
-	interpreter := NewStartosisInterpreter(testServiceNetwork, packageContentProvider, runtimeValueStore)
-	script := `
-def run(plan):
-	get_recipe = GetHttpRequestRecipe(
-		port_id = "http-port",
-		endpoint = "?input=output",
-		extract = {
-			"input": ".query.input"
-		}
-	)
-	response = plan.wait(recipe=get_recipe, field="code", assertion="==", target_value=200, timeout="5m", interval="5s", service_name="web-server")
-	plan.print(response["body"])
-`
-	_, instructions, interpretationError := interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, script, startosis_constants.EmptyInputArgs)
-	require.Nil(t, interpretationError)
-	require.NotEmpty(t, instructions)
-}
-
 func TestStartosisInterpreter_ScriptFailingSingleError(t *testing.T) {
 	packageContentProvider := mock_package_content_provider.NewMockPackageContentProvider()
 	defer packageContentProvider.RemoveAll()
@@ -542,28 +520,6 @@ def run(plan):
 	require.Equal(t, expectedError, interpretationError)
 }
 
-func TestStartosisInterpreter_RequestInstruction(t *testing.T) {
-	packageContentProvider := mock_package_content_provider.NewMockPackageContentProvider()
-	defer packageContentProvider.RemoveAll()
-	startosisInterpreter := NewStartosisInterpreter(testServiceNetwork, packageContentProvider, runtime_value_store.NewRuntimeValueStore())
-	interpreter := startosisInterpreter
-	script := `
-def run(plan):
-	get_recipe = GetHttpRequestRecipe(
-		port_id = "http-port",
-		endpoint = "?input=output",
-		extract = {
-			"input": ".query.input"
-		}
-	)
-	response = plan.request(recipe = get_recipe, service_name = "web-server")
-	plan.print(response["code"])`
-
-	_, instructions, interpretationError := interpreter.Interpret(context.Background(), startosis_constants.PackageIdPlaceholderForStandaloneScript, script, startosis_constants.EmptyInputArgs)
-	require.Nil(t, interpretationError)
-	require.Len(t, instructions, 2)
-}
-
 func TestStartosisInterpreter_ImportingAValidModuleThatPreviouslyFailedToLoadSucceeds(t *testing.T) {
 	packageContentProvider := mock_package_content_provider.NewMockPackageContentProvider()
 	defer packageContentProvider.RemoveAll()