Runtimes
Static, Node, Python and PHP — how the runtime is chosen, the single entrypoint each one looks for, what it installs dependencies from, and the escape hatch for everything else.
The runtime decides how your source is built and started. There are four, and each looks for one entrypoint. Match it and a deploy just works.
| Runtime | Inferred from | Entrypoint it looks for | Installs deps from | Port |
|---|---|---|---|---|
static | index.html | index.html at the project root | — | 80 |
node | package.json | npm start (the start script) | package.json | 3000 |
python | requirements.txt, .py | app imported from app.py | requirements.txt | 8000 |
php | composer.json, .php | index.php at the project root | composer.json (optional) | 80 |
How the runtime is chosen
Pass it explicitly as runtime — "node:22", "python:3.12", "php:8.3", "static" — or omit it
on create_app and agenthost infers it from your files. Inference is a convenience for the common
case; when in doubt, set it explicitly. If you omit it and nothing can be inferred, create_app
fails and asks for one.
The version half is optional: "node" and "node:22" both work, and a supported default is picked
when you leave it off. See Choosing a version.
There is no start_command, and no port setting.
How an app starts is fixed per runtime — it is the convention on these pages, not a parameter. A field the tool schema doesn't define is silently ignored rather than rejected, so a wrong guess looks like it worked.
What every runtime shares
- Your source goes in, dependencies do not.
node_modules,vendor,.venv,__pycache__,.gitand.envfiles are excluded from the build. Ship the manifest, not the install. - HTTPS and routing are automatic. You never expose a port or configure a proxy.
- Environment variables are injected at run time, never written into your source. See Environment variables.
- Builds are asynchronous. A successful call means queued, not live. See Checking a deploy.
The escape hatch
If your project contains a Dockerfile at its root, we use yours and generate nothing. That
covers anything the four runtimes don't: a Go binary, an ASGI server, a runtime with system
dependencies, a bespoke build.
Two constraints hold:
- You still pick a
runtime(or let one be inferred) — it decides which port traffic is routed to. - Your container must listen on that port:
3000for node,8000for python,80for php and static.
Pages
Static sites
Files served exactly as handed, over HTTPS. No build step.
Node
package.json selects the runtime and holds the start script.
Python
A WSGI app named app, in app.py, served by gunicorn.
PHP
index.php as the front controller, composer optional.
Choosing a version
Append a version to the runtime, or take the default.
Common pitfalls
The handful of mistakes behind most failed deploys.