Workflows
The command sequences an agent uses to check an app, build and run an image, react to failures, fix detection, keep caches in CI, and build on Olimpia.
Check that an app can be built
acropolis plan ./app --json > plan.json
- Read
providerandfacts(framework, package manager, runtime) and compare them with the repo. - Read
image.cmd: it is how the container will start. - Read
warnings. - If something is wrong, see Fix detection.
If plan fails, read the exit code: it is 78 (config) when detection or the config is the problem (no provider detected, no start command, invalid or unsupported config, paths outside the app), and can be another class otherwise, such as 75 for a network error or 70 for an unrecognized error. No root or image is needed for this step.
Build an image and run it
acropolis --events json build ./app --oci image.tar --info info.json 2> events.jsonl
docker load -i image.tar
docker run --rm -p 3000:3000 -e PORT=3000 <image id from docker load>
- The build needs root on Linux x86_64 or arm64.
- Read
info.jsonfirst:success, thenerrorClassandexitCodeon failure. - Runtime variables go on
docker run, not onbuild: build variables do not reach the image config. - Publish ports on
127.0.0.1(-p 127.0.0.1:3000:3000) when the machine is reachable from a network.
React to a failed build
jq -r '.exitCode, .errorClass, .error' info.json
exitCode |
next step |
|---|---|
1 |
Read the step_failed and log events in events.jsonl, fix the app’s code or build command, build again. |
75 |
Retry once with the same inputs. |
78 |
Read error. Fix the config (see below) or build with another tool. |
70 |
Build with another tool and report the bug with the error text and acropolis --version. |
Don’t loop on the same failing build without a change, except one retry on 75.
Fix detection
Most apps need no configuration. When the plan is wrong:
-
Try a variable first and re-run
planwith it:acropolis plan ./app --json -e ACROPOLIS_START_CMD="node dist/server.js" acropolis plan ./app --json -e ACROPOLIS_NODE_VERSION=22 acropolis plan ./app --json -e ACROPOLIS_PROVIDER=python -
When it works, make it permanent in
acropolis.jsonat the app root, so every build gets it:{ "deploy": { "startCommand": "node dist/server.js" } } -
Run
planagain, thenbuild.
Unknown keys in acropolis.json fail the build. Every key and variable is in Configuration.
Build in CI with a cache
On a runner that starts empty, carry the per-app cache between runs:
export ACROPOLIS_CACHE_KEY=my-app
acropolis cache import cache.tar.zst || true
acropolis --events json build . -t registry.example.com/team/my-app:"$GIT_SHA" --info info.json
acropolis cache export cache.tar.zst
|| true keeps the job going when there is no cache yet or the file is broken: cache import exits non-zero then, and the build works without it. Store cache.tar.zst with the CI system’s cache. Run the three commands as the same user, or with the same --home, so they use the same home. ACROPOLIS_CACHE_KEY must come from the environment of the acropolis process: through -e it is ignored, and without it the build uses a hash of the app path, which differs between runners with different checkout paths. For builds of code you don’t control, follow Running in production.
Upgrade Acropolis
- Read the changelog entries between the installed version (
acropolis --version) and the new one. - Install the new release with checksum and attestation checks (Install).
- Run
plan --jsonon the apps you build and compare with the previous plans before building.
Build on Olimpia
With Olimpia’s MCP server connected, an agent switches an app to Acropolis and deploys it:
update_app(app: "web", builder: "acropolis")
deploy(app: "web")
get_deployment(app: "web", wait_seconds: 50) # repeat while it is still building
get_logs(app: "web", since: "5m")
For a new app, pass builder: "acropolis" to create_app. If Acropolis cannot build the app, Olimpia continues with the default builder (the Dockerfile, or Railpack when there is none). To go back, update_app(app: "web", builder: "default").
With builder: "acropolis" and a GitHub source, a push only redeploys the app when it touches files its image depends on. Olimpia’s deploy flow is documented in Olimpia’s agent docs.