Repository navigation
OpenCode Go: Xiaomi MiMo rejects list-type tool message content (400 text is not set) #32613
Description
Activity
@Cdddo @fwang , I fixed the issue with PR #32966.
Root cause: MiMo/GLM-5.2/Xiaomi require tool role messages to have
contentas a plain string, notContentPart[]array. The AI SDK sends tool results as[{type: "tool-result", output: {type: "text", value: "..." }}], which these providers reject with 400 errors.Fix: Added provider-specific transform that flattens single-part tool results to plain strings for affected providers. Multi-part content is preserved as array (providers that don't support it will error, which signals the limitation clearly.
+1 — still affecting OpenCode Go users
I'm running OpenCode Go with Xiaomi MiMo v2.5 as my primary model (via Hermes Agent on a Raspberry Pi). This issue causes intermittent 400 errors whenever a tool result includes image content (vision analysis, browser screenshots, etc.), forcing fallback to non-vision models and breaking my entire image verification workflow.
What I've tried:
- Routing through OpenRouter instead of OpenCode Go's native relay (works, but adds latency and loses some features)
- Keeping the fallback chain as a band-aid (all fallback models lack vision, so the system becomes unusable for visual tasks)
PR #32966 by @lexlian looked like the right fix (flatten single-part tool results to plain strings for affected providers), but it was closed by automated cleanup before being reviewed. The fix was tested and passing all 277 tests.
Request: Could this be prioritized? The Xiaomi API isn't going to change this behavior — their docs explicitly require string content for tool messages. The relay is the right place to handle this translation.
Happy to help test if a new PR is opened.
Current reproduction through OpenCode Go / MiMo v2.5
I am adding current evidence to this existing issue rather than opening a duplicate.
Effective route
- Hermes
maincommit:fe3dd9106a1c9d2327fb3795e55b09742c43bafd - Provider:
opencode-go - Model:
mimo-v2.5 - Base URL:
https://opencode.ai/zen/go/v1
Reproduction
Using a fresh temporary Hermes home, without changing the permanent configuration:
opencode-go/mimo-v2.5 → browser_navigate completed → browser_vision completed → next request through opencode-go/mimo-v2.5 → HTTP 400The returned error was:
Error from provider (Xiaomi): Param Incorrect param: `text` is not setThe request did not switch to Xiaomi as the selected Hermes provider. The effective provider remained OpenCode Go throughout the tested route. Hermes also did not silently switch to another model after the 400.
The same failure pattern was previously observed in Hermes sessions using
opencode-go/mimo-v2.5directly and after a real fallback to that route.Question for OpenCode Go
Could you confirm how the OpenCode Go relay/adaptor maps the request state associated with
browser_visioninto the request sent to MiMo v2.5?In particular:
- Is a plain
textfield required for tool messages on this route? - Does the relay normalize list/part-based tool content before forwarding it?
- Is
text is not setexpected for this request shape, or should the relay return a more specific compatibility response?
Scope and limitations
- This is not a direct Xiaomi-provider test; the effective provider was
opencode-go. - Xiaomi is mentioned only because it appears as the upstream source in the returned error.
- The exact wire payload was not captured.
- I am not asserting that OpenCode Go alone is the root cause; the defect may involve Hermes request construction, relay transformation, or the downstream adapter boundary.
- The historical introducing change has not been identified.
Related Hermes reproduction: NousResearch/hermes-agent#49388
- Hermes
- added a commit that references this issue
on Aug 3, 2026 Adding current evidence for the third-party OpenAI-compatible client path, plus one gap that the earlier fix does not cover.
Reproduction as of today:
- Provider
opencode-go, modelmimo-v2.5, base URLhttps://opencode.ai/zen/go/v1 - Client: Hermes Agent (plain OpenAI-compatible chat completions)
- A tool result that carries an image is sent as multi-part content on
role: "tool":
[{"type":"text","text":"..."},{"type":"image_url","image_url":{...}}] - Xiaomi rejects the request: 400,
param: "text" is not set
The part worth flagging: the transform in #32966 only handles single-part tool results. It flattens a lone text/error part to a string and explicitly leaves multi-part content as an array. Multi-part is exactly the shape this bug is about, so even with that transform merged, a tool result carrying an image would still 400.
What would actually close it for these providers, either way:
- hoist media out of the tool result into a normal user message — this is the existing behavior for
@ai-sdk/openai-compatiblein the CLI (supportsMediaInToolResultreturns false for it, so the image is extracted and re-injected as a user message), and it is the same approach PR fix(opencode): hoist Bedrock tool images except Claude, Nova, and Llama 4 #50272 just merged for Bedrock; or - for
role: "tool"messages specifically, emit plain-string content and move the media part to an adjacent user message.
Worth noting the asymmetry: the opencode CLI itself does not hit this, because it already hoists media out of tool results for OpenAI-compatible SDKs. It only bites clients that talk to
/zen/go/v1/chat/completionsdirectly and treat "OpenAI-compatible" literally. Since Go is advertised as an OpenAI-compatible endpoint, closing that gap on the relay side would fix every third-party client at once instead of each one shipping its own workaround.Happy to test a fix or provide a minimal request payload if useful.
- Provider
Description
When using OpenCode Go with Xiaomi MiMo models (e.g.
mimo-v2.5), requests that include tool results with image content (e.g. browser screenshots, vision tool output) fail with a 400 error:The issue is that Xiaomi MiMo API requires
role: "tool"message content to be a string, but OpenAI-compatible clients send it as a list of content parts (e.g.[{"type": "text", "text": "..."}, {"type": "image_url", "image_url": {...}}]) when the tool result includes images.OpenCode Go exposes an OpenAI-compatible
/v1/chat/completionsendpoint and routes MiMo requests to Xiaomi. The relay appears to pass through the list-type tool content unchanged, and Xiaomi rejects it.Steps to Reproduce
mimo-v2.5(or any MiMo model)contentis a list withtext+image_urlpartsExpected Behavior
The relay should either:
Context
This is a known Xiaomi API limitation — their API accepts multimodal user messages but rejects list-type tool message content. Other clients (Hermes Agent, OpenClaw) have hit the same issue (ref: hermes-agent#27344, openclaude#1421).
Clients can work around this by flattening tool-result images to text before sending, but since OpenCode Go positions itself as a unified OpenAI-compatible API, the relay is better positioned to handle this translation — especially since other backends behind the relay (GLM, Kimi) may handle list-type content fine, making this a per-model concern that the relay should abstract away.