Quickstart - Bare Python
z4j-bare is the foundation package; every framework adapter depends on it. You can use it directly if you have no framework.
1. Install
Section titled “1. Install”pip install z4j-bare z4j-celery2. Mint an agent
Section titled “2. Mint an agent”From the z4j dashboard, Agents, Mint. The response shows the bearer token
and the per-project HMAC secret. Save both as Z4J_TOKEN and
Z4J_HMAC_SECRET. The token is stored only as a hash and cannot be recovered.
The HMAC value is derived from the brain master and project ID; it is shared by
agents in that project rather than stored as an agent-specific secret. The
runtime refuses to start without it.
3. Start the agent at process boot
Section titled “3. Start the agent at process boot”import asynciofrom z4j_bare import install_agentfrom z4j_celery import CeleryEngineAdapter
# my_celery_app = Celery("myapp", broker="redis://...")
runtime = install_agent( engines=[CeleryEngineAdapter(celery_app=my_celery_app)], # brain_url / token / hmac_secret / project_id default to the # matching Z4J_* env vars; pass them explicitly only if you do # not want the env-var lookup.)
try: asyncio.run(your_work())finally: runtime.stop() # stop transport and close the durable local bufferinstall_agent returns a started AgentRuntime. Hold the reference and call
.stop() on shutdown. The runtime drives the WebSocket connection on a
background thread and an internal asyncio loop, so it composes with sync
workloads. stop() does not wait for the brain to acknowledge every pending
event; unsent rows stay in the SQLite buffer for a later start.
Verify before launching the long-running agent
Section titled “Verify before launching the long-running agent”Before you run worker.py for the first time, run the doctor. It checks local
configuration, the buffer path, DNS/TCP/TLS reachability, and whether the
transport can start without leaving a persistent agent running:
Z4J_BRAIN_URL=... Z4J_TOKEN=... Z4J_HMAC_SECRET=... Z4J_PROJECT_ID=... \ python -m z4j_bare doctorRun as the same user your worker process will run under. The WebSocket probe
does not wait for the agent-auth handshake, so [OK] is not proof that the
token or project is accepted. After starting the worker, also confirm that its
worker slot is online in z4j and inspect agent-auth warnings.
4. What install_agent does
Section titled “4. What install_agent does”- Opens the configured transport.
autocurrently means WebSocket; there is no automatic long-poll fallback. To use long-poll, setZ4J_TRANSPORT=longpolland the mintedZ4J_AGENT_IDexplicitly. - Sends
hellowith engine and scheduler capabilities. - Installs patches on the supplied engine adapters to capture lifecycle events.
- Starts a heartbeat loop.
- On
runtime.stop(), requests transport shutdown, joins the background thread within the timeout, and closes the durable buffer. Pending rows are not synchronously flushed to the brain.
5. Multiple engines
Section titled “5. Multiple engines”install_agent accepts any number of engine adapters; the runtime fans events out for each:
from z4j_bare import install_agentfrom z4j_celery import CeleryEngineAdapterfrom z4j_rq import RqEngineAdapterfrom redis import Redisfrom rq import Queue
rq_connection = Redis.from_url("redis://localhost:6379/0")rq_queue = Queue(connection=rq_connection)
runtime = install_agent( engines=[ CeleryEngineAdapter(celery_app=celery_app), RqEngineAdapter(rq_app=rq_queue), ],)- For mapped configuration fields, explicit keywords win over environment
variables, which win over defaults. Adapter objects,
framework,buffer_path, anddev_modeare code-only inputs.Z4J_BUFFER_PATHis a removed variable that causes startup refusal, andZ4J_DEV_MODEis ignored by the generic resolver. See install_agent reference for the full argument list. - The same
AgentRuntimeobject can be stopped and started again. Do not callinstall_agent()a second time after stopping it: the process singleton returns the already-registered, stopped runtime. Callruntime.start()on the object you retained instead.