Example · Agents in sandboxes

Give Hermes a shell.
Keep everything else.

Hermes Agent, from Nous Research, writes code, runs it, and fixes what breaks. On Chalk it does that inside a sandbox that can reach only its model endpoint, using an API key it never sees. One Python file sets it up, runs the task, and hands you the diff.

CHALK SANDBOX · 2 CPU · 4 GI☤ hermes chat--oneshot --yolo$ python test_roman.py✓ all tests passed✍ roman.py · test_roman.py/root/projectgit diff → 2 new filesshell, files, git: all localenvOPENROUTER_API_KEY=__chalk-secret-7f3a…EGRESS PROXYopenrouter.aikey injected heregithub.comonly with --repoeverything elseno route, no DNS

One task, start to finish

The default prompt asks Hermes for a Roman numeral module and its tests, with no package index to lean on. In about a minute it writes both files, runs the tests, and reports back. Then the sandbox is gone, and what remains is the diff.

hermes v2026.9.24
$ ./examples/hermes/hermes.py --model anthropic/claude-sonnet-4-6
Starting sandbox (the first run builds the Hermes image)...
Running Hermes with anthropic/claude-sonnet-4-6...
Query: Create a small, standard-library-only Python module roman.py with to_roman(int) and from_roman(str) for 1-3999, and a test_roman.py that checks a round trip over the whole range plus invalid inputs…
Initializing agent...
┊ ✍️ write /root/project/roman.py 8.2s
┊ review diff a/roman.py → b/roman.py +57
┊ ✍️ write /root/project/test_roman.py 0.1s
┊ review diff a/test_roman.py → b/test_roman.py
┊ 💻 $ python test_roman.py 0.2s
☤ Hermes
All five tests pass, zero failures.
roman.py converts with a greedy table of 13 value/symbol pairs and rejects malformed input like IIII or IM with a canonical round-trip check. test_roman.py covers 21 known values, all 3999 round trips, and 16 invalid inputs, with plain asserts.
Duration: 1m 2s · Messages: 8 (1 user, 6 tool calls)
--- Changes made by Hermes ---
A roman.py
A test_roman.py
Terminated sandbox da132ad3-2fdf-4b75-b120-f2b0f9f6a6fa.

How it works

A coding agent is only useful with real tools, and only safe if those tools stay inside a boundary. The sandbox draws that boundary in three places.

A pinned image

Hermes' own installer runs once, at a pinned release, inside an image Chalk builds and caches. Every later sandbox starts from the same bytes in seconds.

An allowlisted network

The sandbox's network policy lists the model endpoint and, if you ask for one, the git host. Every other connection fails before it leaves the sandbox: no route, no DNS.

A key the agent never sees

Hermes' environment holds a random placeholder. The egress proxy replaces it with the real API key, and only on requests bound for the model host.

Getting started

Run it with one command

Clone the SDK, log in, set a model key, and run the example. The first run builds the Hermes image, which takes a few minutes; after that a sandbox is ready in seconds and a typical task finishes in about a minute.

Pass --repo to work on your own code and --prompt to change the task. Swap the model endpoint without touching anything else.

chalk-sandbox-sdk/examples/hermes
git clone https://github.com/chalk-ai/chalk-sandbox-sdk
cd chalk-sandbox-sdk

# Or export CHALK_CLIENT_ID and CHALK_CLIENT_SECRET.
chalk login
export OPENROUTER_API_KEY=...

# Builds the image, starts a sandbox, runs one task, prints the diff.
./examples/hermes/hermes.py

What Chalk handles

Hermes brings the agent. Chalk brings the place it's safe to let it work.

A real shell, safely

Hermes runs with --yolo: no approval prompts for each command. The sandbox, not a human clicking yes, is what bounds what it can do.

Nothing to exfiltrate

A prompt-injected agent that dumps its environment finds a placeholder, and has nowhere to send it except your model provider.

Images from Python

Image.debian_slim().run_commands(...) builds the container. No Dockerfile, no registry, and the first build is the only slow one.

Bounded lifetimes

Each sandbox is terminated when the run ends and carries a server-side lifetime, so a killed laptop never leaves compute running.

Any OpenAI-compatible model

OpenRouter by default. Point --base-url at OpenAI, a gateway, or a vLLM server in your own cloud without touching the sandbox code.

Reviewable output

The project is a git repository, so every run ends with git status and a full diff of exactly what the agent changed.

Put your agents in a sandbox

Coding agents, evaluation harnesses, or anything that runs model-written code. Talk to an engineer about running them next to your data.