Skip to content

Repository files navigation

Omni Tool Runtime

Portable, cloud-agnostic execution runtime for OmniBioAI tools


Overview

omnibioai-tool-runtime is a minimal, deterministic execution runtime used by OmniBioAI’s Tool Execution Service (TES) to run individual tools across multiple execution backends, including:

  • Local Docker execution
  • AWS Batch
  • Azure Batch
  • GCP Batch (gs:// results upload)
  • Kubernetes Jobs
  • Slurm / HPC via TES adapters

The runtime provides a strict execution contract so that:

  • TES adapters stay thin and backend-specific
  • Tool containers remain portable and backend-agnostic
  • Results are uploaded consistently (S3 / Azure Blob / future backends)

This mirrors the design philosophy used throughout OmniBioAI: separate orchestration from execution, and execution from logic.


What This Runtime Is (and Is Not)

✅ This runtime is

  • A containerized tool launcher

  • Responsible for:

    • Reading tool inputs from environment variables
    • Executing tool logic
    • Writing results.json
    • Uploading results to cloud storage
  • Cloud-agnostic (AWS / Azure supported today)

❌ This runtime is not

  • A workflow engine
  • A scheduler
  • An LLM executor
  • A UI layer

Those responsibilities live elsewhere in OmniBioAI.


Execution Contract (Critical)

All tools executed via omnibioai-tool-runtimemust follow this contract.

Environment Variables (Injected by TES Adapter)

VariableDescription
TOOL_IDTool identifier (echo_test, blastn, etc.)
RUN_IDUnique run ID (generated by adapter)
INPUTS_JSONJSON-encoded tool inputs
RESOURCES_JSONJSON-encoded resource request
S3_RESULT_URI(AWS Batch) S3 URI to upload results
RESULT_URI(Azure Batch) azureblob:// URI to upload results

Only one of S3_RESULT_URI or RESULT_URI is expected per run.


Repository Structure

omnibioai-tool-runtime/
├── Dockerfile
├── README.md
├── pyproject.toml
├── omni_tool_runtime/
│ ├── __init__.py
│ ├── contract.py # ToolContract + read_contract_from_env() —
│ │ # the code implementing "Execution Contract" below
│ ├── run.py # Generic entrypoint: resolves TOOL_ID ->
│ │ # tools.{tool_id}.run and calls its main()
│ ├── result_uri.py # URI parsing & dispatch
│ ├── upload_result.py # Unified upload logic
│ └── uploaders/
│ ├── s3_uploader.py
│ └── azureblob_uploader.py
├── tools/
│ ├── echo_test/ # Minimal reference implementation — see below
│ │ ├── __init__.py
│ │ └── run.py
│ ├── generic_sif_runner/ # The real, production tool — embedded in every
│ │ └── run.py # ECR/ACR/GCR image (see omnibioai-tes's README)
│ └── workflow_runner/
│ └── run.py
└── tests/

Testing

cd~/Desktop/machine/omnibioai-tool-runtime
pytest tests/ -v --cov=.
# 99% coverage (verified 2026-08-07; 371 tests. Two lines in# generic_sif_runner/run.py are the only gap)# Covers: upload_result, S3 uploader, Azure uploader,# echo_test/generic_sif_runner/workflow_runner tools, run lifecycle

Example Tool: echo_test

This is a minimal reference implementation — small enough to read end-to-end as a template for a new tool. The real, production tool embedded in every ECR/ACR/GCR image is tools/generic_sif_runner/ (see omnibioai-tes's README); a third, tools/workflow_runner/, also ships here.

Behavior

  • Reads INPUTS_JSON
  • Echoes a value
  • Writes results.json
  • Uploads results to configured storage backend

Minimal tool implementation

# tools/echo_test/run.pyimportjsonimportosfromomni_tool_runtime.upload_resultimportupload_resultdefmain():
tool_id=os.environ["TOOL_ID"]
run_id=os.environ["RUN_ID"]
inputs=json.loads(os.environ.get("INPUTS_JSON", "{}"))
text=inputs.get("text", "")
result= {
"ok": True,
"tool_id": tool_id,
"run_id": run_id,
"results": {"echo": text},
}
upload_result(result)
if__name__=="__main__":
main()

How Results Upload Works

upload_result() automatically detects the backend:

BackendURI Example
AWSs3://bucket/prefix/run_id/results.json
Azureazureblob://account/container/path/results.json
GCPgs://bucket/prefix/run_id/results.json (via google.cloud.storage)

The runtime:

  1. Serializes result as JSON
  2. Uploads to correct backend
  3. Prints result to stdout (for debugging)

Adapters never upload results themselves.


Building the Docker Image

From repository root:

# Build from ecosystem root (required — COPY needs omnibioai-tool-runtime/)cd~/Desktop/machine
docker build \
-t ghcr.io/omnibioai/omnibioai-tool-runtime:latest \
-f omnibioai-tool-runtime/Dockerfile \
.
docker push ghcr.io/omnibioai/omnibioai-tool-runtime:latest

Verify:

docker images | grep omnibioai-tool-runtime

Running a Tool Locally (No Cloud)

docker run --rm \
-e TOOL_ID=echo_test \
-e RUN_ID=local-test-1 \
-e INPUTS_JSON='{"text":"hello world"}' \
-e RESOURCES_JSON='{}' \
ghcr.io/omnibioai/omnibioai-tool-runtime:latest

Expected:

  • JSON output printed to stdout
  • No upload attempted if no result URI is provided

AWS Batch Usage

Job Definition

  • Image: ghcr.io/omnibioai/omnibioai-tool-runtime:latest
  • Command override:
["python", "-m", "tools.echo_test.run"]

Injected Environment

  • S3_RESULT_URI provided by AwsBatchAdapter
  • IAM Role handles S3 auth

Azure Batch Usage

Task Settings

  • Image: ghcr.io/omnibioai/omnibioai-tool-runtime:latest
  • Command:
python -m tools.echo_test.run

Injected Environment

  • RESULT_URI=azureblob://...
  • Managed Identity handles Blob auth

Pushing the Image

Docker Hub

docker push ghcr.io/omnibioai/omnibioai-tool-runtime:latest

Azure Container Registry

az acr login --name YOUR_ACR
docker tag ghcr.io/omnibioai/omnibioai-tool-runtime:latest YOUR_ACR.azurecr.io/omnibioai-tool-runtime:latest
docker push YOUR_ACR.azurecr.io/omnibioai-tool-runtime:latest

Adding a New Tool

Step 1: Create tool folder

mkdir tools/my_new_tool
touch tools/my_new_tool/__init__.py
touch tools/my_new_tool/run.py

Step 2: Implement run.py

Rules:

  • Must read env vars
  • Must write result via upload_result()
  • Must be deterministic

Step 3: Register tool in adapter config

AWS Batch

job_definition_map:
my_new_tool: "omnibioai-my-new-tool:1"

Azure Batch

tools:
my_new_tool:
image: "ghcr.io/omnibioai/omnibioai-tool-runtime:latest"command: ["python", "-m", "tools.my_new_tool.run"]

Current State

Implemented

  • Unified runtime image embedded in all tool Docker images
  • AWS Batch support (S3 result upload)
  • Azure Batch support (Azure Blob result upload)
  • GCP Batch support (GCS result upload)
  • Kubernetes Job support — the same image runs unmodified as a K8s Job's container; no Kubernetes-specific code lives in this repo
  • Deterministic execution contract
  • Reference echo_test tool, plus the production generic_sif_runner and workflow_runner tools
  • 99% test coverage

Intentionally not included (by design)

  • No workflow orchestration
  • No retry logic
  • No state machine
  • No scheduling policy

Design Philosophy (Important)

This runtime is intentionally boring.

That’s a feature.

  • No magic
  • No backend assumptions
  • No hidden orchestration
  • One job → one tool → one result

Everything complex belongs above this layer.


Related Services

ServiceRole
omnibioai-tesInjects env vars and submits jobs using this runtime
omnibioai-tool-imagesEmbeds this runtime in every tool Docker image
omnibioai-studioOrchestrates execution backends that run this runtime

Final Note

If this runtime feels similar to:

  • CWL CommandLineTool
  • TES task containers
  • AWS Batch single-purpose images

That’s intentional.

You’re building the correct abstraction boundary.

About

Minimal cloud-agnostic container execution runtime for the OmniBioAI Tool Execution Service — enforces a strict input/output contract for tools running on AWS Batch, Azure Batch, and Kubernetes. Handles environment injection, output collection, and exit-code-based status reporting with no cloud-specific dependencies in tool images.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages