Skip to main content
You can run an Agent37 instance from any Docker image. Register it as a workspace template in one of two ways: 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 on ghcr.io/agent37-platform/hermes-base. It includes Hermes, the gateway, Chromium, and the standard toolchain. This example adds a CLI and a skill:
Bake binaries into /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.
Your built image freezes its base at build time. :latest is convenient while getting started; pin a dated Hermes base tag for reproducible production rebuilds. Find published tags on GHCR, or read the current tag from agent37-hermes’s image_ref on GET /v1/templates.

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. Plain docker build stores the amd64 result in your local Docker, including on an Apple Silicon Mac:
Run the image locally if it is practical: registration validates the image, but only a running container proves that its entrypoint and service work. If you take the public registry path, this local 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 (the Dockerfile and the files it COPYs), and Agent37 builds the image on its own infrastructure:
What it does:
  • Packs the directory (default .; it must have Dockerfile at its root) into a gzipped context, excluding .git and your .dockerignore patterns (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 .env or key file included, and a COPY . . 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. --name defaults 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.
Builds are free, run one at a time per workspace, and time out after 45 minutes. The built image is capped at 8 GB decimal like any template image, and practically tops out around 4 GB today; if you need more, contact support. Everything the build fetches — the 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:
On GHCR, make the package public after the first push (PackagesPackage settingsChange visibilityPublic). The starter example includes a GitHub Actions workflow that builds linux/amd64 and publishes immutable commit tags. Register a specific tag, not latest:
curl
Agent37 needs anonymous access only while it copies the image. The template and its instances no longer depend on the source registry after registration. A future image update needs a new public tag.
If your own image serves HTTP on port 8000, declare it: pass --default-port 8000 on the build, or include "default_port": 8000 beside name and image_ref. The bare instance URL then routes to that port, and instance creation probes it at boot. Omit it for hermes-base, whose gateway uses the 3737 fallback, or for a long-running private sandbox with no HTTP service.

4. Create an instance

Register once, then create instances from the template name:
curl
The result is a standard Agent37 instance running your image: same lifecycle, exec, and routed URLs as any other. Confirm your CLI shipped, without needing a model:
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:
Your endpoint must serve the two OpenAI-compatible routes Hermes uses: 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.
Want chat to work out of the box on Agent37’s managed model instead? Build FROM ghcr.io/agent37-platform/hermes:<tag> (tags on GHCR) — the full image wires the managed model — and pass a budget on create.

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 PATCH image_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.

Troubleshooting