SAVANT has privileged access to your VPS. This document explains every safety mechanism built in to prevent accidental damage.
Every WebSocket connection is locked until the owner sends a valid access code.
- The code is stored as a SHA-256 hash in SQLite — the plain text is never persisted
- All audio and commands are dropped until the code is verified
- Invalid codes receive
access_deniedand the connection is closed - Returning sessions: hash match → immediate unlock
- New sessions: hash saved → onboarding triggered
This prevents unauthorized voice access to the VPS, even if someone finds the WebSocket URL.
No destructive operation executes without explicit voice confirmation.
SAVANT must ask the owner before executing any of the following:
docker stop / restart / kill / rm / prune
systemctl stop / restart / disable
rm / mv / cp (when overwriting existing files)
truncate
userdel / useradd / passwd
DROP / TRUNCATE / DELETE (SQL)
iptables -D / -F
any flag: --force / -f / --remove / --delete / --purge
Flow:
- SAVANT says: "I'm going to stop the nginx container. Ready?"
- SAVANT stops speaking and waits
- Owner says: "oui" (or "yes", "ok", "go ahead")
- SAVANT executes
If the owner says "non", "cancel", or "not now" — the action is dropped, never queued.
Not required for: touch, mkdir on new paths, any read-only command.
Write and critical actions use a two-prong backend gate:
- First call → SAVANT asks, stores a pending confirmation marker with the current turn count
- Owner affirms in a new turn →
last_affirm_turnupdated - Either Gemini re-emits the action with
confirmed=true, or the backend fires it automatically confirmed=truewithout a new affirm turn → blocked — cannot be bypassed
Before every write or critical Hermes action, SAVANT automatically:
- Backs up the relevant file(s) to
/home/savant/backups/hermes/ - Stores the backup path in Redis (
savant:last_backup, 7-day TTL)
Undo by voice:
"Undo the last change"
"Revert what you just did"
This triggers execute_action(action_type="undo") which restores from the last backup.
SAVANT doesn't trust self-reports. After every write/critical action, Hermes must prove the change was applied.
The instruction always includes: [VERIFY — MANDATORY]
Hermes must end its response with:
VERIFICATION: VERIFIED— change confirmedVERIFICATION: NOT_VERIFIED — <reason>— something went wrong
The backend checks the exact first token after the colon. Vague language like "it should be done" or "appears to have worked" results in NOT_VERIFIED.
Verified actions are logged with verified=1 in the action_log table.
Certain command patterns are hard-blocked at the backend level — no confirmation can override them:
mkfs.* # format filesystem
wipefs # wipe filesystem signatures
dd of=/dev/ # direct disk write
rm -rf /etc # wipe system config
rm -rf / --no-preserve-root
reboot / shutdown / halt / poweroff # (in dangerous contexts)
:(){ :|:& };: # fork bomb
kill -9 1 / kill -9 -1 # kill init
These patterns trigger an immediate block with a clear error message. The command is never sent to Hermes.
- API keys: stored only in
.envandhermes-agent.env— both gitignored, never committed - Workflow auth keys: stored in SQLite, never returned in
list_workflows()output, never spoken - Access code: stored as SHA-256 hash only
- Secrets in logs: the system prompt instructs Gemini to never speak secrets
- Redis: credentials only in
.env, Redis itself contains no sensitive data
Protects:
- All
/control/*REST endpoints (pause, stop, resume, status) - Hermes internal API calls
- The Console Live exec server (
:8644)
Use a strong random string: openssl rand -hex 32
Every Hermes action is logged in SQLite action_log:
action_type(read/write/critical/undo)descriptionstatus(success/error)duration_sverified(0/1)created_at
Every write/critical action is also appended to HERMES_CHANGELOG.md:
## 2026-06-04 14:32 UTC — [write] Updated nginx config | Result: ok
By design:
- No subprocess from the backend — all VPS access goes through Hermes
- No unauthenticated control —
/control/*requires the shared secret - No format/wipe operations — hard-blocked regardless of confirmation
- No interactive TTY programs — vim, top, htop are blocked in Console Live
- No secret echo — workflow auth keys and API keys are write-only