Set reasoning: { effort: "minimal" }. That is the fix. Everything below is
why the obvious alternatives fail, because we lost a batch to this and the failure
mode gives you nothing to work with.
The symptom
You point a working generation pipeline at z-ai/glm-5.3-flash, change nothing
else, and every row fails. Not with an error — with an empty content string. The
request returns 200. Token usage looks normal, sometimes high. The message is
blank.
In our case: 0 of 8 rows produced usable output, with no error to trace.
The cause
This endpoint has mandatory reasoning. With default settings the model spends
its entire max_tokens allowance on reasoning tokens and has nothing left for the
visible message. At max_tokens: 4000, all 4000 go to reasoning.
Because reasoning tokens are billed and counted but not returned in content, the
usage numbers look like the model worked. It did. You just cannot see any of it.
Why you cannot simply turn it off
Both intuitive approaches fail with a 400:
| Attempt | Result |
|---|---|
reasoning: { enabled: false } |
400 — "Reasoning is mandatory for this endpoint" |
reasoning: { max_tokens: 0 } |
400 — same |
reasoning: { effort: "minimal" } |
Works. Reasoning drops to roughly zero tokens. |
No reasoning parameter at all |
Empty content — the default burns the budget |
That last row is the dangerous one. Omitting the parameter is not neutral. A pipeline that works against every other model will fail against this one without any code change, purely by switching a model name in configuration.
Why it is worth the trouble anyway
Once configured, this model was the best value we measured for Arabic conversational generation:
| Model | Pass rate against the same gate | Cost per row | 50,000 rows |
|---|---|---|---|
z-ai/glm-5.3-flash + effort: "minimal" |
59/62 (95%) | ~$0.00076 | ~$34–46 |
deepseek/deepseek-v4-flash |
20/27 (74%) | ~$0.0016–0.0027 | ~$80–133 |
Same prompts, same validators, same corpus. The pass-rate difference matters more than the token price, because a failed row costs a full retry.
The general lesson for model swapping
If your pipeline stores the model name as runtime configuration — which it should — then a model name is not a safely swappable value. Providers differ in required parameters, and the failures are not always loud.
Two defences worth building:
Assert on non-empty content. Treat an empty content as a hard error at the
client boundary, not as a row that failed validation. Those are different bugs and
conflating them cost us a batch of confused debugging.
Log reasoning token counts separately when the provider reports them. A row with 4,000 reasoning tokens and 0 completion tokens is instantly diagnosable; a row with "4,000 tokens used" is not.
Checklist before switching generation models
- Does the endpoint require or default to reasoning?
- What happens to
max_tokenswhen it does? - Does an empty
contentsurface as an error in your client? - Have you re-measured pass rate, not just token price?
The last point is the one that decides your bill. Token price is what you compare on a pricing page; pass rate is what you pay.