Feature

A Python SDK with two decorators

Load your model once, handle jobs one after the other. runqy-python turns a plain Python script into a worker process, with no framework to learn and no config file in your code.

pip install runqy-python

A complete worker

# main.py
import torch
from diffusers import StableDiffusionXLPipeline
from runqy_python import load, task, run

@load
def setup():
    pipe = StableDiffusionXLPipeline.from_pretrained(
        "stabilityai/stable-diffusion-xl-base-1.0",
        torch_dtype=torch.float16,
    ).to("cuda")
    return {"pipe": pipe}

@task
def generate(payload, ctx):
    image = ctx["pipe"](payload["prompt"]).images[0]
    url = upload(image)  # your storage
    return {"url": url}

if __name__ == "__main__":
    run()
@load

Runs once when the process starts. Load models, open connections; the return value becomes ctx.

@task

Runs for each job with its JSON payload and ctx. Return a dict for the result; raise to fail and retry.

@reload

Optional. Reloads configuration between tasks when the worker receives config-reload, without reloading models.

run() / run_once()

run() keeps the process alive and loops over tasks. run_once() handles one task per process.

Two execution modes

long_running

One process stays alive and handles every task. The model loads once. Built for GPU inference: image generation, LLMs, embeddings.

one_shot

A fresh process per task, with run_once(). Nothing leaks from one job to the next. Built for scripts, scraping and conversions.

Enqueue from Python

The same package ships a client for your application. Other languages use the REST API.

from runqy_python import RunqyClient

client = RunqyClient("https://runqy.example.com", api_key="client-key")

task = client.enqueue("images.premium", {"prompt": "a fox in the snow"})
result = client.get_task(task.task_id)
print(result.state, result.result)

# Many jobs in one request
client.enqueue_batch("images.standard", [{"prompt": p} for p in prompts])

Not only Python

Under the SDK is a small protocol: the worker writes one JSON task per line to your process's stdin and reads one JSON response per line from its stdout. Any program that speaks it can be a runqy worker, in Go, Node.js or anything else.

← {"status": "ready"}
→ {"task_id": "abc123", "payload": {"prompt": "a fox"}}
← {"task_id": "abc123", "result": {"url": "..."}, "error": null, "retry": false}

Read the guides