Skip to content

Quickstart - Flask

Terminal window
pip install z4j-flask z4j-rq z4j-rqscheduler
# or: pip install z4j-flask z4j-celery z4j-celerybeat

From the z4j dashboard, Agents, Mint. The response shows the bearer token and the per-project HMAC secret exactly once. Save both.

Z4J(app) reads configuration from Flask’s app.config (flat Z4J_* keys), an optional Z4J dict, or the environment. It does not take a config dict as a positional argument.

Either set the values on app.config before calling Z4J(app):

app.py
from flask import Flask
from z4j_flask import Z4J
def create_app():
app = Flask(__name__)
app.config["Z4J_BRAIN_URL"] = "wss://z4j.example.com/ws"
app.config["Z4J_TOKEN"] = "z4j_agent_..."
app.config["Z4J_HMAC_SECRET"] = "..."
app.config["Z4J_PROJECT_ID"] = "billing-prod"
Z4J(app)
return app

Or, more commonly, set them as environment variables (Z4J_BRAIN_URL, Z4J_TOKEN, Z4J_HMAC_SECRET, Z4J_PROJECT_ID, Z4J_AGENT_NAME) and just call Z4J(app). The third form is the nested dict:

app.config["Z4J"] = {
"brain_url": "...",
"token": "...",
"hmac_secret": "...",
"project_id": "billing-prod",
}
Z4J(app)

All three forms are equivalent; pick one. Z4J_HMAC_SECRET is required — the agent refuses to start without it.

Z4J(app) registers request teardown hooks and starts the agent’s background WebSocket task during app init.

Run the doctor first, which confirms the agent can reach z4j end-to-end and reports a specific failure if it cannot:

Terminal window
python -m z4j_flask doctor

Run as the same user your service runs under (sudo -u www-data ... for gunicorn). All probes should be [OK].

Then boot Flask plus your RQ (or Celery) worker. Both processes register as agents (web + worker). The dashboard shows both.

Each gunicorn / uwsgi worker process registers separately. The worker-first protocol identifies each one by (agent_id, worker_id), so a gunicorn -w 4 deployment shows up as four workers under one agent in the dashboard. Set Z4J_AGENT_NAME to keep multi-host deploys readable:

import os
import socket
app.config["Z4J_AGENT_NAME"] = f"web-{socket.gethostname()}-{os.getpid()}"

See framework: Flask for the deeper reference.