Hook Pipeline
The plugin registers 12 Hermes hooks. Here is what each one does and why it was chosen:
Hook Purpose────────────────────────────────────────────────────────────────────────────on_session_start Create runs row, extract cron_job_id from session_id. Fired ONCE per new session (not per turn).
pre_api_request Stash approx_input_tokens keyed by (session_id, call_count) for the fallback estimator when usage=None.
post_api_request PRIMARY TOKEN SOURCE. One call per individual API call within a turn. Carries the usage dict with real token counts. Calculates cost, records llm_calls row (incl. turn_id / task_id / api_request_id, schema v18), updates runs totals.
api_request_error (1) Records EVERY API failure per attempt in the llm_call_errors ledger — any status, retryable or not (schema v18). (2) Captures 404 "model removed / unavailable" errors to power the model-unavailable alert. NO token data.
post_tool_call Records tool name, success/failure, latency, and (v18) the turn_id + tool_call_id it belongs to. Also records a proxy row for delegate_task/subagent calls (no token data there, just a count).
post_llm_call Fires once per turn after the tool loop. NO token data. Used only to keep runs.ended_at current during multi-turn interactive sessions.
subagent_start Records the parent→child delegation edge (subagent_edges) so subagent cost attributes to the root cron_job. Fires synchronously before the child dispatches. NO token data.
subagent_stop Records a synthetic tool_call row ("delegate_task/subagent") for proxy count of subagent invocations, and finalizes the subagent_edges row (stopped_at + child_status). NO token data.
on_session_end Fires at the end of every run_conversation() call. Sets final status: ok / error / interrupted.
on_session_finalize Safety net for true session teardown (CLI atexit, gateway expiry). Ensures status is "ok" if not already set.
pre_llm_call (1) Attaches sender_id to the run for per-sender budgets. (2) Injects one-time-per-window soft budget alert into the conversation context (`enforce` mode only). (3) Injects one-shot free→paid transition warning when the current model was previously seen as free but is now incurring cost.
pre_tool_call Hard budget enforcement. Returns {"action":"block",...} if any scope is in hard breach. Also triggers cron pause. Only registered in `enforce` mode (the default); in `observe` mode the hook is never registered.Why post_api_request is the primary token hook: Hermes can make multiple
API calls per turn (retries, tool-call rounds, reasoning). Only post_api_request
fires per individual API call and carries the usage dict. The pre_/post_llm_call
hooks fire once per turn and have no token data. This design was discovered from
the source (not guessable from the hook names alone).
Why not capture budget in post_api_request: Token counts have just been
recorded but verdict cache is stale. The tool-gate in pre_tool_call is the
right place — it fires synchronously before the next tool and has a fresh view
of accumulated spend.
hermes-telemetry is an independent community plugin for Hermes Agent. It is not affiliated with or endorsed by Nous Research.