Your agent should remember to check on you.
Most assistants wait. You ask, it answers, the thread closes — and the thing you mentioned on Tuesday (you were sick, you had a meeting, you bought something) never comes back.
hermes-autonomous is a proactivity layer for Hermes Agent:
it quietly reads your past conversations, notices what is worth returning to, and comes back at the
right moment — sometimes with a useful check (weather, price, a deadline), sometimes with nothing more
than "did your throat get better?"
It is not a digest. It is not a task list. It does not require you to configure what it should watch.
You don't install anything. Just tell your agent:
Install the plugin
xiaok/hermes-autonomous, enable it, configure it for this chat, and create the review cron job.
It installs the plugin, writes your local settings, copies the cron helpers and schedules the loop.
Nothing identifying lives in this repo — your ids end up in
~/.hermes/plugin-data/hermes-autonomous/settings.json (mode 0600), on your machine only.
Manual install — five commands (if your agent can't do it)
hermes plugins install xiaok/hermes-autonomous --enable
PLUGIN=~/.hermes/plugins/hermes-autonomous
python3 $PLUGIN/scripts/followups.py setup --owner-id <id> --dm-target telegram:<id>
cp $PLUGIN/cron/*.py ~/.hermes/scripts/
hermes cron create "*/15 * * * *" "Read $PLUGIN/prompts/review.md and follow it" \
--name "proactive follow-ups" --monitor-script followup-wake.py \
--script followup-digest.py --deliver local --failure-deliver origin--monitor-scriptis required. It is the wake gate; leave it out and the agent runs unconditionally every 15 minutes.--deliver localkeeps normal runs from posting anything to your chat — you only hear from the job if it fails (--failure-deliver origin). The follow-ups themselves already reach you as DMs viahermes send.- Optional debug switch:
followups.py setup --dev-logmakes each run reply with a short developer log (off by default;--no-dev-logturns it back off).
Don't know your Telegram id? Message @userinfobot, or ask Hermes — it can read the id of the conversation it is in.
From source (development)
git clone https://github.com/xiaok/hermes-autonomous.git ~/opt/hermes-autonomous
ln -s ~/opt/hermes-autonomous ~/.hermes/plugins/hermes-autonomous
hermes plugins enable hermes-autonomous
python3 ~/opt/hermes-autonomous/scripts/followups.py setup --owner-id … --dm-target …hermes plugins update hermes-autonomous
PLUGIN=~/.hermes/plugins/hermes-autonomous
python3 $PLUGIN/scripts/followups.py doctor --fixJobs created by older versions may lack --monitor-script (the agent then runs every 15 minutes no
matter what) or use --deliver origin (every run posts its final reply to your chat). doctor --fix
corrects the job in place with hermes cron edit — it never deletes or recreates it. If there is no
job at all, it prints the commands to create one. Without --fix it only reports.
every 15 min a cheap script asks "is anything worth waking up for?" ~0 tokens
when yes read the last hours of conversation, update the board
check the weather / price / page / calendar
decide: stay silent · act and report · ask first
at most one message, at most three items
Four things have to be true before it speaks:
| Gate | Rule |
|---|---|
| Due | that specific thing is worth revisiting now — not a fixed 9am digest |
| New | something changed since you last talked about it; a repeat is not a follow-up |
| Sourced | it can quote what you actually said; no source, no message |
| Rationed | ≤3 items and ≤6 lines per message, 90-minute cooldown, silence 23:00–08:00 |
The first three are judgment calls the agent makes against the rubric. The last one is enforced in
code: every DM goes out through followups.py send, which refuses at night, during the cooldown,
for more than 3 items or more than 6 lines. A refused message is not sent and not shortened — that
run simply ends without one. The cooldown also means one message per wake at most.
And the reason it does not become noise: your reactions are written back. At the start of each
review the agent records how you reacted to what it sent in the last 48 hours (accepted,
ignored, annoyed, useless). Within 30 days, one annoyed or three ignored on sent items mute
that whole category (care / utility / risk / curiosity): its due items no longer wake a
review, the digest marks them held, and send refuses them. Muting only happens once those outcomes
have been recorded; followups.py why shows what is muted.
- Utility — the meeting is tomorrow: here is the weather and when to leave.
- Care — you said your throat hurt. Two days later: "better?" No action value at all, and still the most important message it can send.
That is why the decision runs on two separate scoring lines. Judging only by "is this actionable" silently deletes every caring message.
We read the post-mortems so you don't have to. ChatGPT Pulse was retired nine months after launch: its own limitation note admitted it kept suggesting work you had already finished, and v1 shipped with no off switch. The pattern behind every dead proactive assistant is the same — fixed schedules, no completion write-back, configuration pushed onto the user.
This one binds to events, writes every outcome back, and asks for nothing but a yes/no answer in chat.
The full teardown and the research numbers (the best models score ~66% F1 on "should I speak", with
35–48% precision) are in docs/RESEARCH.md (Chinese) and
docs/teardown.md (Chinese).
prompts/decide.md— the rubric: what counts as worth returning to, the two scoring lines, the three action tiers.scripts/decide.py— run any scenario offline and see the exact judgment:python3 scripts/decide.py --scenario scenarios/01-throat.jsondocs/DECIDER.md(Chinese) — inputs, gates, output schema.
The conversations in scenarios/ are made-up examples; they do not belong to any real user.
- Only sessions that belong to your user id are read, and by default only your DM with Hermes:
your messages there and Hermes' replies. Group chats, threads, forum topics and channels
(Discord/Slack threads, Telegram forum-group topics — i.e. any session Hermes records as
chat_type='group','thread','forum'or'channel'; a Telegram private-chat topic stays'dm') are off unless you runfollowups.py setup --include-groups— and once on, everything in those sessions is read, including what other members wrote there. - State lives in
~/.hermes/plugin-data/hermes-autonomous/(SQLite + settings, mode 0600), never in the repo. - The repo ships with no ids, names, chats or personal scenarios — you configure them locally.
- Reads the Hermes session database
~/.hermes/state.db— read-only, only sessions owned by your user id: user and assistant turns in your DM; group, thread, forum and channel sessions (all members' messages) only withinclude_groups. - Reads Hermes' cron job store
~/.hermes/cron/jobs.json(read-only) whendoctorruns — also once at the end ofsetup— to find this plugin's job. If the store can't be read it falls back tohermes cron list. Besides that it reads only its own settings. - Writes its own data directory
~/.hermes/plugin-data/hermes-autonomous/(SQLite board +settings.json, mode 0600; plus asend.lockfile). - Copies the two cron helpers (
cron/followup-wake.py,cron/followup-digest.py) into~/.hermes/scripts/at install time — your agent does this, or you do with thecpabove. That is where the job's--script/--monitor-scriptnames are looked up. - Modifies its own cron job with
doctor --fix:hermes cron edit <id> --monitor-script … --deliver local --failure-deliver originon the job it recognises as this plugin's. Never another job, never delete or recreate; without--fixit only reports. - Network: the plugin code makes no requests. During a review your agent may look things up (weather, prices, news) using Hermes' own tools — that traffic belongs to Hermes, not to this plugin.
- Shell:
/followupsruns one local Python helper (scripts/followups.py) withsys.executable; the cron helpers are plain Python.followups.pystartshermesin two places:doctor(hermes cron listas the fallback above,hermes cron editwith--fix) andfollowups.py send, which runshermes sendto deliver the DM after its gates pass. During a review the agent itself uses its terminal tool to run this plugin's helpers (followups.py digest,followups.py send,followups.py apply, …). The offline toolscripts/decide.pycallshermes -zfor one tool-less model call — only when you run it yourself. No hook, no background thread, no approval bypass. - Credentials: none. Your Telegram ids live in the plugin's own
settings.json(0600) — not in.env,auth.jsonor any keychain. - No telemetry, no analytics.
中文说明 · Design (Chinese) · Research (Chinese) · Decider (Chinese) · Teardown (Chinese)
Tested with Hermes Agent 0.22.2 (requires_hermes: ">=0.22.2").
MIT.