The traps
Each of these is a setting or a mechanism you can check tonight.
1 · Allow-all overrides everything
The gateway checks access in a fixed order: per-platform allow-all
→ DM-pairing approved list → platform allowlists → global allowlist → global
allow-all → deny. Allow-all comes first. Turn it on to skip pairing
while testing Discord, and every allowlist below it stops mattering. On a
public server, someone who joined nine seconds ago can then command an agent
with a terminal toolset and discord_admin. Test with
pairing from day one. Only use allow-all when everyone who can reach the bot is
someone you’d hand your laptop to.
2 · Without write approval, prompt injection sticks
Stages 2 to 4 of the prompts rely on the agent
rewriting its own skills with skill_manage. With
skills.write_approval off, a member’s message, or a pasted
“changelog” hiding instructions, can get the agent to edit a
SKILL.md or a scripts/ file. A bad reply is gone once sent. A
poisoned skill stays and runs again. A community bot reads
untrusted text all day, so keep the gate on, read the diffs, and keep
approvals.mode on manual until things settle.
3 · Memory is one screen long
MEMORY.md caps at 2,200 characters, USER.md at 1,375.
That’s all the memory sent with every prompt. Ask it to remember 300
people and each new fact silently pushes out an old one. Keep MEMORY.md as an
index (“notes live in the community-notes skill”), put member facts
in per-member files, and look up history with session_search. If
you reworded stage 1, this is why the bot keeps forgetting petra.
4 · session_search is keyword search
It’s SQLite FTS5 full-text matching, with no embeddings or vector store, whatever an AI summary told you. It finds “webhook” and misses “the callback thing broke”. Have the bot write notes in the community’s own words (stage 2). If you need semantic recall, add an external memory provider such as Mem0 or Honcho.
5 · Faking per-member memory leaks
Hermes doesn’t split memory by group-chat member. USER.md describes you, the owner. Tell the bot to “remember things about members” without the notes skill, and those facts go into the shared memory sent with every conversation. That’s how a WhatsApp DM detail turns up in public Discord. The “never quote a member’s file” rule helps, but the model follows it by convention and nothing enforces it. Don’t store anything you couldn’t stand to see misfiled.
6 · Always-on costs
A terminal agent bills when you type. A gateway agent bills when
anyone in three busy channels types, and each call carries the memory
and skill context. On a frontier model, a busy Discord week becomes a large
invoice, so put a cheap model on community duty. Nous Portal’s
web_search and browser tools are metered, which is partly why the
changelog skill uses curl. A weekly cron calling a metered tool is a
subscription you didn’t know you’d signed up for.
7 · Scripts run as you
On the default local terminal backend,
execute_code and skill scripts are unsandboxed
and run as your user, next to ~/.hermes/.env and your SSH keys.
Switch the terminal backend to docker: the container drops all
capabilities, sets no-new-privileges and caps processes, and the docs say
the container itself is the security boundary. Keep
approvals.deny globs too. The built-in blocklist catches
rm -rf / and little else.
8 · No mod tier
Access is all or nothing. Mods paired to your instance can do everything the
bot can, discord_admin and the terminal included. A prompt rule
like “only obey Dana for rewards” is a polite request. It blocks nothing. Give mods their own profile:
hermes profile create mods gives them a separate config with its
own toolsets, allowlist, approvals.deny and gateway. Keep the
powerful profile paired only to you.