# Hermes

Hermes Agent, from Nous Research. See the [Hermes documentation](https://hermes-agent.nousresearch.com/docs/) for its current Python and dependency requirements before installing, since those change independently of this page.

Verified with Hermes 0.19.0 for K2 Horizon.

## Install

```
pip install hermes-agent
hermes --version
```

If pip says `No matching distribution found for hermes-agent`, your Python version is unsupported. The reason is in pip's first line, `Ignored the following versions that require a different python version`.

## Install the IFM provider plugin

Hermes needs a small provider plugin to use IFM. It registers the endpoint and tells Hermes that IFM requires the reasoning trace to be echoed back on every replayed assistant message. Without it Hermes strips the trace and every turn after the first is rejected.

Create `~/.hermes/plugins/model-providers/ifm/` and put both files in it.

`~/.hermes/plugins/model-providers/ifm/plugin.yaml`

```
name: ifm-provider-profile
kind: model-provider
version: 1.0.0
description: IFM K2 Horizon — OpenAI-compatible endpoint with reasoning echo-back
author: IFM
```

`~/.hermes/plugins/model-providers/ifm/__init__.py`

```
from __future__ import annotations

from providers import register_provider
from providers.base import ProviderProfile

IFM_HOSTS = ("api.ifm.ai",)
IFM_PROVIDER_NAMES = ("ifm", "custom:ifm")

ifm = ProviderProfile(
    name="ifm",
    display_name="IFM",
    description="IFM — K2 Horizon reasoning models",
    signup_url="https://ifm.ai/",
    env_vars=("IFM_API_KEY",),
    base_url="https://api.ifm.ai/v1",
    fallback_models=("IFM/K2-Horizon-375B-A23B",),
    default_aux_model="IFM/K2-Horizon-375B-A23B",
)

register_provider(ifm)

def _enable_reasoning_echo_back() -> None:
    """Make _needs_thinking_reasoning_pad() true for IFM endpoints."""
    try:
        import run_agent
    except Exception:
        return
    agent_cls = getattr(run_agent, "AIAgent", None)
    if agent_cls is None:
        return
    original = getattr(agent_cls, "_needs_thinking_reasoning_pad", None)
    if original is None or getattr(original, "_ifm_patched", False):
        return

    def _needs_thinking_reasoning_pad(self):
        provider = (getattr(self, "provider", "") or "").strip().lower()
        base_url = (getattr(self, "base_url", "") or "").strip().lower()
        if provider in IFM_PROVIDER_NAMES:
            return True
        if any(host in base_url for host in IFM_HOSTS):
            return True
        return original(self)

    _needs_thinking_reasoning_pad._ifm_patched = True
    agent_cls._needs_thinking_reasoning_pad = _needs_thinking_reasoning_pad

_enable_reasoning_echo_back()
```

Self-hosting: see Self-hosting below. `IFM_HOSTS` is only a fallback for setups that rename the provider away from `ifm`, and `display_name` and `signup_url` are cosmetic strings you can edit freely.

## Configure the provider

Hermes reads YAML from `~/.hermes/config.yaml`. The plugin already supplies the base URL, the API-key variable and the model list, so the config only selects which provider and model to use.

```
# ~/.hermes/config.yaml
model:
  provider: "ifm"
  default: "IFM/K2-Horizon-375B-A23B"
```

| Field | Meaning |
| --- | --- |
| model.provider | Provider to use. `ifm` matches the plugin directory name. |
| model.default | Model id used at startup. Override per run with `--model`. |

If you already have a `config.yaml`, add or replace only the `model:` block and leave the rest of the file alone.

## Run

Export the key named by the plugin's `env_vars`, then run:

```
export IFM_API_KEY="sk-ifm-..."

hermes -z "your prompt"
```

`-z` is one-shot mode: it sends a single prompt and prints only the final response, for scripts and pipes. Omit it for the interactive session.

To continue a conversation from a script, run `hermes chat -Q -q "your prompt"`, which prints a `session_id`, then pass `--resume <session_id>` on later calls. Each `-z` call starts a new session.

Confirm the wiring with `hermes status`, which should report `Model: IFM/K2-Horizon-375B-A23B` and `Provider: IFM`.

## Self-hosting

Serve the model with vLLM 0.30.0 or later. Take the GPU and parallelism flags for your hardware from the [vLLM recipe](https://recipes.vllm.ai/IFM/K2-Horizon-375B-A23B), and keep the flags below:

```
vllm serve IFM/K2-Horizon-MoVA-36B-A4B \
  --trust-remote-code \
  --reasoning-parser k2_horizon \
  --enable-auto-tool-choice --tool-call-parser k2_horizon \
  --chat-template-content-format string
```

Then change `base_url` in the plugin to your server, for example `http://<host>:8000/v1`. The plugin and config use the model id `IFM/K2-Horizon-375B-A23B`, which vLLM serves by default when started as above. If you start it from a local path, add `--served-model-name IFM/K2-Horizon-375B-A23B`.

`--chat-template-content-format string` is required.

## Reasoning pass-through

Preserve and resend the model's reasoning field in every assistant turn; otherwise Hermes drops it and multi-turn requests can fail with HTTP 400.

See [Reasoning](https://docs.ifm.ai/docs/reasoning.md) and the [multi-turn guide](https://docs.ifm.ai/docs/multi-turn.md).

_Last updated: October 15, 2026_
