Proactive-agent governance, durable goals, and self-adjusting cadence for the Hermes agent framework — a @refix/proactivity adapter.
Project description
proactivity-hermes
A Hermes plugin that adds the
@refix/proactivity primitives a stock agent lacks:
- Governance envelope: every governed tool call passes through idempotency, a per-tick action cap, and pluggable soft caps before it fires, with a full audit trail. Point it at the tools your agent actually uses to act on the world (a Discord post, a Feishu reply, a custom outbound tool).
- Durable goals: a goal portfolio with lifecycle (active → paused →
completed → archived) and done-conditions. Complements Hermes's
MEMORY.md(facts) and Skills (procedures); it doesn't replace them. - Self-adjusting cadence: a
set_cadencetool that (re)schedules the next proactive tick through Hermes's own cron.
Hermes already provides the agent loop, memory, gateways, and scheduler. This plugin layers governance and goals on top of that machinery; it is an adapter, not a second framework.
Install
Option A — Agent-assisted (recommended)
Tell your Hermes agent:
Install and enable the proactivity plugin: run `pip install proactivity-hermes`, then `hermes plugins enable proactivity`. Confirm both commands succeeded.
Option B — Manual
pip install proactivity-hermes
hermes plugins enable proactivity
Either way, enabling registers three tools (goal, briefing, set_cadence). Naming your
outbound tools in PROACTIVITY_GOVERNED_TOOLS additionally wraps them in a
tool_execution middleware that routes their calls through the envelope.
How it works
| Concern | Mechanism |
|---|---|
| New tools | ctx.register_tool(..., toolset="proactivity") |
| Govern outbound | ctx.register_middleware("tool_execution", …) wrapping the tools in PROACTIVITY_GOVERNED_TOOLS: allow = next_call(args), deny = return a denial result, so the agent sees why it was blocked |
| Cadence | cron.create_job (the same scheduler hermes cron uses) |
| Storage | a private SQLite db at ~/.hermes/proactivity.db (goals + attempt ledger) |
Governance is interception, not name-shadowing: the agent calls a tool it already has; the middleware routes that call through the envelope transparently.
Configuration
Set via environment variables (sensible defaults shown):
| Variable | Default | Meaning |
|---|---|---|
PROACTIVITY_PER_TICK_CAP |
5 |
Max actions taken per tick before the cap denies further ones |
PROACTIVITY_GOVERNED_TOOLS |
(none) | Comma-separated tool names to govern. Empty by default, so governance is opt-in (see Limitations). Set it to your agent's real outbound tools, e.g. discord. Warns if a name isn't a registered tool. |
PROACTIVITY_TICK_SECONDS |
60 |
Width of a "tick" bucket; the scope of the per-tick cap and idempotency |
PROACTIVITY_RECENT_CONTACT_THRESHOLD |
2 |
Soft-cap: hold a send after this many recent contacts to the same recipient |
PROACTIVITY_DRY_RUN |
false |
Record actions as pending_approval instead of performing them |
PROACTIVITY_FAIL_CLOSED |
false |
If governance itself errors (e.g. its store is unavailable), block the tool call instead of letting it through |
PROACTIVITY_ENTITY_ID |
hermes |
Governance scope (for a single personal agent, leave as-is) |
Limitations (honest)
- Cadence is minute-granular. Hermes's cron ticks on a 60s floor, so sub-minute cadence isn't expressible. The SDK's cadence is only first-class on infrastructure Refix controls; here it rides Hermes's cron.
- Ticks are time buckets, not turns. The per-tick cap and idempotency are
scoped to a
PROACTIVITY_TICK_SECONDSwindow, not to a Hermes session/turn. Good enough for a personal agent; upgrade to session-scoped ticks if you need exact per-turn semantics. - Governance fails open. If the envelope itself errors, the action proceeds (matching Hermes's own middleware posture) rather than muting the agent.
- Governance is opt-in; you name your outbound tools. It only fires for
tools the agent actually calls, and only those you list in
PROACTIVITY_GOVERNED_TOOLS(empty by default, so no tool is wrapped until you say so). There's no safe default: stock Hermes deliberately does not expose asend_messagetool to the model (a turn's reply is delivered as the response itself, not a tool call), and only you know which tool your agent sends through (discord,feishu_drive_reply_comment, a custom tool). The plugin warns at the first tool flow if a name you configured isn't a registered tool.
Develop
python3 tests/test_governance.py # governance + store logic, no Hermes needed
# the rest need `pip install hermes-agent` (they skip cleanly without it):
python3 tests/test_plugin_smoke.py # tools + governance via the real tool registry
python3 tests/test_middleware.py # override, routing, fail-open, real-tool govern, phantom warn, idempotency
python3 tests/test_cron.py # set_cadence fires AND re-arms via the real scheduler
python3 tests/test_plugin_load.py # plugin loads through real Hermes + entry point is discoverable
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file proactivity_hermes-0.2.0.tar.gz.
File metadata
- Download URL: proactivity_hermes-0.2.0.tar.gz
- Upload date:
- Size: 23.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b34a17fc888c1f92b0a47b60aec121af36475fcef07f9d485a44957cd33a4c6b
|
|
| MD5 |
a70dcdc4773a09713943813c8bf56a2c
|
|
| BLAKE2b-256 |
daaeb4d8bccefc539331d65c673bbcc55e2210ce29e4c8f5fea7285bb50b1a5f
|
Provenance
The following attestation bundles were made for proactivity_hermes-0.2.0.tar.gz:
Publisher:
release.yml on refixai/proactivity
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proactivity_hermes-0.2.0.tar.gz -
Subject digest:
b34a17fc888c1f92b0a47b60aec121af36475fcef07f9d485a44957cd33a4c6b - Sigstore transparency entry: 2112913176
- Sigstore integration time:
-
Permalink:
refixai/proactivity@f854090c8a5205a1b4e1792768d916dbe96b3aae -
Branch / Tag:
refs/tags/proactivity-hermes-v0.2.0 - Owner: https://github.com/refixai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f854090c8a5205a1b4e1792768d916dbe96b3aae -
Trigger Event:
push
-
Statement type:
File details
Details for the file proactivity_hermes-0.2.0-py3-none-any.whl.
File metadata
- Download URL: proactivity_hermes-0.2.0-py3-none-any.whl
- Upload date:
- Size: 19.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c69601df6225bb3d2e406eced02b6f0e6bf98e55b97974090aea05df85e5d2ce
|
|
| MD5 |
ee99f0e90e893a849f59a48b2f2b0429
|
|
| BLAKE2b-256 |
a041e87aaddb5c813ad75463e983e5eefd481b03e6c44cf5a075aeeb654fbab5
|
Provenance
The following attestation bundles were made for proactivity_hermes-0.2.0-py3-none-any.whl:
Publisher:
release.yml on refixai/proactivity
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
proactivity_hermes-0.2.0-py3-none-any.whl -
Subject digest:
c69601df6225bb3d2e406eced02b6f0e6bf98e55b97974090aea05df85e5d2ce - Sigstore transparency entry: 2112913218
- Sigstore integration time:
-
Permalink:
refixai/proactivity@f854090c8a5205a1b4e1792768d916dbe96b3aae -
Branch / Tag:
refs/tags/proactivity-hermes-v0.2.0 - Owner: https://github.com/refixai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f854090c8a5205a1b4e1792768d916dbe96b3aae -
Trigger Event:
push
-
Statement type: