Make the supervisor work on Podman: reach the socket, and wait for healthy - #372
Merged
Conversation
…althy Nothing had run this stack on Podman. Two things stopped it, both found by bringing it up on rootless Podman 6.1.1 on macOS and running the smoke journey. The supervisor could not reach the engine. The socket is where it expects it, and the mount is correct: Podman's virtual machine already symlinks /var/run/docker.sock to the rootless socket, so no path changes. The machine runs SELinux enforcing and labels that socket user_tmp_t, which a container without label=disable cannot read. Declaring it is the whole fix and is a no-op on Docker. Then every cold start of a computer raced the first request to it. Readiness was read off the image's HEALTHCHECK, and Podman reports none: its images are OCI-manifest, the OCI image config has no healthcheck field, and the instruction is dropped both when Podman builds an image and when it pulls one that carries it. The published agent-computer config does carry it; podman inspect of that same image reports none. With nothing to read, the supervisor took the branch that accepts a container which is merely running, and a running container is not a Chromium that is answering, so the request arrived at a port nothing was listening on yet and was reported as a computer that is not running. It now states the healthcheck when it creates the computer rather than inheriting it, so readiness stops depending on how the image was built. Podman honours an explicit healthcheck: it is how every compose service reports healthy there. Docker is unchanged, because the numbers are the ones the Dockerfile already declared. This also matters for the zstd images published in 0.0.7. zstd layers require OCI media types, and an OCI image cannot carry a HEALTHCHECK that Podman will report, so the two could not both be had while readiness was read off the image. Verified on Podman: cold start failed before the change, twice, and passes after, with the created computer reporting healthy while the image it came from reports no healthcheck at all.
davidmckayv
requested review from
MikeRyanDev,
guidovizoso and
tylerslaton
as code owners
September 4, 2026 19:46
`as const` made every field readonly, and `HealthConfig` declares `Test` as a mutable `string[]`, so the object could not be assigned to it. Caught by `types (supervisor)`, which runs `tsc` from that package after installing its own dependencies; running the script from the repository root instead reports a different and misleading set of errors, because the package's own `node_modules` is not there.
guidovizoso
approved these changes
Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
S1 of the OpenBot Desktop build: prove the stack on Podman. It did not work. Two defects, both fixed here.
1. The supervisor could not reach the engine
The supervisor could not reach Docker (Error: Was there a typo in the url or port?). A computer cannot be started without it.Not a path problem. Podman's VM already symlinks
/var/run/docker.sockto the rootless socket, so the existing compose mount is correct and needs no change. The VM runs SELinux enforcing and labels the socketuser_tmp_t:security_opt: [label=disable]on the supervisor is the whole fix. No-op on Docker Desktop; understood by Docker on SELinux hosts.2. Every cold start of a computer raced the first request
After the socket worked, the supervisor created the computer and the request still failed, now with
The assistant's computer is not running.The computer was running, and answering
/healthwith 200. What was missing was the health status: Podman reports noHEALTHCHECK. Its images are OCI-manifest, the OCI image config has no healthcheck field, and the instruction is dropped both when Podman builds an image and when it pulls one that has it.Read straight from the registry, the published image has it:
podman inspectof that same pulled image:NONE.With no health to read,
waitUntilAnsweringtook the branch that accepts a merely-running container. A running container is not a Chromium that is answering, so the first request hit a port nothing was listening on. That branch's own comment called this out as the worse-but-necessary option; on Podman it was not the exception, it was every time.The supervisor now passes the healthcheck when it creates the computer instead of inheriting it. Readiness stops depending on how the image was built. Podman honours an explicit healthcheck: it is how every service in
docker-compose.ymlreports healthy there. Docker is unchanged, because the numbers are the onesagent-computer/Dockerfilealready declares.This one collides with 0.0.7's zstd images
zstd layers require OCI media types. An OCI image cannot carry a HEALTHCHECK that Podman will report. So zstd and image-declared readiness could not both be had while readiness was read off the image. Stating it at create time is what makes them independent.
Verified on Podman, not reasoned about
Rootless Podman 6.1.1,
applehv, macOS arm64. Isolated stack: own Compose project,COMPUTER_NAMESPACE, database and ports.<none>healthyNONENONE, stillThat last row is the point: the computer reports healthy while the image it came from carries nothing, so it is the explicit healthcheck doing the work.
The full journey passes on Podman: compose up, supervisor holding the rootless socket, a per-Bot computer created through it, and a harness answering a live AG-UI run through the gateway with the trail recording it.
format:check,lintand the supervisor unit tests are clean.supervisor typecheckreports the same five pre-existingTS7006errors asmain, byte-identical apart from shifted line numbers; this change adds none.Three doc corrections this also produced
Not in this PR, they are build-doc edits:
--provider applehvis a no-op on 6.1.1: it is the default on Apple silicon. The pin was written against 5.7.x when libkrun was the default./var/run/docker.socksymlink in the VM.