Skip to content

Tasks

Run a Python script or a whole project folder to completion on a matched GPU or CPU node — submit code, pick an image and hardware, stream the logs, and download the output files.

A task runs a Python script — or a whole project folder — once, to completion, on a node matched to the hardware you pick. You submit the code, an image, and the hardware — Meshive schedules it, streams the logs live, uploads whatever the program writes to /outputs, and charges your prepaid credit only for the time the container actually ran.

Script (main.py + optional requirements.txt)
or Project (folder or .zip, uploaded to Assets)
│ Submit — image + hardware + max run time
▼
Runs on a matched node ──▶ logs stream live in the console
│ program exits (or hits max run time)
▼
Files in /outputs uploaded ──▶ download from the console

Everything lives under Serverless › Tasks in your workspace console.

Serving keeps a model resident behind an always-on endpoint. Tasks run a script and stop.

ServingTasks
What runsA model behind an OpenAI-compatible endpointYour Python script, once
LifetimeUntil you pause or delete itUntil the script exits (or max run time)
You get backAPI responsesLive logs + files from /outputs
BillingGPU-hour × running replicasRuntime of the container, from prepaid credit

Typical task workloads: batch inference over a dataset, fine-tuning a model, data preprocessing — anything with a start and an end.

  1. Open Serverless › Tasks in your workspace console and click Submit task.

  2. Name the task.

  3. Add your code — the Script card has a Script | Project switch:

    • Script — write one file in the code editor, or click Open file to load a .py from your computer. An optional requirements.txt goes under the editor (see below).
    • Project — drop a project folder or a .zip on the card, then pick the file to run (see Run a project).

    You can also drop straight onto the Script card: one .py loads into the editor, and a folder or a .zip switches the card to Project. Whatever you type under Arguments is passed to your program as command-line arguments.

  4. Input assets (optional) — attach assets from your workspace; each one lands at /inputs/<name>. Files that aren’t in Assets yet can be uploaded right there: drop files or a folder on the Input assets card, or use Upload new in the Add assets dialog (see Upload and attach in one step).

  5. Pick an image — an official template, or your own image from a custom registry (see Container images).

  6. Pick hardware — a GPU model and count, or a CPU-only preset:

    PresetvCPURAM
    Micro28 GiB
    Small416 GiB
    Standard832 GiB
    Balanced1664 GiB
    Compute816 GiB
    Compute L1632 GiB
    Compute XL3264 GiB
    Compute 2XL64128 GiB
    Compute 3XL96192 GiB
    Compute 4XL128256 GiB
    High-mem864 GiB
    High-mem XL16128 GiB

    A preset with no node able to host it right now is shown as Unavailable.

  7. Environment & secrets (optional) — available to your script as regular env vars. To bring in many at once, paste KEY=VALUE lines or drop a .env file on the card (see Import environment variables). Your script can also read its task ID from MESHIVE_SYS_TASK_ID (the older MESHIVE_TASK_ID holds the same value for now). Names starting with MESHIVE_SYS_ and a few other names Meshive sets in the container can’t be used — the form flags them as you type. Any other name, including other MESHIVE_ names, is yours to use.

  8. Max run time — 1 to 24 hours. The task is stopped when it hits this ceiling (see Task billing & refunds).

  9. Completion webhook (optional) — get a signed POST when the task finishes (see Webhooks).

  10. Click Submit task. The task card shows the live status, streaming logs, and Cost so far. While a project or an input asset is still uploading, the button stays off and the Run summary says what it’s waiting for — click it again once the upload has finished.

You can Stop a running task at any time — you’re charged for the time it actually ran, and no webhook event is sent for a manual stop.

If you attach a requirements.txt, pip install -r requirements.txt runs inside the container, before your script starts.

In Project mode this editor is called Extra packages. Those are installed first, then the requirements file you chose for the project under Install requirements from (see Run a project).

A single file is enough for many jobs. When your code is a folder — several modules, config files, a training repo — switch the Script card to Project and run it as it is, instead of pasting everything into one file.

Drop a project folder or a .zip on the Script card, or click Choose folder or Choose .zip. A GitHub Download ZIP works as it is: the top-level folder inside it becomes the project name.

  • One asset, uploaded for you. The console uploads the project to Assets as one asset and attaches it to the task as an input, so it counts toward the 20-input limit. The upload starts as soon as you drop, while you fill in the rest of the form.
  • Submit waits for the upload. Submit task stays off until the upload has finished — it doesn’t submit by itself, so click it again afterward. If the upload fails, Retry is on the project row.
  • It stays in Assets. The project is an ordinary asset in managed storage, billed as storage like any other upload until you delete it. Dropping the same folder again uploads another copy (-2, -3, and so on).
  • Replace or Remove on the project row swaps or drops it. Switching between Script and Project keeps what you entered in both.

What the console leaves out. It tells you what it skipped under the project row, for example Skipped .git, __pycache__ (1,204 files).

Left outWhy
Version control, caches and tool folders — .git (and .hg, .svn), __pycache__ and *.pyc, node_modules, .ipynb_checkpoints, .mypy_cache, .pytest_cache, .ruff_cache, .tox, .nox, .idea, .vscode, *.egg-infoRebuilt or irrelevant at run time, and often thousands of files
Virtual environments — .venv, venv, and any folder that contains a pyvenv.cfg, whatever its nameInstall packages with a requirements file instead
Experiment logs — wandb, mlruns, lightning_logsOutput, not code
Operating-system leftovers — .DS_Store, __MACOSX, ._*, Thumbs.db, desktop.iniNoise
.env and .env.* files (but not .env.example and the like)Assets aren’t encrypted and are visible in Assets, so secrets stay out. The console offers to load them into Environment & secrets instead — see below
Empty files, except empty .py files such as __init__.py (and py.typed, .gitkeep)Assets can’t hold empty files; an empty __init__.py is kept because it makes a folder a package

Other folders — data, build, dist, env — are uploaded like any other, so keep large datasets out of the project and attach them as input assets.

A .env file in the project. The console doesn’t upload it. Under the project row, Load into Environment & secrets reads it into the rows of that card (with several .env files, there is one Load button for each) and tells you where the variables went. Because the variables are then set in the container, code that calls python-dotenv’s load_dotenv() keeps working without the file.

File count. A task can fetch about 500 files in total at run time, counting the project and the files of the input assets you attach. Linked sources (Hugging Face, CivitAI, URLs) and bucket references aren’t counted. Over the limit, the console names the three folders with the most files and offers a Skip button for each. Many small files are better packed into one archive that your program unpacks.

A .zip is unpacked in your browser. One that is password-protected, uses non-UTF-8 file names, or unpacks to more than about 2 GiB can’t be opened that way — unzip it and drop the folder instead.

Once the project is on the card, set:

  • Run — the .py file to execute. The console picks a top-level main.py, train.py, run.py or __main__.py for you, the only candidate left once files like setup.py, conftest.py and test_*.py are set aside, or the only file with one of those names anywhere in the project (such as mypkg/train.py). When it can’t tell, the field is empty and the form asks you to Choose the file to run.
  • Install requirements from — a requirements*.txt in the project. A top-level requirements.txt is chosen by default; choose None to skip installing.
  • Extra packages (optional) — requirements.txt lines installed before the project’s own requirements file, for a package you don’t want to add to the repository.
  • Arguments (optional) — passed to the file as command-line arguments.

Under these fields the console shows the exact commands that will run, such as pip install -r requirements.txt followed by python -m mypkg.train. The Run summary’s Entrypoint row shows the same command.

The project is downloaded like any input asset — that download time is billed — and then:

  1. It’s copied into a working folder, so the program can write next to its code. Very large files (~64 MiB and up) are linked read-only instead of copied, so big weights inside a project aren’t stored twice; they can be read but not changed in place.
  2. The working directory is the project folder, so relative paths such as data/train.csv or configs/base.yaml work, and sibling modules import as usual. This differs from Script mode, where the working directory is /outputs.
  3. Requirements are installed. Extra packages first, then pip install -r <file> from the project folder. Install time is billed, and a failed install ends the task as a user fault — see requirements.txt.
  4. The entry file runs as python path/to/file.py. When the file sits in a package — every folder from the project root down to it has an __init__.py — it runs as python -m pkg.module instead, so relative imports such as from .utils import load work, and sibling modules imported by plain name (import utils) are still found. A file at the top level always runs as a plain script, and __init__.py can’t be chosen — add a __main__.py to run a package. If your code starts Python again itself with python -m (some multi-GPU launchers do), import sibling modules through the package (from pkg import utils) in those processes.
  5. New files are collected. When the program exits, files it newly created inside the project folder are moved to /outputs at the same relative path and uploaded with the rest of the outputs. Changes to files that came with the project aren’t collected. If moving them would pass the 200-file output limit, nothing is moved and the log lists what wasn’t saved.

The task page shows the project instead of the code: its name with Open in Assets, the command, and the requirements file. Re-run with same config (and Re-run on the task list) attaches the same project and input assets again, after checking they still exist.

The project isn’t uploaded again, so edits on your computer aren’t picked up — drop the folder again to run the new version. If the project asset has been deleted since, the form says so and asks you to drop the folder again.

Instead of typing each row in Environment & secrets, bring in a whole set of variables:

  • Paste into a name field. Paste KEY=VALUE lines, JSON or YAML into the name of a row and it expands into one row per variable.
  • Paste into a value field. Paste a block of several KEY=VALUE lines. A single-line value is never split, so a value that contains =, like a base64 string or a URL, stays as you typed it.
  • Drop a file. Drop a file anywhere on the card.
  • Click Import from file and choose a file (up to 1 MiB).

A line under the card sums up the result, for example “Imported 5 variables · 1 replaced · 2 marked secret · 1 line skipped”.

  • Existing names are replaced. A name that is already a row gets the new value; the other names are added as new rows. If a name appears twice in the pasted text, the last one wins.
  • Secret-looking names come in as Secret. A name containing TOKEN (as a whole word, so MAX_TOKENS is left alone), SECRET, PASSWORD, API_KEY, ACCESS_KEY, PRIVATE_KEY or CREDENTIAL is imported as a Secret. It’s a guess from the name only: click the Variable or Secret pill on a row to change it.
  • Values come in as written. Wrapping quotes are removed, but ${VAR}, $(command) and %VAR% are not expanded. Numbers and booleans become text.
  • A file with several sets of variables asks which one you want. Two Compose services or two Kubernetes containers are never merged silently: pick one, or All, where a name that appears twice takes the later value.
  • Kubernetes secrets are decoded. Values under data are decoded from base64 and come in as secrets, along with stringData. valueFrom entries have no value to import, so they’re skipped.

The format is recognized from the content, so the file name doesn’t matter:

FormatWhat’s understood
.envKEY=value, KEY: value, # comments, "double" quotes with \n escapes and multi-line values, 'single' quotes
Shellexport KEY=value (several on a line), .envrc, fish set -x, csh setenv
WindowsPowerShell $env:KEY = "value", set KEY=value, set "KEY=value", setx
JSONAn object, a list of {"name": …, "value": …} or "KEY=value" strings, comments and trailing commas (launch.json), AWS SAM env.json, ECS task definitions
YAMLPlain maps, Docker Compose, Kubernetes env, ConfigMaps and Secrets, GitHub Actions env, serverless.yml, App Engine env_variables
TOMLwrangler.toml, fly.toml, netlify.toml, Cargo [env], mise
OtherJava .properties, INI, systemd Environment=, Dockerfile ENV, two columns pasted from a spreadsheet
  • Lines that aren’t valid variable names are skipped and counted. The usual limits and reserved names still apply.

The same import works in a Pod’s or template’s Environment variables section: names that match a variable the template already defines fill in its value, and names that look secret are added as secret variables.

SourceRequirements
Official templateNone — guaranteed to work with tasks out of the box
Custom registry imageMust have python (with pip, if you use requirements.txt) on the PATH

A custom image without a working python fails at startup — that’s a user fault and is charged like any other user-code failure. Test the image locally first: docker run --rm <image> python --version.

Private registries use the registry credentials already connected to your workspace — the same ones used for custom pod templates.

Anything your program writes to /outputs is uploaded automatically after the container exits and becomes downloadable from the task’s page in the console. In Script mode your script also starts with /outputs as its working directory; in Project mode the working directory is your project folder instead.

  • Script mode: relative writes (open("result.csv", "w")) already land in /outputs — no path handling needed.
  • Project mode: relative writes land in the project folder, and files that are new there are moved to /outputs when the program exits. Write to /outputs/... explicitly for anything that must survive a Stop or a max run time.
  • _task.log is added automatically: a tail of the run’s log, archived alongside your files.
  • To keep only some of the files, choose them in the Output card of the submit form — see Choosing which files to save. By default everything is kept.
  • When the run ends, everything in /outputs (or only the files you chose to save) becomes an asset in your workspace — kept until you delete it, and billed as storage if it lives in managed storage. Each run becomes its own asset — re-running the task creates a new one (-2, -3, and so on). Only _task.log follows the log retention policy.
  • The upload resumes after interruptions and retries automatically for up to ~3 days; its progress and state are shown on the task page. If you don’t need the files, Discard outputs on the task page stops the transfer and releases the storage.
Output limitValue
Max size per file5 GiB
Max number of files200
Output disk budget20 GiB

In the Output card, click All files next to /outputs. Turn on any mix of Images, Videos, Model files and Data & logs, add your own patterns, or type a path under Check a path to see whether it would be saved. The example tree under /outputs marks what each choice keeps.

Your own patterns are globs, the same syntax as watched-folder include rules. Only files under /outputs that match are uploaded; the rest are deleted when the task ends. From code, pass the patterns as output_include (SDK and MCP) or --output-include (CLI).

PatternSaves
*.safetensorsEvery .safetensors file, in any subfolder
samples/*.pngPNGs directly inside samples/ — not in its subfolders
samples/**/*.pngPNGs anywhere under samples/
checkpoints/Every folder named checkpoints, at any depth, with everything inside (/checkpoints/ only the one at the top)
  • Patterns are relative to /outputs: write samples/*.png, not /outputs/samples/*.png or ./samples/*.png.
  • A pattern that matches a folder saves everything inside it. out/* also matches the folder out/sub, so it saves all of out.
  • Matching is case-sensitive (*.png doesn’t match A.PNG). Brackets and braces ([abc], {png,jpg}) aren’t supported — add one pattern per alternative (*.png, *.jpg) and use ? for a single character. Separate folders with /, not \. A leading ! is reserved.
  • In the submit form you can type several patterns separated by commas. From code, pass a list (or repeat --output-include) — there a comma is part of the pattern.
  • _task.log is still added.
  • Files you don’t save still take up /outputs while the task runs — they count toward the output disk budget, and toward the disk charge where /outputs is billed as a volume. They are deleted, not uploaded, when the task ends.
  • If no file matches, the task still succeeds and no output asset is created; the task page shows that nothing matched the filter.
  • The file-count limit applies to the files that match.

A task gets the same disk a pod does: it’s ephemeral (wiped when the task ends) and split into two parts, both counted against one on-node budget.

  • System storage — the container’s working space for package installs, model/HF caches, temp files, and logs. It’s sized automatically from your hardware, the same formula a GPU or CPU pod uses:
    • GPU: max(15 + 10 × GPU count, 5) GiB
    • CPU: max(5 + 1 × vCPU, 5) GiB
  • /outputs — a separate 20 GiB budget for the files you want back (see above).

The submit form shows both numbers for your selected hardware (e.g. a single 24 GB GPU → 25 GiB system + 20 GiB /outputs = 45 GiB total).

Add a webhook to be notified when a task reaches a terminal state:

EventWhen
task.succeededScript exited with code 0
task.failedScript failed — non-zero exit, OOM, eviction, install failure, or a platform fault
task.timed_outMax run time reached
task.outputs_readyEvery output file has finished saving to Assets. Fires after the terminal event — outputs can still be uploading when task.succeeded arrives.

Terminal states only (plus task.outputs_ready once the outputs land). A manual Stop sends no event.

The payload envelope matches inference webhooks:

{
"id": "evt_3f9c1a2b4d5e6f70",
"type": "task.succeeded",
"created_at": 1780000000,
"data": {
"id": "task_abc123",
"name": "nightly-batch-embed",
"status": "succeeded",
"fault_class": "none",
"exit_code": 0,
"failure_reason": null,
"namespace_name": "my-workspace",
"gpu_model": "RTX 4090",
"created_at": 1779996400,
"finished_at": 1779999998,
"total_cost": "0.42000000"
}
}
  • fault_class — none (succeeded), user, or platform. This is what decides whether anything is refunded.
  • total_cost — the final, trued-up charge in credit.
  • Terminal payloads also carry output_upload_state — where the output transfer stands at that moment. Wait for task.outputs_ready before fetching files programmatically.

Deliveries carry the same X-Meshive-Signature HMAC header as every other Meshive webhook — verify it exactly as described in Webhooks → Verifying the signature. Retries, idempotency (dedupe on the event id), and security rules are also identical.

No webhook, or one that can’t be reached? You get an email. When a task has no webhook for its event — no webhook_url on the task and no workspace endpoint subscribed to that event — the person who submitted it gets one email when it succeeds, fails, times out, or is stopped because the credit balance ran out. If the task has webhooks but none of them accepted the event after all retries, the same email goes out with the reason the delivery failed. A task you stop yourself sends no email.

LimitValue
Max run time1 – 24 hours
Script + requirements.txt size~960 KiB combined (a project’s files are not counted — they’re uploaded to Assets)
Input assetsUp to 20 per task; a project counts as one
Files fetched at run time~500 across the project and its input assets
Environment variablesUp to 64, ~32 KiB total
GPUs per taskUp to 8
Concurrent tasksNo cap — every task is paid
Output files5 GiB / file · 200 files · 20 GiB total