Python
Python apps are WSGI — agenthost imports the name app from app.py and serves it with gunicorn.
Python apps are served as a WSGI application. agenthost imports the name app from app.py — so
your project must have a file named app.py at its root that exposes a WSGI callable named app.
This is a fixed convention, not something you can rename with a parameter.
- The entrypoint is
appinapp.py. A Flask or Django app object namedappin that file is exactly what's expected. - List your dependencies in
requirements.txt, and includegunicornthere — that's what serves the app. Omit it and the app fails to start.
# must expose `app`
from flask import Flask
app = Flask(__name__)
@app.route("/health")
def health():
return {"ok": True}flask
gunicornThe most common Python failure
The entrypoint isn't named app.py, or the WSGI object inside it isn't named app — so the import
fails and the container crash-loops even though provisioning "succeeded". If you need a different
framework or an async (ASGI) server, adapt it to expose a WSGI app in app.py, or wrap it so
that name resolves.
Supported versions are 3.11, 3.12 and 3.13, defaulting to 3.12 — see Choosing a version.
Making the name resolve
Your code doesn't have to live in app.py; the name just has to be importable from there.
from myproject.wsgi import application as app# FastAPI is ASGI; gunicorn here is WSGI. The a2wsgi adapter bridges it.
from a2wsgi import ASGIMiddleware
from main import app as asgi_app
app = ASGIMiddleware(asgi_app)The wrapper approach works, but if you need real ASGI concurrency, bring your own Dockerfile and run uvicorn yourself on port 8000.
What gets built
FROM python:<version>-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["sh", "-c", "gunicorn app:app -b 0.0.0.0:8000"]requirements.txt is copied and installed before the rest of your source, so unchanged
dependencies are cached between deploys. Traffic is routed to port 8000; gunicorn is already
bound there for you.
Common failures
| Symptom | Cause |
|---|---|
| "gunicorn: not found" | gunicorn missing from requirements.txt |
ModuleNotFoundError: No module named 'app' | No app.py at the project root |
Failed to find attribute 'app' in 'app' | app.py exists but the callable inside is named something else |
| A package fails to build during install | It needs system libraries the slim image lacks — pin a wheel-shipping version or bring your own Dockerfile |
| Django: static files missing | Run collectstatic before deploying, and serve them via WhiteNoise |