--- name: hermes-provider-config description: "Hermes custom_providers configuration — extra_body injection, temperature control, base_url matching, per-model overrides, and provider profile quirks." version: 1.0.0 author: Hermes Agent --- # Hermes Provider Configuration Configuration techniques for Hermes `custom_providers` entries — injecting API parameters, per-model overrides, and understanding provider profile behavior. ## Temperature Injection via extra_body Hermes does not send a `temperature` parameter by default. The main agent loop omits it entirely. The only user-configurable injection point is `extra_body` on a `custom_providers` entry. ### How it works `_merge_custom_provider_extra_body` (agent/agent_init.py:147) matches the agent's provider name + base_url against `custom_providers` entries. When both match, the entry's `extra_body` dict is merged into `agent.request_overrides["extra_body"]`. The transport then merges `request_overrides` into `api_kwargs` (chat_completions.py:564-570), sending the fields as top-level API parameters. ### Provider-level extra_body ```yaml custom_providers: - name: Ollama base_url: http://localhost:11434/v1 api_key: m extra_body: temperature: 0.3 models: deepseek-v4-pro:cloud: {} glm-5.2:cloud: {} ``` ### Per-model extra_body ```yaml 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 ``` ## Matching Requirements Both provider name AND base_url must match: - The agent's `model.provider` (e.g. `custom:ollama`) is split — the `ollama` part is matched against the entry's `name` field - The agent's `model.base_url` is normalized (stripped, trailing slash removed) and compared to the entry's `base_url` - If either doesn't match, `extra_body` is silently skipped — no error, no warning **PITFALL — Stale base_url in profile config:** If a profile's `model.base_url` points to a different server than the `custom_providers` entry (e.g. profile has `http://10.0.0.26:8000/v1` but the Ollama entry has `http://localhost:11434/v1`), the match fails and `extra_body` is silently dropped. Always verify the profile's `model.base_url` matches the intended `custom_providers` entry. ## What Doesn't Work - There is no `generation:` config block in Hermes (Grok hallucinated this) - `request_overrides` is not user-configurable in config.yaml — it's built at runtime from the turn route - The OllamaCloudProfile only handles `reasoning_effort`, not temperature - The CustomProfile only handles `ollama_num_ctx` and `think=false` ## Model-Specific Temperature Behavior - **GLM-5.2** — respects temperature. `temperature: 0` → deterministic outputs; `temperature: 1.0` → varied outputs - **DeepSeek V4 Pro** — 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 (docs.together.ai/docs/deepseek-v4-quickstart) warn: "Lower temperatures can collapse the reasoning trace and degrade answer quality, so prefer to control output length with `max_tokens` rather than turning down temperature." The parameter is silently accepted but has zero effect — this is by design, not an Ollama quirk. - **Ollama OpenAI-compatible endpoint** — supports `temperature` as a standard field (confirmed via docs.ollama.com). Rejects out-of-range values: temperature=4 returns HTTP 400. - **Temperature range validation** — Ollama enforces range limits. Temperature=4 caused HTTP 400 on every request. Temperature=2 (DeepSeek's documented max) was accepted. This confirms `extra_body` injection reaches the API. ## Verification Workflow When testing whether temperature (or any `extra_body` parameter) is working: 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" ## Verification Results (2026-07-02) Tested against Ollama local (localhost:11434/v1) with DeepSeek V4 Pro: - Temperature=0: poems varied across runs (model ignores parameter) - Temperature=1.0: poems varied across runs (model ignores parameter) - Temperature=2: poems varied across runs (model ignores parameter) - Temperature=4: HTTP 400 on all runs (Ollama rejects out-of-range, proves injection works) Direct API test with GLM-5.2 confirmed the mechanism works for models that respect temperature. ## References - `references/temperature-verification.md` — full test results, direct API vs Hermes comparison