What you need
- A workload and its key. See Set up a workload; it needs the Admin or Owner role.
- Access to the agent-base image, Quint’s base image for agent containers. The image is private. Your Quint contact gives you access to it and the details for signing in to the image registry. Sign in before you check the signature or build your image (the first two steps below), and in any CI job that builds it.
- Docker on Linux, or Docker Desktop on Mac. For Docker Desktop on Windows, rootless Docker or Podman, talk to your Quint contact first.
- The docker run snippet from the workload’s Keys tab. The one extra permission Quint needs is
--cap-add NET_ADMIN, which lets it control the container’s network. Don’t add--user,--privileged,--network host,--read-onlyor--security-opt seccomp=unconfined: Quint refuses to start with any of them. - At least
--memory 512mfor Quint alone, plus what your agent needs. The dashboard’s snippet uses2g.
1
Pin the image by digest
The Dockerfile snippet on the workload’s Keys › Connect a container names the agent-base image on its The command accepts the two release workflows that sign Quint’s images, so it works for every release digest.
FROM line, pinned by digest (a fingerprint of one exact build). Pin agent-base by digest, never by tag.Each image is signed. Once you have signed in to the registry, check the signature before you build from the image. In the command, replace <image>@sha256:<digest> with the reference on the snippet’s FROM line:2
Build your image
Start from the dashboard’s Dockerfile snippet. It already has the
FROM line and the line that declares the Claude Code version to Quint. Change two things:- Replace the snippet’s placeholder install line with the commands that install Claude Code, in the version the snippet names. Quint can hold tool calls only for the Claude Code versions it knows, and an image that declares a version it doesn’t know does not start. agent-base is
debian:bookworm-slim, so add whatever else your agent needs. - Set
CMDto your agent’s command. Keep the base image’sENTRYPOINT.
/etc/quint/harness-versions.json as it is. The file tells Quint which agent is in the image and its exact version, and Quint needs it to hold a tool call while a person decides. Check that claude --version in your image prints the version the file declares. Without the file the agent still runs, but every rule that should ask for approval refuses the tool call straight away, and nobody is asked.In a container, rules on tool calls cover Claude Code. For any other agent, leave claude-code out of the file, count on network-level coverage only, and ask your Quint contact about tool calls.The agent runs as a non-root user, so paths it writes must be writable by it, and its tools must honour HTTPS_PROXY.3
Give the container its key
Save the key from the dashboard to a file named
quint-key. Never put the key itself in the docker run command. Quint removes the key from the agent’s environment, so the agent never sees it.- Docker on Linux, run as root: the file must be owned by root and readable by root only.
- Rootless Docker or rootless Podman: don’t use
sudo. Leave the file owned by your own account and runchmod 0400 quint-key. If the file no longer belongs to your account under rootless Podman,podman unshare chown 0:0 quint-keyreturns it to you. - Docker Desktop: don’t mount a key file. Docker Desktop’s file sharing ignores a file’s owner and permissions, so Quint refuses it. Set
QUINT_WORKLOAD_KEYfrom your secret store instead, and pass it by name only.
4
Say who started the run
Export
QUINT_RUN_INITIATOR in the shell or CI job that runs docker run, set to the email address the person starting the run signs in to Quint with. The commands in the next step pass it into the container by name. In CI, Quint also reads GITHUB_ACTOR, GITLAB_USER_LOGIN, BUILDKITE_BUILD_CREATOR_EMAIL or CIRCLE_USERNAME when you pass it into the container. If none of them is set, the run does not say who started it, and approvers can deny its held tool calls but can’t approve them. The person who started a run can’t approve its held tool calls, so an approval takes two people.5
Run the container
First export On Docker Desktop, with
QUINT_RUN_INITIATOR in your shell, set to the email address of the person starting the run. Both commands below pass it through by name, and Docker passes only exported variables. Then, with a key file:QUINT_WORKLOAD_KEY also set in your shell or listed in an --env-file:QUINT_WORKLOAD is the workload’s name. If QUINT_RUN_INITIATOR is not exported in your shell, the container starts without it and its log says warning: no run initiator.--stop-timeout must be longer than the workload’s Stop grace plus its Evidence flush timeout plus a few seconds. 30 covers the defaults. 90 covers the largest values an admin can set, so it stays right if someone raises them later. With a timeout that is too short, Docker ends the container before Quint has sent its last records, and the run shows Lost contact.6
Check the run
The container log shows
quint-init: enrolled run followed by the run’s ID and the workload’s name. On the Workloads page, open the workload: the run is on its Runs tab with the status Running.Your own rules refuse or hold the run’s tool calls only once Enforcement is on for your workspace. Until then the run records what they would have done. See Decide held tool calls.Stop the container
docker stop: Quint passes the stop to the agent and waits for the workload’s Stop grace. An agent that exits in time ends the run with its own exit code. One that doesn’t is stopped by force, and the run ends “Terminated from the dashboard or by a runtime stop.” with exit code 78. Quint then sends the run’s last records and closes the run.- Terminate run on the run’s page stops the run from the dashboard. The container exits with code 78 within about 30 seconds. See Stop a run.
docker kill, or a stop timeout that runs out first, ends the container before Quint can close the run. The run then shows Lost contact, and its last events may be missing.
On Kubernetes
The workload’s Kubernetes snippet runs the same image as a pod. Copy it rather than typing it, and set itsQUINT_RUN_INITIATOR to the person or system that starts the run, as “Say who started the run” above describes.
The snippet is the spec: part of a pod: put it under your own apiVersion, kind and metadata, or use it as the pod template of a Job.
Before you apply it, create a namespace that allows the privileged Pod Security level, and a Secret that holds the key from the dashboard under the name key:
quint-workload-key is the Secret name the snippet uses, and quint-key is the file you saved the key to. Then:
- Keep the snippet’s
seccompProfile,runAsUser: 0,NET_ADMINanddefaultMode: 0400lines as they are. - Don’t add
fsGroup,runAsNonRoot: true,hostNetworkorprivileged. - Give
terminationGracePeriodSecondsthe value you would give--stop-timeout. - Keep
requestsequal tolimits, as the snippet has them. The pod starts without that, but with it the agent, not Quint, is stopped first if memory runs out.
baseline or restricted level reject NET_ADMIN. Use the Restricted setup there.
Where it doesn’t run
- ECS Fargate: it doesn’t allow
NET_ADMIN. - gVisor: its network stack lacks what Quint needs to set the container’s network rules.
If this fails
The container exits and its log ends with a line that startsquint-init: refused:, or a quint-init: warning: line explains a limit. The table quotes the part of the line to look for, as the agent-base images released so far print it.
Next
- Use a workload: read runs, decide held tool calls, stop a run.
- Run Quint with agents in containers for the Kubernetes setups.