What the agent does
The agent starts from the failure, not the Dockerfile. It reads the failed job's log, finds the first error rather than the last line, and works out which image and which stage broke. In a repository like GoogleCloudPlatform/microservices-demo that matters, because there are eleven service images in four languages and the build runs through Skaffold: .github/workflows/ci-main.yaml installs Docker Buildx and Skaffold, then runs skaffold run --default-repo=... --tag=$GITHUB_SHA -p network-policies, and skaffold.yaml maps each image to a context such as src/frontend, with src/cartservice/src as the exception.
Then it reproduces the build in its sandbox with plain docker build on the failing context, so the error shows up without Skaffold, GKE or registry credentials in the way. It reads the Dockerfile stage by stage. Here every builder stage is pinned to a digest and built with --platform=$BUILDPLATFORM: Go services on golang:1.27.0-alpine@sha256:… and a gcr.io/distroless/static runtime, Node services on node:24.20.0-alpine and an alpine:3.24.1 runtime, Python on python:3.14.7-alpine, cartservice on the .NET 10 SDK and runtime-deps chiseled images, adservice on Eclipse Temurin 25. It notes that gcr.io/distroless/static is the one base with no tag or digest, so it can change under the build without a commit.
The usual causes are a base image or package that moved, a dependency file copied after the step that needs it, a build context that is missing a file because of .dockerignore (seven services here have one, five do not), a lockfile out of step with its manifest, or a compiler version the code no longer builds with. The agent fixes the cause in the Dockerfile or the code and rebuilds until docker build succeeds, recording the image size before (when the old image still builds from the previous commit) and after.
A build that succeeds is not yet proof, so the agent starts the image. For the frontend it runs the container with PORT set, since src/frontend/main.go reads it, and requests /_healthz, which answers ok. For a gRPC service such as cartservice on port 7070 it checks that the process stays up and listens on the port its Dockerfile EXPOSEs. Then it opens the pull request with the build output and the run check.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "The Docker build in CI failed; the log is linked below. Read the log and find the first error and the image it belongs to. Reproduce the build in the sandbox with docker build on that image's context. Fix the cause in the Dockerfile or the code, without unpinning base images or removing build steps. Build the image again, then start the container and check that it serves: an HTTP health endpoint if it has one, otherwise that the process stays up and listens on its exposed port. Report the image size before and after. Open a pull request with the cause, the fix, the final build output and the run check.\n\nFailed job: {ci_log_url}",
"resources": [
{
"url": "https://github.com/your-org/your-app"
}
]
}- Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
- Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
- Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.
What comes back
What comes back is a pull request that changes the smallest thing that fixes the build: a Dockerfile line, a .dockerignore entry, a lockfile, or the code a new compiler rejected. In a multi-service repository like Online Boutique it touches only the failing service's directory. The description names the cause in one sentence, quotes the error from the CI log, shows the end of the successful docker build output, the image size before and after, and the result of starting the container, such as the ok from the frontend's /_healthz.
The pull request's own checks run the repository's CI on the fix. Where CI only builds images on pushes to the main branch, as ci-main.yaml does here while ci-pr.yaml runs only Go and C# unit tests, the description says so, and the sandbox build in the trajectory is the evidence until the merge build runs. The trajectory keeps every build attempt with its output, including the ones that failed on the way to the fix.
Before merging, a reviewer checks that the fix addresses the cause rather than hiding it (a pinned digest replaced by a floating tag fixes nothing for long), that no build step or test was removed to get green, and that the image size did not grow for no reason.
Run it on every failed image build
Subscribe to GitHub's workflow_run webhook and, when a run of your image-building workflow completes with conclusion: failure, have your server send this request with the run's URL in input and the repository in resources. Use the workflow run id as the Idempotency-Key header so a redelivered webhook does not start a second fix for the same failure.
Give the API key a webhook URL and Rush POSTs run.completed or run.failed when the agent's turn ends, with the session URL to read the pull request link from, so your server can post it in the channel where the failure was announced.
The use case this job follows, with its automation and trigger: Fix a bug from an alert.
Why run it on Rush?
Reproducing a broken image build on a laptop drags in your local Docker cache, a different CPU architecture than CI, and whatever base images you pulled last month, so the build often fails differently or not at all. The agent on Rush builds in a clean sandbox of its own, reproduces the failure from the log, and keeps every docker build with its output, so the pull request carries the before and after, not a guess.
It also checks the part people skip: that the fixed image starts and serves. A green build of an image that crashes on boot is a broken deploy one step later. Because each failure is its own run, two services that break on the same base image bump get two independent fixes, each reviewed on its own.
Frequently asked questions
Can it build images for another architecture?
It reproduces the build for the sandbox's own architecture first, which catches nearly every Dockerfile and dependency error. If the failure is specific to another platform, it can use Buildx with QEMU emulation in the sandbox, as microservices-demo's CI does with its Set up QEMU step, at the cost of a slower build.
Does it need my registry credentials?
No. It builds and runs the image locally in the sandbox and never pushes it. Pushing stays with your CI, which runs on the merged fix. If a base image lives in a private registry, the build needs a pull credential; save it as a secret in a Project and start the run in that Project.
Will it unpin my base images to make the build pass?
The request tells it not to. If the fix genuinely needs a newer base, it updates the pin to a specific new tag and digest and says why in the pull request, so the build stays reproducible.
What if the build fails because of the CI runner, not the image?
If the sandbox build succeeds unchanged, the agent says so: the cause is outside the Dockerfile, such as a runner's disk space, an expired registry token or a rate limit on image pulls. It reports what in the log points there and opens no pull request, rather than changing code that was not broken.