A cloud build fetches everything itself — the
FROM base image and anything RUN downloads — so those sources must be publicly reachable. There is no build-secret or private-registry-credential support yet; if your base image is private, contact support.
A complete example — a Dockerfile, an example skill, a registration script, and a tiny LLM proxy — lives in custom-agent-image/, ready to copy into your own repo.
This page is the walkthrough; Templates → build on the Hermes base image is the reference for the contract.
When you register a template, Agent37 copies your image once into private storage and pins it by digest. That snapshot is what every instance runs, so registering takes up to a few minutes for a large image. Re-pushing the same tag later does nothing: publish a new tag and update the template, or re-run the cloud build. Your image is stored privately and never republished.
1. Choose a starting image
To customize Hermes, build onghcr.io/agent37-platform/hermes-base. It includes Hermes, the gateway, Chromium, and the standard toolchain. This example adds a CLI and a skill:
/usr/local/bin, skills into /usr/local/share/agent37/default-skills/ (the entrypoint copies them to ~/.hermes/skills at boot), and everything else into /usr/local or /opt — never /home/node or /home/linuxbrew, which are masked at runtime. Keep the base ENTRYPOINT. See the full contract.
You can also use an existing image or start from any base. Its main process must keep running. If it serves HTTP, bind it to 0.0.0.0 and note its listening port; you will pass that as default_port when you register the template. An image with no HTTP service can omit default_port and be driven through exec, but it still needs a long-running ENTRYPOINT or CMD.
2. Verify it locally (optional)
You don’t need Docker to publish — the cloud build does the real build. If you have Docker, a local build is still the fastest way to test before publishing. Plaindocker build stores the amd64 result in your local Docker, including on an Apple Silicon Mac:
linux/amd64 build is also the artifact you push.
3. Register the image
You have two ways to get the image to Agent37. Either way the resulting image is capped at 8 GB decimal (8,000,000,000 bytes), and either way the platform copies it once into private storage at registration.
Registration is synchronous and can take a few minutes for a large image. The returned
image_digest identifies the immutable private copy every instance runs. Re-pushing a mutable source tag does not change that copy.Build it in the cloud
Use this path when the image isn’t in a public registry — or doesn’t exist yet. You upload a small build context (theDockerfile and the files it COPYs), and Agent37 builds the image on its own infrastructure:
- Packs the directory (default
.; it must haveDockerfileat its root) into a gzipped context, excluding.gitand your.dockerignorepatterns (plain patterns only;!negations are ignored). The context is capped at 100 MB — it holds the Dockerfile’s inputs, not the image, so it stays small. - Everything else in the folder ships with the context — a stray
.envor key file included, and aCOPY . .bakes it into the image. Check the folder, or add a.dockerignore, before you build. - Builds the image on Agent37’s infrastructure and streams the live build log to your terminal. On failure the command exits non-zero with the failing step visible.
- Publishes the result as the workspace template.
--namedefaults to the folder name;--default-port <port>sets the template’s default port. Re-building an existing name publishes a new template revision; existing instances never change. - Ctrl-C does not cancel the build; it continues server-side and still publishes on success.
FROM base image, anything RUN downloads — must be publicly reachable; there is no build-secret or private-registry-credential support yet. A template published this way has an image_digest but no image_ref, because there is no public registry reference.
To script the same flow without the CLI, see the raw contract in
Templates → build an image in the cloud.
Import a public registry image
Push the image to any public OCI registry, then register its fully qualified reference. For example:linux/amd64 and publishes immutable commit tags.
Register a specific tag, not latest:
curl
4. Create an instance
Register once, then create instances from the template name:curl
curl
If the instance comes up
failed instead of running, read its logs. An entrypoint that exits, a missing binary, or a service that never listens on default_port are the usual causes. exec cannot help until the container is running.5. Bring your own model
hermes-base is clean: it boots with no LLM provider (standard Agent37 instances use Agent37’s managed model; this base is for bringing your own). To run an instance on your own model, point Hermes at any OpenAI-compatible endpoint — your own proxy, or a provider directly — by writing ~/.hermes/config.yaml on the instance:
GET /v1/models (to resolve the model id) and POST /v1/chat/completions (the turn). The example folder includes a ~40-line llm-proxy/ that implements exactly these and forwards to OpenRouter with your key — a minimal pattern to deploy and adapt.
Write the config over exec or the instance terminal; it lives on the persistent volume, so it survives restarts. Then send a message and the agent runs on your model.
Keep it current
Your image freezes its base; rebuilding is how it picks up platform updates. Each template revision is an immutable snapshot, so a new build takes effect only after the template changes: re-run the cloud build under the same name, or publish a new registry tag and PATCHimage_ref. Every successful build and every changed image_ref increments the template’s automatic revision; a re-build counts even when its digest matches the previous image. PATCHing the same image_ref string deliberately reuses the existing snapshot and revision.
Existing instances keep their installed template_revision. Update each instance to recreate it from the template’s current revision. A skill already seeded into an instance’s ~/.hermes/skills is not overwritten on update — only fresh instances get a changed skill.