All plugins

hermes-continuity-capture

Records Hermes lifecycle events (session, subagent, and kanban task) as Continuity schema-v2 events in a local SQLite spool under the plugin data directory, and can forward them to a NATS/JetStream server you run yourself. Disclosure - binds nine lifecycle hooks and writes SQLite (spool_path defaults to spool.db in the plugin data directory, 90-day retention, periodic sweep; the file grows with event volume); free-text fields (prompts, tool results, args, summary, reason, tool_call_history) are always dropped before the INSERT and only their length is kept (there is no setting that keeps them). The optional NATS password is read from the environment variable HERMES_CONTINUITY_CAPTURE_NATS_PASSWORD, never from config.yaml. Delivery is opt-in: the default publish_mode is spool-only (nothing leaves the host); in core/jetstream mode a background thread publishes to your own NATS endpoint using the bundled standard-library client, and failed deliveries stay as error rows and are retried. Only the NATS server itself is external - it is not part of this plugin. Inactive until an operator enables it. Disclosure — binds nine lifecycle hooks and writes a SQLite spool (default spool.db in the plugin data directory, 90-day retention sweep) holding event type, profile/agent id, host FQDN, process id and start time, session/subagent/task ids and tool names; prompts, tool args/results, summaries, reasons and tool_call_history are always dropped before writing and only their lengths kept. Default publish_mode is spool-only (nothing leaves the host); in the opt-in core/jetstream modes a background thread sends those events to the NATS server you configure in nats_url (default 127.0.0.1) using the bundled standard-library client, and unless nats_tls is on or the URL uses tls:// (TLS is off by default) the NATS user and password travel in plaintext.

GoitonthefloorAutomationv0.2.2Updated 5 hours ago

About

Records Hermes lifecycle events (session, subagent, and kanban task) as Continuity schema-v2 events in a local SQLite spool under the plugin data directory, and can forward them to a NATS/JetStream server you run yourself. Disclosure - binds nine lifecycle hooks and writes SQLite (spool_path defaults to spool.db in the plugin data directory, 90-day retention, periodic sweep; the file grows with event volume); free-text fields (prompts, tool results, args, summary, reason, tool_call_history) are always dropped before the INSERT and only their length is kept (there is no setting that keeps them). The optional NATS password is read from the environment variable HERMES_CONTINUITY_CAPTURE_NATS_PASSWORD, never from config.yaml. Delivery is opt-in: the default publish_mode is spool-only (nothing leaves the host); in core/jetstream mode a background thread publishes to your own NATS endpoint using the bundled standard-library client, and failed deliveries stay as error rows and are retried. Only the NATS server itself is external - it is not part of this plugin. Inactive until an operator enables it. Disclosure — binds nine lifecycle hooks and writes a SQLite spool (default spool.db in the plugin data directory, 90-day retention sweep) holding event type, profile/agent id, host FQDN, process id and start time, session/subagent/task ids and tool names; prompts, tool args/results, summaries, reasons and tool_call_history are always dropped before writing and only their lengths kept. Default publish_mode is spool-only (nothing leaves the host); in the opt-in core/jetstream modes a background thread sends those events to the NATS server you configure in nats_url (default 127.0.0.1) using the bundled standard-library client, and unless nats_tls is on or the URL uses tls:// (TLS is off by default) the NATS user and password travel in plaintext.

hermes-continuity-capture

A Hermes general plugin that records Hermes lifecycle events as Continuity schema-v2
events in a local SQLite spool, and can hand the validated events to a NATS/JetStream
server you run yourself. It is inactive until an operator enables it, and it ships no
credentials.

What it does

The plugin subscribes to a fixed set of Hermes hooks and turns each hook call into a
schema-v2 continuity event:

  • on_session_start / on_session_end / on_session_finalize -> hermes.session.started / hermes.session.ended
  • subagent_start / subagent_stop -> hermes.agent.started / hermes.agent.stopped
  • kanban_task_claimed / kanban_task_completed / kanban_task_blocked -> hermes.task.claimed / hermes.task.completed / hermes.task.blocked
  • post_tool_call -> subscribed, but intentionally not mapped to its own event type; it
    currently produces no spool entry (no isolated tool events by design).

Each event is redacted and validated, written to a SQLite spool file, and then a
background sender thread drains the spool. The default publish_mode is spool-only:
events stay in the local database and nothing is sent anywhere. Set publish_mode to
core or jetstream to deliver events to an external NATS server.

Requirements

  • Python 3.10 or newer (standard library only; no third-party runtime dependencies).
  • Only for publish_mode: core or jetstream: a reachable NATS server, with
    JetStream enabled for jetstream mode. The NATS server is not part of this plugin
    and must be deployed separately. In the default spool-only mode nothing external is
    needed.
  • Hermes >= 0.21.5, which is the version that exposes the kanban_task_* hook surface
    (kanban_task_claimed / kanban_task_completed / kanban_task_blocked) this plugin binds to.

Install

Copy this repository root into the plugin directory, then enable it explicitly. The
plugin does nothing on its own.

cp -r . ~/.hermes/plugins/hermes-continuity-capture

Then, as the operator:

hermes config set plugins.enabled '["hermes-continuity-capture", ...]'
sudo systemctl restart hermes-gateway.service

install-to-hermes.sh performs the copy step only. It never activates the plugin.

Configuration

Settings are read per key through ctx.get_config("<key>") (i.e.
plugins.entries.hermes-continuity-capture.settings.<key>), validated into
CaptureConfig (continuity_capture/config.py). Unset keys keep their default; an
invalid publish_mode fails loading with a ValueError.

| Field | Default | Meaning |
| --- | --- | --- |
| agent_id | active Hermes profile | Logical agent identity used in the event identity (ctx.profile_name). |
| host_identity | runtime hostname | Host identity; defaults to the runtime FQDN/hostname. |
| spool_path | spool.db in the plugin data dir | SQLite spool file. A relative path is resolved against the plugin data directory and must stay inside it; an escaping relative path is rejected. |
| publish_mode | spool-only | spool-only, core, or jetstream. Must be one of these. |
| spool_cap | 200000 | Maximum pending/accepted rows before the oldest are moved to given_up (backpressure). |
| retention_days | 90 | Age after which terminal spool rows (including error rows) are pruned. |
| retention_sweep_seconds | 3600 | Interval of the periodic retention sweep; <= 0 disables it. The sweep also runs once at startup. |
| send_retry_attempts | 5 | Delivery attempts before a row is given up. error rows are retried too. |
| exclude_tools | {} | Tool names for which post_tool_call metadata is skipped. |
| exclude_event_types | {} | Event types excluded from capture. |
| dedup_ttl_seconds | 300 | Window in which a repeated role-specific event is treated as a duplicate. |
| bridge_subject_events | hermes.continuity.events | NATS subject for main events. |
| bridge_subject_quality | hermes.continuity.quality | NATS subject for quality events. |
| nats_url | nats://127.0.0.1:4222 | URL of the external NATS server (used by core/jetstream only); a tls:// scheme also enables TLS. |
| nats_user | – | NATS user name (optional). |
| nats_password | – | NATS password. Declared as a secret in plugin.yaml with env: HERMES_CONTINUITY_CAPTURE_NATS_PASSWORD, so it is resolved through Hermes' secret route (the plugin never reads credential files itself) and never logged or echoed in errors. |
| nats_tls | false | Require TLS for the NATS connection. |
| jetstream_stream_name | hermes_continuity | JetStream stream to publish into (provisioned idempotently). |
| jetstream_duplicate_window_s | 120 | Server-side dedup window; each event carries Nats-Msg-Id = <event_id>. |

The spool lives under the plugin's own data directory (ctx.state.data_dir), not in the
process working directory.

NATS transport and TLS

nats_password is a secret: it is only read from the environment variable
HERMES_CONTINUITY_CAPTURE_NATS_PASSWORD (Hermes stores the value there when the field
is saved in the plugin's settings form), never from config.yaml and never from a
credential file. Set nats_tls: true for every nats_url that is not loopback —
without TLS the NATS user and password travel in plaintext. A tls://host:4222 URL
enables TLS as well, so the flag and the scheme are interchangeable.

Commands

/continuity-capture status   # spool counters, publish mode, transport state, last error
/continuity-capture flush    # wake the sender to retry pending and error rows now

Event types

The set of event types is a closed registry (continuity_capture/registry.py,
RESERVED_REGISTERED_TYPES). An event type must be listed there to be produced; the
registry is never grown at runtime from arbitrary hook names. A type that is not in the
list is rejected before it reaches the spool.

Privacy and safety guarantees

  • Redaction happens before the SQLite INSERT (continuity_capture/redact.py). The
    free-text fields user_message, result, args, summary, reason, and
    tool_call_history are dropped by default; only their length is kept as a
    non-sensitive signal in omitted_fields.
  • Free-text fields are always dropped; there is deliberately no setting that would keep
    prompts or tool results in the spool.
  • Runtime identity is a deterministic UUIDv5 derived from agent, host, process, and start
    time; IDs are never invented. If the required inputs are missing, no ID is produced and
    the event is marked incomplete instead.
  • Deduplication is role-specific. A repeated event is only collapsed when it is provably
    the same factual instance; missing or ambiguous keys disable deduplication. Parallel
    subagents are never merged into one.
  • Capture failures are isolated: a failing hook never blocks the agent run.
  • There is no silent fallback to the non-persistent core path when JetStream delivery
    fails. An event is only marked done after confirmed delivery; a failed delivery is
    recorded as an error row and retried.
  • The plugin is not active by default. Enabling it is an explicit operator action.

Tests

python3 -m pytest tests -q

The suite uses only the standard library and pytest, performs no network access (the NATS
transport is exercised against a local socket dummy), and writes every SQLite spool to a
temporary directory (it never creates data/spool.db in the repository).

License

MIT. See LICENSE.

README from the reviewed commit 0b7ca3b; it updates when the author re-pins.

More by Goitonthefloor

2 plugins by Goitonthefloor in the catalog.

Developer Mode

Explore built-in Hermes toolsets and actions.

HermesAgent

Developer?

Create a Hermes extension for Desktop or agent workflows.

Developer Section