Docs

Builds and runtime

How a push becomes a deploy: Python version, dependencies, system packages, subfolders and the sandbox each run gets.

Every push to a connected branch builds the repo into an image and deploys every @deploy function in it. You can follow each build's log on the project page, and roll a function back to an earlier deploy.

What a build does

  1. Clones the commit.
  2. Installs system packages from apt.txt, if there is one.
  3. Installs Python and your dependencies.
  4. Imports every module that uses callables, and reads the functions and their type hints.
  5. Publishes the functions. If any module fails to import, nothing is published and the previous deploy stays live.

Run call check before pushing to catch the problems a build would hit.

Python version

Taken from .python-version (such as 3.13). Without one, the newest version your pyproject.toml requires-python allows. Otherwise 3.12. Supported: 3.11 to 3.14.

Python dependencies

From requirements.txt at the repo root, or [project].dependencies in pyproject.toml. Don't list callables: the platform installs its own matching copy.

System packages

When a function shells out to a command-line tool, list the Debian packages it needs in apt.txt at the repo root, one per line:

# apt.txt
ffmpeg
poppler-utils
  • Names only, no versions. You get the version Debian 13 (trixie) ships.
  • Packages are installed without their recommended extras. If a tool is missing something, such as fonts, list that package too.
  • They're installed once per change to apt.txt, not on every push.
  • call local uses the tools on your own machine, so install them there too.

Functions in a subfolder

By default the whole repo is built. To build one folder, such as in a monorepo, add callables.toml at the repo root:

root = "automations"

Or [tool.callables] with root = "automations" in pyproject.toml. Only that folder goes into the image, and its own requirements.txt, apt.txt and .python-version are used. Code in it can't import from the rest of the repo. call check, call local and call manifest use the same folder when run from the repo root.

Import-time code

Every module that imports callables is imported at build time. Keep import-time code cheap and free of side effects: no network calls, and no reading secrets at module level. Read secrets inside the function.

The run sandbox

  • Each run gets a fresh sandbox on Debian 13 (trixie), as a non-root user, with internet access.
  • Your code in /app is read-only.
  • You can write to your home directory (~) and to /tmp, which is limited to 256 MB.
  • Nothing persists between runs. Keep state in your own database or storage.
  • /tmp doesn't allow running programs. Put a downloaded binary under ~ and chmod +x it, or better, install it with apt.txt.
  • print() and logging output show as the run's logs.

Memory and CPU

You don't size anything. A run can use memory and CPU up to the team's plan limit, and usage is billed on what the run actually used. Builders see each run's peak memory and CPU time on its page. A run that goes over the memory limit fails with an error that says so: process data in chunks, or move to a bigger plan. Child processes count toward the same limit.

Rollback

Each function page lists its recent deploys. Roll back to any version that's still kept: the current one, the three before it, and any that a queued or running run needs.