# NousResearch/hermes-agent · Mistral API 422 errors from invalid message fields

## Open now

- Nothing open on GitHub.

A cluster of issues and fixes addressing HTTP 422 errors when calling the Mistral API, caused by internal or unsupported fields (such as finish_reason and reasoning params) being included in API message payloads. The fixes involve stripping or skipping these fields before making API calls.

## TL;DR

- 5 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 3 PR(s) closed without merging.
- A fix was merged to main in PR #253. Verify it addresses your case.
- **Recommended:** read PR #253 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-253`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.40`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #134: Error code: 422 when calling mistral api

## Prior & competing PRs

- **#250: fix(agent): strip finish_reason and internal fields before API calls**. closed without merge · fix tier `suggested`
  - maintainer direction: category `uncategorized`; implication `needs_llm`; refs `#253`
- **#253: fix(agent): strip finish_reason from assistant messages to fix Mistral 422 errors**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `run_agent.py`
  - fix hunks:
  - `run_agent.py`

    ```diff
    @@ -2087,7 +2087,8 @@ def _build_api_kwargs(self, api_messages: list) -> dict:
             _is_openrouter = "openrouter" in self.base_url.lower()
             _is_nous = "nousresearch" in self.base_url.lower()
     
    -        if _is_openrouter or _is_nous:
    +        _is_mistral = "api.mistral.ai" in self.base_url.lower()
    +        if (_is_openrouter or _is_nous) and not _is_mistral:
                 if self.reasoning_config is not None:
                     extra_body["reasoning"] = self.reasoning_config
                 else:
    ```

    ```diff
    @@ -2232,6 +2233,7 @@ def flush_memories(self, messages: list = None, min_turns: int = None):
                         if reasoning:
                             api_msg["reasoning_content"] = reasoning
                     api_msg.pop("reasoning", None)
    +                api_msg.pop("finish_reason", None)
                     api_messages.append(api_msg)
     
                 if self._cached_system_prompt:
    ```

    ```diff
    @@ -2859,6 +2861,9 @@ def run_conversation(
                     # We've copied it to 'reasoning_content' for the API above
                     if "reasoning" in api_msg:
                         api_msg.pop("reasoning")
    +                # Remove finish_reason - not accepted by strict APIs (e.g. Mistral)
    +                if "finish_reason" in api_msg:
    +                    api_msg.pop("finish_reason")
                     # Keep 'reasoning_details' - OpenRouter uses this for multi-turn reasoning context
                     # The signature field helps maintain reasoning continuity
                     api_messages.append(api_msg)
    ```
- **#138: fix: sanitize internal fields from API messages**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`
- **#252: fix(agent): skip reasoning param for Mistral API to prevent 422 errors**. closed without merge
  - maintainer direction: category `silent_close`; implication `active`

## Fix status

- Merged to main in PR #253 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-03-02`. This confirmation is old and may be out of date (a revert/reopen would not have invalidated it here); re-verify.
