Bug Description
This endpoint returned error
[webui] ERROR GET /api/crons
Traceback (most recent call last):
File "/app/server.py", line 382, in do_GET
result = handle_get(self, parsed)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/api/routes.py", line 13510, in handle_get
active_jobs, other_jobs = _cron_jobs_cross_profile(active_profile)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/api/routes.py", line 1459, in _cron_jobs_cross_profile
from cron.jobs import list_jobs
File "/home/hermeswebui/.hermes/hermes-agent/cron/__init__.py", line 18, in <module>
from cron.jobs import (
File "/home/hermeswebui/.hermes/hermes-agent/cron/jobs.py", line 42, in <module>
from utils import atomic_replace, atomic_write_text
ImportError: cannot import name 'atomic_write_text' from 'utils' (/app/venv/lib/python3.12/site-packages/utils.py)
Using hermes-agent latest on a docker container.
hermes-webui latest on another container, and that container calls the hermes-agent cron api on the other container. Resulting int his error. I think its a get request to get all available cron jobs.
This endpoint should return the cron jobs.
I've tried starting the container with this: /app/venv/bin/pip uninstall utils -y and it did not work.
Steps to Reproduce
- Start the multi container setup
- Error occurs when trying to use the crons api via hermes-webui.
Expected Behavior
Crons api should be working as expected.
Actual Behavior
Crons api raises exception:
[webui] ERROR GET /api/crons
Traceback (most recent call last):
File "/app/server.py", line 382, in do_GET
result = handle_get(self, parsed)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/api/routes.py", line 13510, in handle_get
active_jobs, other_jobs = _cron_jobs_cross_profile(active_profile)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/app/api/routes.py", line 1459, in _cron_jobs_cross_profile
from cron.jobs import list_jobs
File "/home/hermeswebui/.hermes/hermes-agent/cron/__init__.py", line 18, in <module>
from cron.jobs import (
File "/home/hermeswebui/.hermes/hermes-agent/cron/jobs.py", line 42, in <module>
from utils import atomic_replace, atomic_write_text
ImportError: cannot import name 'atomic_write_text' from 'utils' (/app/venv/lib/python3.12/site-packages/utils.py)
Affected Component
Gateway (Telegram/Discord/Slack/WhatsApp)
Messaging Platform (if gateway-related)
No response
Debug Report
Don't feel comfortable pasting this publicly.
But I can provide you anything else you need.
Operating System
Debian 14 "root@eac47d8c0095:/opt/hermes# cat /etc/os-release PRETTY_NAME="Debian GNU/Linux 13 (trixie)" NAME="Debian GNU/Linux" VERSION_ID="13" VERSION="13 (trixie)" VERSION_CODENAME=trixie DEBIAN_VERSION_FULL=13.4 ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/""
Python Version
No response
Hermes Version
No response
Additional Logs / Traceback (optional)
Here is my compose:
:
hermes-agent-personal:
#image: hermes-agent-local
image: nousresearch/hermes-agent:latest
#image: nousresearch/hermes-agent:v2026.5.16
shm_size: "1g"
container_name: hermes-agent-personal
user: root
restart: unless-stopped
#command: /bin/bash /home/hermes/.hermes/start_gateways.sh
command: gateway run
# command: >
# bash -c "apt-get update && apt-get install -y openssh-server
# && mkdir -p /var/run/sshd
# && echo 'root:YOUR_PASSWORD_HERE' | chpasswd
# && sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
# && /usr/sbin/sshd -D
# && gateway run"
ports:
- "8642:8642" # gateway API - default
- "8643:8643" # gateway API - investments
- "38109:9119" # dashboard (only reached when HERMES_DASHBOARD=1)
- "2223:22"
volumes:
#- ~/.hermes:/opt/data
# Persist config, state, sessions, skills, memory across restarts
- ${HERMES_HOME}:/home/hermes/.hermes
#- ${HERMES_WORKSPACE_BOOKS}:/home/hermes/.hermes/workspace/common/knowledge_base/BOOKS
#- ${HERMES_WORKSPACE_BOOKS}:/home/hermes/.hermes/workspace/common/knowledge_base/BOOKS:ro
#- /home/omv/.hermes:/home/hermes/.hermes
# Expose agent source so the WebUI can install dependencies from it
- hermes-agent-src-personal:/opt/hermes
#- hermes-uv-cache:/home/hermes/.cache/uv # ← add this
#- hermes-py-venv:/app/venv
# Run before Hermes starts
- ${HERMES_HOME}/03-install-deps:/etc/cont-init.d/03-install-deps:ro
# env_file:
# - /home/omv/.hermes_personal/.env
environment:
- HERMES_DASHBOARD=${HERMES_DASHBOARD}
- HERMES_DASHBOARD_TUI=${HERMES_DASHBOARD_TUI}
- HERMES_TUI_DIR=${HERMES_TUI_DIR}
- API_SERVER_ENABLED=${API_SERVER_ENABLED}
- API_SERVER_HOST=${API_SERVER_HOST}
- API_SERVER_KEY=${API_SERVER_KEY}
- GATEWAY_ALLOW_ALL_USERS=${GATEWAY_ALLOW_ALL_USERS}
- HERMES_HOME=${HERMES_AGENT_HOME}
- HERMES_UID=${HERMES_UID}
- HERMES_GID=${HERMES_GID}
- HERMES_DASHBOARD_INSECURE=${HERMES_DASHBOARD_INSECURE}
#- TERMINAL_CWD=${HERMES_AGENT_HOME}/workspace
- HERMES_DASHBOARD_BASIC_AUTH_USERNAME=${HERMES_DASHBOARD_BASIC_AUTH_USERNAME}
- HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH=${HERMES_DASHBOARD_BASIC_AUTH_PASSWORD_HASH}
- HERMES_DASHBOARD_BASIC_AUTH_SECRET=${HERMES_DASHBOARD_BASIC_AUTH_SECRET}
# Uncomment to forward specific env vars instead of using .env file:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- OPENAI_API_BASE_URL=${OPENAI_API_BASE_URL}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
deploy:
resources:
limits:
memory: 4G
cpus: "4.0"
networks:
- hermes-net-personal
hermes-webui-personal-investments:
image: ghcr.io/nesquena/hermes-webui:latest
#image: hermes-webui-local:latest
container_name: hermes-webui-personal-investments
user: root
shm_size: "1g"
ports:
# Expose on localhost only. Remove 127.0.0.1: to expose on all interfaces
# (set HERMES_WEBUI_PASSWORD if doing so).
- "38111:8787"
volumes:
# Same hermes home as the agent — shares config, sessions, state
- ${HERMES_HOME_INVESTMENTS}:/home/hermeswebui/.hermes
# Agent source mounted where docker_init.bash expects it.
# Mounted read-only — the WebUI only reads this volume to install
# the agent's Python dependencies at startup (`uv pip install`).
# Read-only enforces that defence-in-depth at the kernel layer.
- hermes-agent-src-personal:/home/hermeswebui/.hermes/hermes-agent:ro
# Workspace directory — browse and edit files from the WebUI.
# Adapt the host path to your project directory.
# ${HOME} is used rather than `~` so the default resolves the same way
# across Linux, macOS, WSL2, and Docker Desktop on Windows.
- ${HERMES_HOME}/profiles/investments/workspace:/workspace
- hermes-uv-cache:/uv_cache # ← add this
- hermes-py-venv:/app/venv
# env_file:
# - /home/omv/.hermes_personal/.env
environment:
- HERMES_WEBUI_HOST=${HERMES_WEBUI_HOST}
- HERMES_WEBUI_PORT=${HERMES_WEBUI_PORT}
- HERMES_WEBUI_STATE_DIR=${HERMES_WEBUI_STATE_DIR_INVESTMENTS}
- HERMES_WEBUI_PASSWORD=${HERMES_WEBUI_PASSWORD}
- HERMES_HOME=${HERMES_WEBUI_HOME}
# Match your host user's UID/GID for correct file permissions.
# Run `id -u` and `id -g` to find your values.
# On macOS, UIDs start at 501 (not 1000) — set these in a .env file:
# echo "UID=$(id -u)" >> .env && echo "GID=$(id -g)" >> .env
- WANTED_UID=${HERMES_UID}
- WANTED_GID=${HERMES_GID}
# NOTE: When using bind-mount volumes shared across containers, ALL containers
# that write to the same host directory must run as the same UID/GID.
# If hermes-agent initialises the state dir as root (UID 0), hermes-webui
# will get a PermissionError accessing those paths — including a crash on every
# HTTP request if the auth signing-key file is unreadable. Either set WANTED_UID
# to match the agent container's UID, or use a named Docker volume (preferred).
# Optional: set a password for remote access
# - HERMES_WEBUI_PASSWORD=your-secret-password
# Bind-mount permission handling for the WebUI (fixes #1389, #1399).
# NOTE: WebUI's HERMES_HOME_MODE is a credential-file threshold (allow
# group bits on .env/.signing_key/etc.), DIFFERENT from the agent's
# which applies to the HERMES_HOME directory itself. 0640 is correct
# for the WebUI; do NOT copy this value to the agent service block.
# - HERMES_SKIP_CHMOD=1
# - HERMES_HOME_MODE=0640
- HERMES_API_URL=${HERMES_API_URL_INVESTMENTS}
- GATEWAY_HEALTH_URL=${HERMES_API_URL_INVESTMENTS}
- HERMES_WEBUI_CHAT_BACKEND=gateway
restart: unless-stopped
networks:
- hermes-net-personal
depends_on:
- hermes-agent-personal
command: >
/bin/sh -c "
apt-get update &&
apt-get install -y nodejs npm passwd &&
export PATH=/usr/sbin:/usr/bin:/bin:$PATH &&
npm install -g @playwright/test &&
npm install -g @playwright/cli@latest &&
npx playwright install --with-deps &&
npx -y patchright-mcp@latest &&
npm install -g @icoretech/warden-mcp@latest &&
curl -LsSf https://astral.sh/uv/install.sh | sh &&
export PATH=$HOME/.local/bin:$PATH &&
. /root/.local/bin/env &&
uv tool install mcp-server-linkedin@latest &&
uv tool install zulipchat-mcp &&
uv tool install patchright &&
uv tool update-shell &&
/app/venv/bin/pip uninstall utils -y &&
export PATH=$HOME/.local/bin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH &&
/hermeswebui_init.bash
"
networks:
hermes-net-personal:
driver: bridge
volumes:
# IMPORTANT — upgrading the agent image:
# The `hermes-agent-src` volume is initialised from the agent image's
# `/opt/hermes` on first `up`, and Docker reuses the volume verbatim on
# later runs — even after `docker pull` of a newer agent image. After
# upgrading the agent image, run:
#
# docker compose -f docker-compose.three-container.yml down
# docker volume rm <project>_hermes-agent-src
# docker compose -f docker-compose.three-container.yml pull
# docker compose -f docker-compose.three-container.yml up -d
#
# The full procedure (and why) is documented in docs/docker.md.
hermes-agent-src-personal:
hermes-uv-cache: # ← and declare it
hermes-py-venv:`
Root Cause Analysis (optional)
The recreated-volume result shows cron, cron.jobs, and utils all resolving from the WebUI venv's site-packages. That rules out the earlier stale-volume/path-order hypothesis. The packaged Hermes Agent cron module is importing an unqualified top-level utils, and the installed environment resolves an unrelated package by that name instead of the Agent-owned atomic-write helper. Uninstalling arbitrary utils packages is not a durable WebUI fix.
The correct boundary is upstream packaging/import ownership: use a package-relative Agent utility import (or package the helper under an unambiguous Agent namespace), with a clean-wheel regression that imports cron.jobs in an environment where an unrelated utils distribution is installed. I removed needinfo and needs-reproduction; keeping investigation, priority, docker, and upstream-change while that upstream fix is routed.```
See more here on issue created in hermes-webui which determined a hermes-agent issue. https://github.com/nesquena/hermes-webui/issues/6811#issuecomment-5227884743
### Proposed Fix (optional)
_No response_
### Are you willing to submit a PR for this?
- [ ] I'd like to fix this myself and submit a PR
Bug Description
This endpoint returned error
Using hermes-agent latest on a docker container.
hermes-webui latest on another container, and that container calls the hermes-agent cron api on the other container. Resulting int his error. I think its a get request to get all available cron jobs.
This endpoint should return the cron jobs.
I've tried starting the container with this:
/app/venv/bin/pip uninstall utils -yand it did not work.Steps to Reproduce
Expected Behavior
Crons api should be working as expected.
Actual Behavior
Crons api raises exception:
Affected Component
Gateway (Telegram/Discord/Slack/WhatsApp)
Messaging Platform (if gateway-related)
No response
Debug Report
Operating System
Debian 14 "root@eac47d8c0095:/opt/hermes# cat /etc/os-release PRETTY_NAME="Debian GNU/Linux 13 (trixie)" NAME="Debian GNU/Linux" VERSION_ID="13" VERSION="13 (trixie)" VERSION_CODENAME=trixie DEBIAN_VERSION_FULL=13.4 ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/""
Python Version
No response
Hermes Version
No response
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)