Skip to content

Known Limitations

  • 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. A pre_llm_call abort for cron jobs would require Hermes to honor it (it currently doesn’t).
  • on_estimated.mode: warn_only is the default. Hard verdicts based on estimated data degrade to soft. Users with reliable providers should set mode: enforce.
  • per_cron_job budgets now attribute delegated (async/nested) subagent spend back to the cron job that started the delegation chain, via the subagent_edges table and a recursive CTE in db.spend_by_scope (schema v11, issue #49). global remains the cap that captures literally everything, including any edge that fails to resolve.
  • runs.parent_session_id stays dormant by design — subagent_edges is 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 global while it runs; in-path enforcement that pauses a runaway child mid-flight is a planned Phase 2. db.unattributed_child_cost flags, at query time, child spend whose parent edge never resolves to a real root.
  • 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_llm fires no hooks), so a MoA session’s recorded cost is a lower bound. /stats and 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 /moa slash command (the one-shot path, decode_moa_turn → conversation_loop.py:827) runs both the reference models and the aggregator through the auxiliary call_llm path, then injects their synthesis as context into the real main model call. Only that final main-model call fires post_api_request. So on this path telemetry records zero MoA cost — not even the aggregator — and the moa_calls / moa_preset markers are never set. This is not a plugin gap we can close: no hook fires for either MoA call type here (verified against agent/moa_loop.py::aggregate_moa_context and agent/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.
  • Auto-refresh covers OpenRouter models (via API) and Google AI Studio (static table). Anthropic, OpenAI direct-API pricing requires manual pricing.yaml entries or a new PricingSource subclass.
  • GoogleAISource is a constant table. It will drift without manual quarterly updates. See LAST_VERIFIED in pricing_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.

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.