Deploy the on-prem agent
The on-prem agent runs Great Expectations against a database the cloud can't reach. See Agent mode for the architecture; this page is the operator runbook.
Prereqs
- An owner account in PLACEHOLDER Cloud — agent tokens are issued from the Settings → Agents screen.
- A machine inside the customer network with outbound HTTPS to the cloud control plane and inbound access to the customer DB. Docker optional but recommended.
- The connection string for each datasource the agent will validate.
1. Issue an agent token
In PLACEHOLDER Cloud, go to Settings → Agents → Issue token. Name
it after the machine you'll run on (e.g. prod-vpc-01). Copy the
dqa_… token that appears — the token is shown only once.
2. Deploy the agent container
The agent ships as a Docker image. Pull, set the three env vars, run:
docker run -d \
--name dq-agent \
--restart unless-stopped \
-e DQ_AGENT_CLOUD_URL=https://placeholder.example.com \
-e DQ_AGENT_TOKEN=dqa_… \
-e DQ_AGENT_DATASOURCE_DSNS='{}' \
ghcr.io/tomplace/dq-cloud-agent:latest
The first start will fail to find a datasource — that's expected; you'll wire DSNs in step 4.
3. Register your datasources
The agent calls the cloud to register each local datasource. From the container, post a registration:
docker exec dq-agent python -c "
import httpx, os
r = httpx.post(
os.environ['DQ_AGENT_CLOUD_URL'] + '/api/agent/v1/datasources',
headers={'Authorization': f'Bearer {os.environ[\"DQ_AGENT_TOKEN\"]}'},
json={'name': 'prod-orders', 'type': 'postgres'},
)
print(r.status_code, r.json())
"
The response includes the datasource's UUID. Copy it.
You can also do this from the cloud UI — Settings → Agents → <your agent> → Register datasource — which posts on your behalf.
4. Map the datasource UUID to a local DSN
The agent owns the DSN, not the cloud. Stop the container, set
DQ_AGENT_DATASOURCE_DSNS to a JSON object keyed by the UUID, and
restart:
docker stop dq-agent && docker rm dq-agent
docker run -d \
--name dq-agent \
--restart unless-stopped \
-e DQ_AGENT_CLOUD_URL=https://placeholder.example.com \
-e DQ_AGENT_TOKEN=dqa_… \
-e DQ_AGENT_DATASOURCE_DSNS='{"<datasource-uuid>": "postgresql://dq_ro:****@private.db.local:5432/orders"}' \
ghcr.io/tomplace/dq-cloud-agent:latest
Multiple datasources go in one JSON object. The DSN format is whatever
SQLAlchemy + the dialect driver accepts — postgresql://,
snowflake://, bigquery://, etc.
5. Run a checkpoint
In the cloud UI, build a rule suite against the agent-mode datasource
and click Run now. Within DQ_AGENT_POLL_INTERVAL_SECONDS (default
5 s) the agent picks up the job, runs the validation locally, and
posts redacted metadata back. The result appears in the Results
list with no "view failing rows" panel — the on-prem cut by design.
If you watch docker logs dq-agent you'll see one log line per cycle:
agent_started cloud_url=https://placeholder.example.com datasources=[...]
agent_claim_won run_queue_id=... datasource_id=...
agent_complete_ok success=True expectations=4
Configuration
| Env var | Default | What it does |
|---|---|---|
DQ_AGENT_CLOUD_URL | https://placeholder.example.com | Base URL of the cloud control plane. |
DQ_AGENT_TOKEN | (required) | dqa_… issued in the cloud UI. |
DQ_AGENT_DATASOURCE_DSNS | {} | JSON object: datasource UUID → local DSN. |
DQ_AGENT_POLL_INTERVAL_SECONDS | 5 | Sleep between empty-queue polls. |
DQ_AGENT_HEARTBEAT_INTERVAL_SECONDS | 60 | Keep-alive interval while a job runs. |
DQ_AGENT_REQUEST_TIMEOUT_SECONDS | 30 | HTTP timeout for each cloud call. |
DQ_AGENT_RUN_TIMEOUT_SECONDS | 600 | Wall-clock cap on a single GX run. |
Operations
- Logs. The agent writes structured (JSON-friendly) lines to stderr. Ship them into your SIEM as you would any container's stderr.
- Health. The agent is headless — there's no
/healthzto probe. Liveness is "the container is running"; readiness is "the cloud is reachable", which the poller surfaces asagent_poll_failedwarnings if not. Use your orchestrator's process check. - Scaling. A single agent processes one job at a time. Run more containers under the same token to scale horizontally — the cloud's atomic claim makes contention safe.
- Rotation. To rotate the token, issue a new one in the cloud UI,
restart the container with
DQ_AGENT_TOKENset to the new value, then revoke the old one. The redactor / claim flow is stateless on the agent side so no draining is needed. - Upgrading. Pull a newer image tag and replace the container. In
flight jobs that hadn't reached
/completeget reclaimed by another agent after the claim TTL (default 5 minutes); make sure another agent is running before stopping the only one mid-run.
See also
- Agent mode — the architecture and the metadata cut.
- Deploy with Docker — for the cloud-side images.