Files
Hermes Agent b0d790be34 Add all 104 active skills from all 16 Hermes profiles
12 unversioned skills now versioned at 1.0.0:
agent-communication, ascii-video, external-reasoning-augmentation,
jotty-notes-api, minecraft-modpack-server, obsidian, pokemon-player,
powerpoint, social-search, songwriting-and-ai-music,
workspace-context-organization, youtube-content

Total repo: 141 skills across all profile scopes
2026-07-04 11:44:04 -05:00

8.1 KiB

name, description, version, author, metadata
name description version author metadata
hermes-config-internals Hermes Agent config internals — what parameters the agent actually sends to providers vs what users expect. Covers temperature, generation params, provider profiles, request_overrides, and the gap between documented/expected behavior and source-code reality. 1.0.0 agent
hermes
tags
hermes
config
providers
internals
debugging

Hermes Config Internals

When a user asks whether Hermes supports a config option (temperature, top_p, generation params, etc.), do NOT trust external sources (Grok, ChatGPT, blog posts). Always verify against the source code. Many plausible-sounding config blocks do not exist.

Core Finding: No generation: Config Block

Hermes Agent does not have a generation: config section. Temperature, top_p, top_k, seed, etc. are not user-facing config knobs for the main agent loop. Any external source claiming otherwise is wrong.

Temperature — What Actually Happens

Main agent loop

The build_kwargs method in agent/transports/chat_completions.py never sets a temperature key. For registered providers, _build_kwargs_from_profile checks profile.fixed_temperature — most profiles (including Ollama Cloud and Custom/Ollama) inherit None from ProviderProfile, so temperature is omitted entirely. The provider/server uses its own default.

Auxiliary tasks (hardcoded 0.3)

  • Compression summaries: 0.3
  • Title generation: 0.3
  • One-shot helpers: 0.3

Model-specific overrides

_fixed_temperature_for_model() in agent/auxiliary_client.py only overrides for:

  • Kimi/Moonshot models → OMIT_TEMPERATURE (strip entirely, server-managed)
  • Arcee Trinity Thinking → force 0.5
  • Everything else → None (no opinion)

Claude Opus 4.7+

_forbids_sampling_params() in agent/anthropic_adapter.py returns True for Opus 4.7+ — these models 400 on any non-default temperature/top_p/top_k. Hermes strips them.

MoA (Mixture of Agents)

The only user-configurable temperature in Hermes is for MoA presets:

  • moa.presets.<name>.reference_temperature (default 0.6)
  • moa.presets.<name>.aggregator_temperature (default 0.4)

Provider Profiles — What They Actually Control

Ollama Cloud (plugins/model-providers/ollama-cloud/__init__.py)

  • Only handles reasoning_effort (maps xhigh→max)
  • No temperature, no num_ctx, no options
  • fixed_temperature is None (inherited from ProviderProfile)

Custom/Ollama Local (plugins/model-providers/custom/__init__.py)

  • ollama_num_ctxextra_body.options.num_ctx
  • reasoning_config disabled → extra_body.think = False
  • No temperature
  • fixed_temperature is None

request_overrides — The Injection Point

The transport merges request_overrides into api_kwargs at the end of build_kwargs. If {"temperature": 0.3} were in request_overrides, it would land as a top-level API parameter. However, request_overrides comes from turn routing (gateway/CLI runtime resolution), not from static config.

Working Method: extra_body on custom_providers

This works. Adding extra_body to a custom_providers entry injects parameters into the API call. The OpenAI SDK flattens extra_body keys into top-level JSON fields in the HTTP request.

Code path

  1. _custom_provider_request_overrides() in hermes_cli/runtime_provider.py (line 899): reads custom_provider["extra_body"] → returns {"extra_body": {...}}
  2. _merge_custom_provider_extra_body() in agent/agent_init.py (line 147): merges into agent.request_overrides["extra_body"]
  3. Transport _build_kwargs_from_profile() in agent/transports/chat_completions.py (line 564): iterates request_overridesextra_body keys are merged into the extra_body dict
  4. OpenAI SDK sends extra_body keys as top-level JSON fields in the HTTP request body

Config example

custom_providers:
- name: Ollama
  base_url: http://localhost:11434/v1
  api_key: m
  extra_body:
    temperature: 0.3
  models:
    deepseek-v4-pro:cloud: {}

Per-model variant

custom_providers:
- name: Ollama
  base_url: http://localhost:11434/v1
  api_key: m
  models:
    deepseek-v4-pro:cloud:
      extra_body:
        temperature: 0.3
    glm-5.2:cloud:
      extra_body:
        temperature: 0.7

_custom_provider_extra_body_for_agent() (line 95) matches by provider name + base_url, then checks _custom_provider_model_matches() for per-model extra_body.

Verified: 2026-07-02

Tested on general profile with DeepSeek V4 Pro via Ollama (localhost:11434/v1). The extra_body injection mechanism works — confirmed by temperature=4 causing HTTP 400 (Ollama rejects out-of-range). However, DeepSeek V4 Pro's Thinking Mode explicitly does NOT support temperature. Official DeepSeek API docs (api-docs.deepseek.com/guides/thinking_mode): "Thinking mode does not support the temperature, top_p, presence_penalty, or frequency_penalty parameters. Please note that, for compatibility with existing software, setting these parameters will not trigger an error but will also have no effect." Default temperature is 1.0 (api-docs.deepseek.com/quick_start/parameter_settings). Together AI docs warn: "Lower temperatures can collapse the reasoning trace and degrade answer quality." The parameter is silently accepted but has zero effect — this is by design, not an Ollama quirk. GLM-5.2 confirmed to respect temperature via direct API test. See references/temperature-test-results.md.

Verification workflow for parameter testing

When testing whether a parameter reaches the API and is respected:

  1. Test the model directly against the API first — use curl to confirm the model actually respects the parameter before testing through Hermes
  2. Use the model the user specifies — do NOT suggest alternative models. If the user says "test with DeepSeek," test with DeepSeek even if you suspect it won't work
  3. Get test prompts from the web — when the user says "get test questions from the web," use SearXNG MCP to find validated test prompts. Do NOT reuse the same prompts or invent your own
  4. Test at multiple temperature values — 0, 1.0, and an out-of-range value (e.g. 4) to confirm the parameter reaches the API (out-of-range → 400 proves injection)
  5. Run each test 3-5 times — temperature effects are statistical; single runs are inconclusive
  6. Use creative prompts for differentiation — "write a poem about X" shows variation better than "name a random number"

Matching logic

_custom_provider_extra_body_for_agent() matches by:

  1. Provider name (custom:ollama → filter by name: Ollama or provider_key: ollama)
  2. Base URL (normalized: strip trailing /)
  3. Optionally per-model via _custom_provider_model_matches()

The runtime resolution for custom:<name> picks up the matching custom_providers entry's base_url, overriding the profile's model.base_url. So the agent's actual base_url at runtime matches the entry.

Verification Workflow

When investigating whether Hermes supports a parameter:

  1. Search the source for the parameter name: search_files(pattern="temperature", path="~/.hermes/hermes-agent/agent")
  2. Trace build_kwargs in agent/transports/chat_completions.py — this is where API kwargs are assembled
  3. Check the relevant provider profile in plugins/model-providers/<name>/__init__.py
  4. Check agent/agent_init.py for how config values flow into the agent
  5. Check hermes_cli/runtime_provider.py for how custom provider config maps to runtime

Key Source Files

File Role
agent/transports/chat_completions.py API kwargs assembly (build_kwargs, _build_kwargs_from_profile)
agent/auxiliary_client.py _fixed_temperature_for_model, _build_call_kwargs
agent/agent_init.py Config → agent attribute mapping
agent/anthropic_adapter.py _forbids_sampling_params
providers/base.py ProviderProfile base class (fixed_temperature, build_extra_body)
plugins/model-providers/*/__init__.py Per-provider profiles
hermes_cli/runtime_provider.py Custom provider → runtime resolution, request_overrides