FastAPI
Install + wire
Section titled “Install + wire”from contextlib import asynccontextmanagerfrom fastapi import FastAPIfrom z4j_fastapi import Z4JAgent
@asynccontextmanagerasync def lifespan(app: FastAPI): agent = Z4JAgent( brain_url=os.environ["Z4J_BRAIN_URL"], token=os.environ["Z4J_TOKEN"], project_id=os.environ.get("Z4J_PROJECT_ID", "default"), agent_name=os.environ.get("HOSTNAME", "fastapi"), ) async with agent: app.state.z4j = agent yield
app = FastAPI(lifespan=lifespan)Why lifespan not on_event
Section titled “Why lifespan not on_event”FastAPI’s @app.on_event("startup") is deprecated. The lifespan context manager is the current idiom; it cleanly runs the agent for the full server lifetime.
Worker processes (arq / taskiq)
Section titled “Worker processes (arq / taskiq)”arq and taskiq workers are separate processes from the FastAPI app. They also need an agent. Pattern:
# arq workerfrom arq import ArqRedisfrom z4j_fastapi import Z4JAgent
async def on_startup(ctx): ctx["z4j"] = Z4JAgent(...) await ctx["z4j"].__aenter__()
async def on_shutdown(ctx): await ctx["z4j"].__aexit__(None, None, None)
class WorkerSettings: functions = [...] on_startup = on_startup on_shutdown = on_shutdownSame shape for taskiq (startup / shutdown hooks).
Uvicorn reload
Section titled “Uvicorn reload”During uvicorn --reload, agents reconnect on every save. The brain tolerates this - rapid reconnects don’t create duplicate agents because tokens are unique.
Multi-worker (uvicorn --workers N)
Section titled “Multi-worker (uvicorn --workers N)”Each worker is a separate agent process. Set agent_name with $PID if you want per-worker visibility.
Auth integration
Section titled “Auth integration”z4j is not an authentication provider for your FastAPI app. The agent only authenticates to the brain. Your app’s own auth is untouched.
Verify with doctor
Section titled “Verify with doctor”python -m z4j_fastapi doctor runs the same probes the agent runtime does (buffer dir writable, brain DNS / TCP / TLS, WebSocket upgrade) using the Z4J_* env vars your service is configured with.
# Always run as the same user the service runs under.sudo -u app /srv/app/venv/bin/python -m z4j_fastapi doctor
# Skip the WS round-trip when the brain is intentionally offline:python -m z4j_fastapi doctor --no-websocket
# Machine-readable for scripting:python -m z4j_fastapi doctor --jsonExits 0 on all-green, 1 on any failure. Catches uvicorn-under-service-user silent startup failures, NAT / firewall / cert issues, and wrong-token / wrong-project_id problems with a specific failure reason. See service-user deployments.
Troubleshooting
Section titled “Troubleshooting”First, run python -m z4j_fastapi doctor — it surfaces the most common failures with a specific reason.
PermissionError: ... /nonexistent/.z4junder uvicorn - the service user has an unwritable$HOME. Upgrade to z4j-bare 1.0.6+ (auto-relocates buffer to$TMPDIR/z4j-{uid}) and see service-user deployments.- Agent only registers under uvicorn, not under arq/taskiq workers - workers are separate processes and need their own
Z4JAgent(...)boot in the worker’son_startuphook.
Config keys
Section titled “Config keys”Same as Django/Flask - see Django.