Runtime overview
Beacon supports Hermes Agent through shell hook payloads sent tobeacon-hooks, with local session database sync for historical backfill.
Prerequisites
Before enabling Hermes Agent hooks, make sure:- Hermes Agent is installed for the user or its
config.yamlexists in the Hermes home directory (see Hermes home and profiles). beacon endpoint installhas run so shared endpoint config and runtime log paths exist.- Beacon hooks are installed with
beacon endpoint hooks install --harness hermes. - Hermes hook consent is handled for the session, especially in non-interactive gateway, cron, or CI runs.
- Hermes is restarted after hook install or removal so new sessions load the updated config.
Collection path
Beacon merges shell-hook entries into theconfig.yaml of the Hermes home directory, ~/.hermes/config.yaml by default. Hermes invokes Beacon’s hook adapter for supported lifecycle, prompt, tool, approval, and subagent events, and the adapter writes normalized endpoint events to the configured runtime JSONL log.
Beacon can also read Hermes Agent’s committed SQLite session store:
Sync Hermes Agent sessions
state.db (~/.hermes/state.db by default) locally and offline. It writes mapped events with harness.collection_method=poll, so it can recover historical sessions or sessions that ran before hooks were installed, but it cannot hold, approve, deny, or delay tool calls.
Discovery and status
Beacon detects Hermes through thehermes executable or the Hermes home directory, then checks that directory’s config.yaml for Beacon-managed commands, identified by the endpoint settings flags (--log, --config, --cli) or a legacy BEACON_ENDPOINT_MODE=1 prefix, together with --platform hermes.
Use beacon endpoint hooks status --harness hermes to inspect Hermes Agent hook status. Use beacon endpoint hermes status to inspect committed local sessions and how much Beacon has synced.
Install or configuration support
beacon endpoint install prepares shared endpoint config and runtime log paths. Install Hermes Agent hooks separately:
Install runtime hooks
Hermes home and profiles
Hook install, uninstall and status, discovery, inventory, and session status, sync and handoff all resolve one Hermes home directory, the one a plainhermes command uses:
- The base directory is
HERMES_HOMEwhen it is set in Beacon’s environment, trimmed, with a leading~/and$VAR/${VAR}references expanded, and a relative value taken from the current directory. Otherwise it is Hermes’s native root:~/.hermeson macOS/Linux or%LOCALAPPDATA%/hermeson Windows, withHERMES_DATA_DIR_SUFFIXappended when set. - A
HERMES_HOMEthat already names a profile,<root>/profiles/<name>, is used as it is. - Otherwise a sticky profile selected with
hermes profile use <name>, which Hermes records in<root>/active_profile, moves the home to<root>/profiles/<name>. The root is the native root whenHERMES_HOMEis unset or inside it, andHERMES_HOMEitself when it points elsewhere.
active_profile names a profile that is not a valid name or has no directory, Hermes refuses to start. Hook install, uninstall and status then return an error naming the profile, discovery reports Hermes as missing with the reason, and inventory leaves out the Hermes config. Session status, sync and handoff keep reading the base directory’s state.db.
A profile chosen for a single command with hermes -p <name> leaves nothing on disk, so Beacon cannot see it. Its hooks and sessions belong to <root>/profiles/<name>: run Beacon with HERMES_HOME set to that directory, or pass --db <path> to status/sync or --store-dir hermes=<path> to handoff.
The scheduled inventory job runs without your shell’s environment, so a per-user install or repair records HERMES_HOME (as an absolute path) and HERMES_DATA_DIR_SUFFIX in the job when they are set. It does not record the active profile, so the job follows a later hermes profile use on its own. If you change either variable later, run beacon endpoint repair from a shell that has the new value. System-mode installs record neither.
Telemetry coverage
Session database sync
beacon endpoint hermes sync reads committed rows from Hermes Agent’s state database after Hermes has written them. Session status, sync, and handoff use the state.db in the Hermes home directory, following HERMES_HOME and a sticky profile. Pass --db <path> to status/sync or --store-dir hermes=<path> to handoff to select a database explicitly.
Synced events record the Hermes home they were read from in harness.config_path and its profile in harness.profile: the <name> of a <root>/profiles/<name> home, and default otherwise.
The cursor is stored in Beacon endpoint state and advances by session message id. Each Hermes home has its own cursor file, so syncing one profile or store never advances another’s cursor: the native root (~/.hermes) keeps hermes.json, and any other home, a profile or a custom HERMES_HOME, uses hermes-<profile>-<id>.json, where <id> is derived from the home’s path. The home a default sync resolves to starts its keyed cursor from hermes.json, which every default sync advanced before cursors were keyed, so upgrading does not re-collect it. Any other home starts with a new cursor the first time it is synced this way, so its retained history is collected once more. Use --print to preview mapped events without writing the runtime log or advancing the cursor.
Synced events take their event.id from the session id, the Hermes message id and the kind of event, so syncing a session again names its events the same way. A cloned profile starts from a copy of the original home’s state.db, so both homes hold the same session ids, and once the copies diverge their message ids count up independently. To keep the two homes from writing different events under one id, hermes-session-homes.json, beside the cursor files, records which home first synced each session id. That home keeps the ids above. Any other home that syncs a session with the same id for the first time derives that session’s ids from its own path as well, and beacon endpoint hermes status marks such sessions ids keyed by home (ids_keyed_by_home in --json). A session keeps the ids it was first synced with, so a session two homes had both synced before this file existed keeps its original ids in both. A --print dry run claims no session for its home.
For scheduled collection, run beacon endpoint hermes sync --watch, or run one-shot sync from your scheduler. Live hooks remain the real-time path.
Deployment notes
Hermes prompts for first-use consent for each(event, command) hook pair. For non-interactive gateway, cron, or CI runs, set HERMES_ACCEPT_HOOKS=1, start Hermes with --accept-hooks, or configure hooks_auto_accept: true in the Hermes home directory’s config.yaml.
Beacon preserves existing Hermes settings and non-Beacon hooks when installing or uninstalling Hermes telemetry. It replaces only Beacon-managed Hermes hook commands.
Restart Hermes after installing or removing hooks so new sessions pick up the updated configuration.
Related
Supported agent harnesses
Return to the runtime support overview.
Hooks
Install, inspect, and uninstall runtime hook integrations.