Test storage automations locally
Watch a local directory with the Tilebox CLI, register a Python storage-event automation, and trigger a job by writing a file.
Use a local storage location to test storage-event automations without configuring a cloud bucket or cloud notifications. The CLI watches a directory and sends events to Tilebox. A Python runner on the same machine reads the files and executes the triggered tasks.
Local storage locations also work for processing files locally. Files stay on your machine, while Tilebox coordinates the jobs. The watcher and runner need a connection to Tilebox.
Prerequisites
- Install the Tilebox CLI and uv.
- Set up authentication. The CLI and Python SDK both use
TILEBOX_API_KEY; saving it in your shell configuration makes it available in new terminals.
Create a project
The shell examples use Bash. Create a project and install the Python workflow SDK:
mkdir local-storage-test
cd local-storage-test
uv init --no-package
uv add tilebox-workflows
mkdir inputRegister and watch the directory
Register input as a local storage location:
tilebox storage-location create local --path ./input --name "Local automation test"Copy the returned location ID. Replace <storage-location-id> with it throughout this guide. The CLI resolves --path to an absolute path, so the registered location does not depend on the watcher’s working directory.
Start the watcher in this terminal:
tilebox storage-location watch <storage-location-id>Wait for the Watching ... message and leave the command running.
The watcher reports new and modified files in the directory and its subdirectories after one second without changes. Existing, unchanged files are not sent when it starts. It respects .gitignore rules by default; use --no-gitignore to include ignored files.
Define the Python task
Open a second terminal in local-storage-test. Save this as local_automation.py:
from tilebox.workflows import Client, ExecutionContext, Runner
from tilebox.workflows.automations import StorageEventTask
class ReadFile(StorageEventTask):
def execute(self, context: ExecutionContext) -> None:
path = self.trigger.location
data = self.trigger.storage.read(path)
context.logger.info(
"Read file",
path=path,
size_bytes=len(data),
)
if __name__ == "__main__":
client = Client()
runner = Runner(tasks=[ReadFile])
runner.connect_to(client).run_forever()self.trigger.location is relative to the registered directory, for example hello.txt or nested/hello.txt, without a leading /. self.trigger.storage.read() returns the file’s bytes. The task logs its path and size, so it works with text, images, and other binary files.
Register the automation
Save this second file beside local_automation.py:
import sys
from uuid import UUID
from tilebox.workflows import Client
from local_automation import ReadFile
client = Client()
automations = client.automations()
location_id = UUID(sys.argv[1])
location = next(
location
for location in automations.storage_locations()
if location.id == location_id
)
automation = automations.create_storage_event_automation(
"read-local-files",
ReadFile(),
triggers=[(location, "**")],
)
print(f"Automation ID: {automation.id}")Select the location by the ID returned by the CLI, then register the automation once:
uv run python register_automation.py <storage-location-id>Save the printed automation ID for cleanup. Register once: each run creates a new automation.
The pattern ** matches all files in the directory and its subdirectories. To process only text files, use **.txt. See glob patterns for the syntax, examples, and an online way to test them.
Start the runner
In the second terminal, start the task runner:
uv run python local_automation.pyLeave it running alongside the watcher on the same machine. Both the automation and this runner use the default cluster. Storage reads use the registered absolute path, so the runner does not need to start in the watched directory. The command above runs from the project directory so uv can find the Python environment and script.
Trigger an event and inspect the job
Open a third terminal in local-storage-test. With both the watcher and runner running, create a matching file:
echo "Hello from local storage" > input/hello.txtAfter the file has been unchanged for a second and the notification is delivered, the watcher prints:
Event: hello.txtThe runner should log Read file with path=hello.txt and size_bytes=25. You can also copy an image or another file into input to trigger a job. Check the received event and its triggered jobs:
tilebox storage-location events <storage-location-id> --limit 10 --jsonFind object_key: "hello.txt" and copy a job_id from triggered_jobs. Inspect the job in the Console or read its logs:
tilebox job logs <job-id>To trigger another event, modify the file after the first event has arrived:
echo "A second update" >> input/hello.txtIf no event appears, check that the watcher is still running, the file is inside the registered directory, and no .gitignore rule excludes it. If the event has no triggered jobs, check the automation’s location ID and glob. If a job stays queued or fails, check the runner’s cluster and access to the directory.
Stop the test
Press Ctrl+C in the watcher and runner terminals.
In the Console’s Automations page, delete read-local-files. Use the ID printed during registration to identify it if you have several automations with that name. You can keep the location for another test if you want.
Use the same task with cloud storage
The same StorageEventTask works with local storage, AWS S3, Google Cloud Storage, and Azure Blob Storage. To use ReadFile with a cloud location, connect the bucket or container, then register an automation with that location’s ID. Configure the runner’s cloud credentials so self.trigger.storage.read() can read the objects. Cloud notifications replace the local CLI watcher; the task code stays the same.