Skip to content

Framework - Flask

Package: z4j-flask - Flask 2.3+ / 3.x.

from flask import Flask
from z4j_flask import Z4J
z4j = Z4J()
def create_app():
app = Flask(__name__)
app.config.from_object("myapp.config.Config")
z4j.init_app(app, {
"brain_url": app.config["Z4J_BRAIN_URL"],
"token": app.config["Z4J_TOKEN"],
"project_id": app.config.get("Z4J_PROJECT_ID", "default"),
})
return app

Or the one-shot form:

Z4J(app, {...config...})

Flask’s application context doesn’t have a natural “startup” hook. z4j-flask uses app.before_request (first-request) to start the agent. This is fine for web processes; for worker processes, call z4j.start() manually in your worker boot.

rq_worker.py
from myapp import create_app
from z4j_flask import z4j
app = create_app()
z4j.start(app) # or place inside `with app.app_context():`
# ... RQ worker loop ...

Same as Django: each worker is its own agent. Set agent_name to include the role:

import socket, os
z4j.init_app(app, {..., "agent_name": f"web-{socket.gethostname()}-{os.getpid()}"})

See Django for the full Z4J config dict - the keys are identical.

z4j does not register any Flask blueprints. It attaches as pure background behavior - your URL space is untouched.

Management commands don’t start the agent unless you explicitly call z4j.start(app).

  • Agent starts but never connects - the first request triggers start. If your app has no inbound traffic yet (fresh deploy), the agent will appear offline until traffic arrives. Call z4j.start(app) at app-factory time if you prefer eager-start.
  • Gunicorn preload mode - the agent’s asyncio loop is per-worker. Preload is fine, but each worker still opens its own WebSocket after fork.