diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml
index cae2c7fe..0b778352 100644
--- a/.github/workflows/develop.yml
+++ b/.github/workflows/develop.yml
@@ -7,6 +7,10 @@ on:
 
 jobs:
   build-test:
+    strategy:
+      fail-fast: false
+      matrix:
+        protocol: [http, non_http]
 
     runs-on:
     - benchmark
@@ -30,6 +34,7 @@ jobs:
 
     - name: Build and Run Tests
       env:
+        TEST_PROTOCOL: ${{ matrix.protocol }}
         AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
         AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
         AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -66,4 +71,3 @@ jobs:
         LENZ_TAG: dev
       run: BUILD_COMPLETE=true ./ci.sh
       shell: bash
-
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 55ed1f1a..dabbdbf0 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -7,6 +7,10 @@ on:
 
 jobs:
   build_and_test:
+    strategy:
+      fail-fast: false
+      matrix:
+        protocol: [http, non_http]
 
     runs-on:
     - benchmark
@@ -30,6 +34,7 @@ jobs:
 
     - name: Build and Run Tests
       env:
+        TEST_PROTOCOL: ${{ matrix.protocol }}
         AWS_ACCESS_KEY_ID:     ${{ secrets.AWS_ACCESS_KEY_ID }}
         AWS_DEFAULT_REGION:    ${{ secrets.AWS_DEFAULT_REGION }}
         AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
index 924ffc88..284be9dc 100644
--- a/.github/workflows/pr.yaml
+++ b/.github/workflows/pr.yaml
@@ -7,6 +7,10 @@ on:
 
 jobs:
   run_test:
+    strategy:
+      fail-fast: false
+      matrix:
+        protocol: [http, non_http]
 
     runs-on:
     - gcp
@@ -34,11 +38,12 @@ jobs:
 
     - name: Build and Run Tests
       env:
+        TEST_PROTOCOL: ${{ matrix.protocol }}
         AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
         AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
         AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
         GCP_SERVICE_ACCOUNT_KEY: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
-        RUNNER_NAME: ${{ runner.name }}
+        RUNNER_NAME: ${{ runner.name }}_${{ matrix.protocol }}
         RUN_TESTS: true
         NO_PUSH: true
         BRANCH_NAME: ${{ github.event.pull_request.head.ref }}
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index c903f5d5..d604b4c1 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -7,6 +7,10 @@ on:
 
 jobs:
   build-test:
+    strategy:
+      fail-fast: false
+      matrix:
+        protocol: [http, non_http]
 
     runs-on:
     - self-hosted
@@ -35,10 +39,12 @@ jobs:
 
     - name: Build and Run Tests
       env:
+        TEST_PROTOCOL: ${{ matrix.protocol }}
         AWS_ACCESS_KEY_ID:     ${{ secrets.AWS_ACCESS_KEY_ID }}
         AWS_DEFAULT_REGION:    ${{ secrets.AWS_DEFAULT_REGION }}
         AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
         GCP_SERVICE_ACCOUNT_KEY: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
+        RUNNER_NAME: ${{ runner.name }}_${{ matrix.protocol }}
       run: RUN_TESTS=true NO_PUSH=true UPDATE_BRANCH=true ./ci.sh
       shell: bash
 
@@ -64,4 +70,4 @@ jobs:
 
     - name: Build Notebook Docker
       run: BUILD_COMPLETE=true NO_PUSH=true ./ci.sh
-      shell: bash
\ No newline at end of file
+      shell: bash
diff --git a/aperturedb/__init__.py b/aperturedb/__init__.py
index 07631782..0b008225 100644
--- a/aperturedb/__init__.py
+++ b/aperturedb/__init__.py
@@ -10,7 +10,7 @@
 import signal
 import sys
 
-__version__ = "0.4.57"
+__version__ = "0.4.58"
 
 logger = logging.getLogger(__name__)
 
diff --git a/ci.sh b/ci.sh
index 3b41ffdc..083a262b 100755
--- a/ci.sh
+++ b/ci.sh
@@ -186,9 +186,9 @@ push_aws_ecr(){
     PREFIX="aperturedata/"
     docker tag ${SRC_IMAGE} \
         684446431133.dkr.ecr.${REGION}.amazonaws.com/${DST_IMAGE}
-    aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin 684446431133.dkr.ecr.${REGION}.amazonaws.com
+    docker run --rm -e AWS_ACCESS_KEY_ID -e AWS_DEFAULT_REGION -e AWS_SECRET_ACCESS_KEY amazon/aws-cli ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin 684446431133.dkr.ecr.${REGION}.amazonaws.com
 
-    aws ecr create-repository --repository-name ${ECR_REPO_NAME} --region us-west-2  || true
+    docker run --rm -e AWS_ACCESS_KEY_ID -e AWS_DEFAULT_REGION -e AWS_SECRET_ACCESS_KEY amazon/aws-cli ecr create-repository --repository-name ${ECR_REPO_NAME} --region us-west-2  || true
 
     docker push 684446431133.dkr.ecr.${REGION}.amazonaws.com/${DST_IMAGE}
 }
diff --git a/robots.md b/robots.md
new file mode 100644
index 00000000..26b73a42
--- /dev/null
+++ b/robots.md
@@ -0,0 +1,69 @@
+# ApertureDB Python Testing Guide
+
+This guide is designed for automated agents and LLMs to quickly understand how to build and run the test suite for `py-aperturedb` locally.
+
+## Prerequisites
+The integration tests rely on local `aperturedb` + `lenz` containers orchestrated by Docker Compose. The environment runs a client container to execute the `pytest` suite against these spun-up backends.
+
+---
+
+## 1. Building the Test Environment Image
+
+To run the tests locally, you first need to build the `aperturedb-python-tests:latest` Docker image. From the workspace root (`/home/remis/src/ad/py-aperturedb`), populate the expected context directory and execute `docker build`:
+
+```bash
+# 1. Provide the expected context data for the test Dockerfile
+mkdir -p test/aperturedb/logs/runner_state
+mkdir -p docker/tests/aperturedata
+
+# 2. Copy the Python source and configurations over
+cp -r aperturedb pyproject.toml README.md docker/tests/aperturedata
+mkdir -m 777 -p docker/tests/aperturedata/test/aperturedb
+
+# 3. Copy test inputs and test scripts over
+cp -r test/*.py test/*.sh test/input docker/tests/aperturedata/test
+
+# 4. Build the test image locally
+docker build -t aperturedata/aperturedb-python-tests:latest -f docker/tests/Dockerfile .
+```
+
+---
+
+## 2. Running the Complete Test Suite
+
+Once the test image is built, use the `run_test_container.sh` wrapper script located in the `test/` directory to coordinate the backend integration environment and run the test suite.
+
+```bash
+cd test
+set -a && source .env && set +a
+bash run_test_container.sh
+```
+
+This script:
+1. Orchestrates spinning up `aperturedb`, `nginx`, `lenz` containers using `docker-compose.yml` on temporary networking bridges.
+2. Starts two parallel test suites (HTTP and non-HTTP modes).
+3. Checks exit codes for successes or failures and cleans up.
+
+---
+
+## 3. Running tests and bypassing AWS/GCP API requirements
+
+A subset of the `pytest` tests interact with external objects, such as fetching blob configurations directly from cloud providers (AWS S3, Google Storage - GS). If your local environment or the automated agent lacks valid AWS/GCP credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `GCP_SERVICE_ACCOUNT_KEY`), you will hit authentication validation errors when resolving `storage.Client()` architectures or boto3 structures during execution.
+
+To dynamically skip external storage tests, you should inform `pytest` running inside the Docker sequence to skip functions interacting with S3 and Google Storage.
+
+Before running the test script, manually modify the `pytest` invocation inside `test/run_test.sh` to explicitly add `-k "not S3 and not GS"` to exclude any specific loading functions targeting S3 or GS, along with keeping away tests appropriately marked with `@pytest.mark.remote_credentials`.
+
+Use this quick `sed` command to patch the exclusion:
+
+```bash
+cd test
+# Modify the pytest invocation to ignore AWS/GCP specific loaders and remotely constrained mark configurations
+sed -i 's/pytest -m "$FILTER"/pytest -k "not test_S3ImageLoader and not test_GSImageLoader and not test_S3VideoLoader and not test_GSVideoLoader" -m "$FILTER and not remote_credentials and not external_network"/' run_test.sh
+
+# Then run the tests as usual
+set -a && source .env && set +a
+bash run_test_container.sh
+```
+
+By applying this change, any LLM/agent can successfully execute internal `aperturedb` connector + python-centric API tests without raising failures tied strictly to external cloud requirements.
diff --git a/test/run_test.sh b/test/run_test.sh
index 93af1096..a4921090 100755
--- a/test/run_test.sh
+++ b/test/run_test.sh
@@ -43,7 +43,7 @@ if [[ $RESULT != 0 ]]; then
 		ARCHIVE_NAME=logs.tar.gz
 		DESTINATION="s3://${BUCKET}/aperturedb-${NOW}-${FILTER// /_}.tgz"
 		tar czf ${ARCHIVE_NAME} ${APERTUREDB_LOG_PATH}/..
-		aws s3 cp ${ARCHIVE_NAME} $DESTINATION
+		docker run --rm -v $(pwd):/workspace -w /workspace -e AWS_ACCESS_KEY_ID -e AWS_DEFAULT_REGION -e AWS_SECRET_ACCESS_KEY amazon/aws-cli s3 cp ${ARCHIVE_NAME} $DESTINATION
 		echo "Log output to $DESTINATION"
 	else
 		echo "Unable to output log, APERTUREDB_LOG_PATH not set."
diff --git a/test/run_test_container.sh b/test/run_test_container.sh
index c51c792f..99e23725 100755
--- a/test/run_test_container.sh
+++ b/test/run_test_container.sh
@@ -30,8 +30,16 @@ function run_aperturedb_instance(){
 
 IP_REGEX='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
 
-GATEWAY_HTTP=$(run_aperturedb_instance "${RUNNER_NAME}_http" | grep $IP_REGEX )
-GATEWAY_NON_HTTP=$(run_aperturedb_instance "${RUNNER_NAME}_non_http" | grep $IP_REGEX )
+# Check if TEST_PROTOCOL is set, otherwise default to both
+TEST_PROTOCOL=${TEST_PROTOCOL:-"both"}
+
+if [ "$TEST_PROTOCOL" == "http" ] || [ "$TEST_PROTOCOL" == "both" ]; then
+    GATEWAY_HTTP=$(run_aperturedb_instance "${RUNNER_NAME}_http" | grep $IP_REGEX )
+fi
+
+if [ "$TEST_PROTOCOL" == "non_http" ] || [ "$TEST_PROTOCOL" == "both" ]; then
+    GATEWAY_NON_HTTP=$(run_aperturedb_instance "${RUNNER_NAME}_non_http" | grep $IP_REGEX )
+fi
 
 # The LOG_PATH and RUNNER_INFO_PATH are set to the current working directory
 LOG_PATH="$(pwd)/aperturedb/logs"
@@ -48,42 +56,57 @@ fi
 
 sleep 20 # wait for the containers to be up and running
 
-echo "running tests on docker image $REPOSITORY with $GATEWAY_HTTP and $GATEWAY_NON_HTTP"
-docker run \
-    -v $(pwd)/output:/aperturedata/test/output \
-    -v $(pwd)/${RUNNER_NAME}_http_ca:/ca \
-    --network=${RUNNER_NAME}_http_default \
-    -v "$LOG_PATH":"${TESTING_LOG_PATH}" \
-    -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
-    -e AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION \
-    -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
-    -e GCP_SERVICE_ACCOUNT_KEY="$GCP_SERVICE_ACCOUNT_KEY" \
-    -e APERTUREDB_LOG_PATH="${TESTING_LOG_PATH}" \
-    -e GATEWAY="nginx" \
-    -e FILTER="http" \
-    $REPOSITORY &
-
-pid1=$!
-docker run \
-    -v $(pwd)/output:/aperturedata/test/output \
-    -v $(pwd)/${RUNNER_NAME}_non_http_ca:/ca \
-    --network=${RUNNER_NAME}_non_http_default \
-    -v "$LOG_PATH":"${TESTING_LOG_PATH}" \
-    -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
-    -e AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION \
-    -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
-    -e GCP_SERVICE_ACCOUNT_KEY="$GCP_SERVICE_ACCOUNT_KEY" \
-    -e APERTUREDB_LOG_PATH="${TESTING_LOG_PATH}" \
-    -e GATEWAY="lenz" \
-    -e FILTER="not http" \
-    $REPOSITORY &
-
-pid2=$!
-
-wait $pid1
-exit_code1=$?
-wait $pid2
-exit_code2=$?
+pid1=0
+pid2=0
+
+if [ "$TEST_PROTOCOL" == "http" ] || [ "$TEST_PROTOCOL" == "both" ]; then
+    echo "running tests on docker image $REPOSITORY with $GATEWAY_HTTP"
+    docker run \
+        -v $(pwd)/output:/aperturedata/test/output \
+        -v $(pwd)/${RUNNER_NAME}_http_ca:/ca \
+        --network=${RUNNER_NAME}_http_default \
+        -v "$LOG_PATH":"${TESTING_LOG_PATH}" \
+        -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
+        -e AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION \
+        -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
+        -e GCP_SERVICE_ACCOUNT_KEY="$GCP_SERVICE_ACCOUNT_KEY" \
+        -e APERTUREDB_LOG_PATH="${TESTING_LOG_PATH}" \
+        -e GATEWAY="nginx" \
+        -e FILTER="http" \
+        $REPOSITORY &
+    pid1=$!
+fi
+
+if [ "$TEST_PROTOCOL" == "non_http" ] || [ "$TEST_PROTOCOL" == "both" ]; then
+    echo "running tests on docker image $REPOSITORY with $GATEWAY_NON_HTTP"
+    docker run \
+        -v $(pwd)/output:/aperturedata/test/output \
+        -v $(pwd)/${RUNNER_NAME}_non_http_ca:/ca \
+        --network=${RUNNER_NAME}_non_http_default \
+        -v "$LOG_PATH":"${TESTING_LOG_PATH}" \
+        -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
+        -e AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION \
+        -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
+        -e GCP_SERVICE_ACCOUNT_KEY="$GCP_SERVICE_ACCOUNT_KEY" \
+        -e APERTUREDB_LOG_PATH="${TESTING_LOG_PATH}" \
+        -e GATEWAY="lenz" \
+        -e FILTER="not http" \
+        $REPOSITORY &
+    pid2=$!
+fi
+
+exit_code1=0
+exit_code2=0
+
+if [ "$pid1" != "0" ]; then
+    wait $pid1
+    exit_code1=$?
+fi
+
+if [ "$pid2" != "0" ]; then
+    wait $pid2
+    exit_code2=$?
+fi
 
 if [ $exit_code1 -ne 0 ]; then
     echo "Tests failed for HTTP"
@@ -94,7 +117,6 @@ if [ $exit_code2 -ne 0 ]; then
     exit $exit_code2
 fi
 
-
 echo "Tests completed"
 echo " --- Runner name: ${RUNNER_NAME} ---"
 check_containers_networks
