Example running Hermes Agents in a Sandbox with Sidecars#1587
Conversation
| f"mkdir -p /root/.ssh && ssh-keygen -q -t ed25519 -N '' -f {SSH_KEY}", | ||
| ) | ||
| pubkey = sb.filesystem.read_text(f"{SSH_KEY}.pub") | ||
| tools.filesystem.write_text(pubkey, "/root/.ssh/authorized_keys") |
There was a problem hiding this comment.
🚩 filesystem.write_text argument order could not be verified
All three filesystem.write_text calls at lines 271, 301, and 327 use (data, path) argument ordering — e.g. tools.filesystem.write_text(pubkey, "/root/.ssh/authorized_keys"). Many filesystem APIs conventionally use (path, data) ordering instead. I installed modal==1.5.0 to check but filesystem is a runtime property and the signature wasn't directly inspectable from the class. The author likely knows the correct API, and all three calls are internally consistent, but a reviewer with access to the Modal SDK source should confirm the parameter order is correct. If reversed, the agent would silently write garbage files and fail during bootstrap.
Was this helpful? React with 👍 or 👎 to provide feedback.
| .apt_install("git", "curl", "openssh-client", "rsync") | ||
| # python-multipart: needed by the dashboard's kanban plugin API routes, | ||
| # which fail to load without it | ||
| .uv_pip_install(f"hermes-agent[web,pty]=={HERMES_VERSION}", "python-multipart") |
There was a problem hiding this comment.
🟡 Unpinned python-multipart dependency violates repository pinning rules
python-multipart is installed without a version pin on line 97. The repository's internal/CLAUDE.md:59-66 and .github/pull_request_template.md:45-46 both require all container dependencies to be pinned: packages with version < 1.0 must be pinned to patch version ==0.y.z. Other examples in the repo already pin this package, e.g. 06_gpu_and_ml/world-models/text_to_world.py:497 uses python-multipart==0.0.20.
| .uv_pip_install(f"hermes-agent[web,pty]=={HERMES_VERSION}", "python-multipart") | |
| .uv_pip_install(f"hermes-agent[web,pty]=={HERMES_VERSION}", "python-multipart==0.0.20") |
Was this helpful? React with 👍 or 👎 to provide feedback.
| sb.exec( | ||
| "sh", | ||
| "-c", | ||
| f"while true; do sleep 60; {sync} {HERMES_HOME}/ {STATE_MOUNT_POINT}/hermes/; done" | ||
| " >>/var/log/state-sync.log 2>&1", | ||
| ) |
There was a problem hiding this comment.
🚩 Fire-and-forget sb.exec() calls for background daemons discard process handles
At lines 306-311 and 317-321, sb.exec() is called for the state-sync loop and the dashboard daemon respectively, but the returned ContainerProcess handles are discarded. This is intentional per the comment at lines 313-315 ("the processes belong to the Sandbox, not to our local handles"), but it means there's no way for the bootstrap code to detect if these daemons crash immediately after starting. The dashboard is indirectly validated by the wait_for curl check at line 324-329, but the state-sync loop at line 306-311 has no such validation — a typo in the rsync command or path would silently fail, and state would never be persisted to the Volume.
Was this helpful? React with 👍 or 👎 to provide feedback.
Deploy with
Type of Change
/docs/examples)Monitoring Checklist
lambda-test: falseis provided in the example frontmatter and I have gotten approval from a maintainermodal run, or an alternativecmdis provided in the example frontmatter (e.g.cmd: ["modal", "serve"])cmdwith no arguments, or theargsare provided in the example frontmatter (e.g.args: ["--prompt", "Formula for room temperature superconductor:"]fastapito be installed locally (e.g. does not importrequestsortorchin the global scope or other code executed locally)Documentation Site Checklist
Content
modal-cdn.comBuild Stability
v1, not a dynamic tag likelatestpython_versionfor the base image, if it is used~=x.y.zor==x.y, or we expect this example to work across major versions of the dependency and are committed to maintenance across those versionsversion < 1are pinned to patch version,==0.y.zOutside Contributors
You're great! Thanks for your contribution.