# mimo-v2.5 — HTTP 400 « Param Incorrect » (`text` is not set) sur screenshots browser_vision **Date** : 2026-07-09 · **Instance** : hermes-nyora · **Tags** : nyora, mimo, opencode, xiaomi, vision, browser_vision, 400 ## Symptôme Depuis le 08/07 ~21:30, appels mimo-v2.5 en échec récurrent (3 sessions, 6 appels) : ``` WARNING agent.conversation_loop: API call failed (attempt 1/3) error_type=BadRequestError provider=opencode-go model=mimo-v2.5 summary=HTTP 400: Error from provider (Xiaomi): Param Incorrect ``` Détail complet dans le log : `'param': '`text` is not set'`. Chaque échec déclenche un fallback silencieux vers deepseek-v4-flash (la réponse arrive, mais pas par mimo). deepseek ne présente jamais le problème sur la même stack. ## Cause racine (reproduite par appel direct opencode.ai/zen/go/v1) 1. **mimo-v2.5 est vision-capable** : les images dans les messages `user` (photos Telegram) passent et sont bien décrites. Ce n'est PAS un problème d'image utilisateur, ni de tools, ni de streaming, ni de `thinking`. 2. **Xiaomi rejette le contenu de type liste dans les messages `role: tool`** (multipart `[{type:text},{type:image_url}]`, ce que produit `browser_vision` pour ses screenshots) → 400 « Param Incorrect », param `` `text` is not set ``. 3. hermes-agent connaît ce bug (issue upstream #27344) et a un recovery dédié (`_try_strip_image_parts_from_tool_messages` + classifier `multimodal_tool_content_unsupported`), **mais le pattern du classifier est `"text is not set"` SANS backticks** alors que l'API renvoie désormais `` `text` `` AVEC backticks → pattern raté → 400 générique → fallback. Repro minimale (SDK openai, clé `OPENCODE_GO_API_KEY` du container) : un message `role:tool` avec `content` liste contenant un part image → 400 systématique. Le même contenu en message `user` → OK. ## Fix appliqué (config-only, aucune modif d'image Docker) Plugin utilisateur (mécanisme officiel `$HERMES_HOME/plugins/model-providers/`, last-writer-wins sur les profils bundled) : `/volume1/docker/hermes-platform/hermes-nyora/data/plugins/model-providers/opencode-go-vision-fix/__init__.py` ```python from providers import get_provider_profile _profile = get_provider_profile("opencode-go") if _profile is not None: _profile.supports_vision_tool_messages = False ``` Effet : `_tool_result_content_for_active_model` convertit préemptivement les résultats d'outils multimodaux en résumé texte (`_multimodal_text_summary`) avant l'envoi à Xiaomi. La vision native des images `user` reste active. Ownership 1026:100, puis `docker restart hermes-agent-nyora`. ## Vérification (2026-07-09 ~07:00 UTC) - Process frais : `supports_vision_tool_messages=False`, cap max_tokens mimo-v2.5-pro conservé, tool result screenshot → str sans image_url. - E2E via api_server (port 8642, clé `API_SERVER_KEY`) : scénario exact en échec la veille (navigation + `browser_vision` + description) → réponse correcte, 3 appels `model=mimo-v2.5`, **zéro 400, zéro fallback**. ## Impact sur le comparatif mimo vs deepseek **Les stats du pilote (05→08/07) ne sont PAS faussées** : zéro occurrence dans agent.log.1 (04/07→08/07 20:42) ; les 6 × 400 datent du 08/07 21:35–22:05, après le verdict, déclenchées par un nouveau pattern d'usage (sessions browser avec screenshots). Le « 1 erreur / 591 appels » de mimo tient. Nuance : les tours en 400 ont été servis par deepseek via fallback (3 tours, négligeable). ## Pièges / à savoir - Les `request_dump_*.json` ne sont écrits que sur `max_retries_exhausted` — un 400 récupéré par fallback ne laisse PAS de dump. Chercher dans `data/logs/agent.log` (`Param Incorrect`, `Fallback activated`). - curl/urllib directs sur opencode.ai → 403 Cloudflare 1010 (User-Agent) ; utiliser le SDK openai du venv du container. - À retirer si l'image upstream corrige le pattern du classifier (backticks) ou si Xiaomi accepte le contenu liste dans les messages tool.