Known Limitations
Enforcement gaps
Section titled “Enforcement gaps”- No true mid-call abort. The in-flight response completes and is billed. The tool-gate stops further work, not the current call.
- Text-only sessions. A session generating only text (no tool calls) never
hits
pre_tool_call. No enforcement possible. Apre_llm_callabort for cron jobs would require Hermes to honor it (it currently doesn’t). on_estimated.mode: warn_onlyis the default. Hard verdicts based on estimated data degrade to soft. Users with reliable providers should setmode: enforce.
Subagent attribution
Section titled “Subagent attribution”per_cron_jobbudgets now attribute delegated (async/nested) subagent spend back to the cron job that started the delegation chain, via thesubagent_edgestable and a recursive CTE indb.spend_by_scope(schema v11, issue #49).globalremains the cap that captures literally everything, including any edge that fails to resolve.runs.parent_session_idstays dormant by design —subagent_edgesis the persistent, single source of truth for the delegation tree, so there is no need to populate the column retroactively.- Since v18 the parent side of an edge also joins to the parent’s own calls
(
llm_calls.turn_id = subagent_edges.parent_turn_id). Filter the left side (parent_turn_id > '') — see§ Turn identity and the failure ledger. - Phase-1 boundary: this is reporting/aggregation correctness only. A
detached async child still self-enforces only against
globalwhile it runs; in-path enforcement that pauses a runaway child mid-flight is a planned Phase 2.db.unattributed_child_costflags, at query time, child spend whose parent edge never resolves to a real root.
MoA reference-model tokens
Section titled “MoA reference-model tokens”- A MoA turn runs N reference models plus the aggregator per iteration, but only
the aggregator fires a hook. Reference-model tokens are never captured
(auxiliary
call_llmfires no hooks), so a MoA session’s recorded cost is a lower bound./statsand the dashboard flag MoA calls (moa_calls/moa_preset) so the gap is visible. See§ Mixture of Agents (MoA).
MoA one-shot (/moa <prompt>) is entirely invisible — by Hermes’ design
Section titled “MoA one-shot (/moa <prompt>) is entirely invisible — by Hermes’ design”- The
/moaslash command (the one-shot path,decode_moa_turn→conversation_loop.py:827) runs both the reference models and the aggregator through the auxiliarycall_llmpath, then injects their synthesis as context into the real main model call. Only that final main-model call firespost_api_request. So on this path telemetry records zero MoA cost — not even the aggregator — and themoa_calls/moa_presetmarkers are never set. This is not a plugin gap we can close: no hook fires for either MoA call type here (verified againstagent/moa_loop.py::aggregate_moa_contextandagent/auxiliary_client.py, which has no hook dispatch). - The re-attribution in v10 (
moa.py) therefore applies only to the preset-as-model path (/model <preset> --provider moa), where the aggregator is the returned main response and does fire the hook. Selecting a preset as your model is the only way MoA usage reaches telemetry at all.
Pricing
Section titled “Pricing”- Auto-refresh covers OpenRouter models (via API) and Google AI Studio (static
table). Anthropic, OpenAI direct-API pricing requires manual
pricing.yamlentries or a newPricingSourcesubclass. GoogleAISourceis a constant table. It will drift without manual quarterly updates. SeeLAST_VERIFIEDinpricing_refresh.py::GoogleAISource.- Gemini tiered-pricing models (
gemini-2.5-pro,gemini-3.1-pro-preview) use the ≤200k context tier. Usage above 200k is undercounted.
DB retention
Section titled “DB retention”telemetry.db grows without bound. No automatic purge. For >100K rows, consider
manual cleanup.
hermes-telemetry is an independent community plugin for Hermes Agent. It is not affiliated with or endorsed by Nous Research.