I switched a local OpenClaw gateway from NVIDIA's free endpoint to Groq. Set the new model as primary, restarted, sent a message. It hung for 120 seconds and timed out.
So I checked the config the way you would: openclaw config get on the model, then the JSON file on disk. Both showed the Groq model as primary. Correct, every time I looked. And yet the turns were going to moonshotai/kimi-k3 — an NVIDIA-hosted model that had already been pulled, which is why nothing ever answered.
The value that mattered was somewhere else:
"agents": {
"defaults": {
"model": { "primary": "custom-groq/openai/gpt-oss-120b" },
"modelPolicy": {
"allow": ["custom-integrate-api-nvidia-com/moonshotai/kimi-k3", "..."]
}
}
}
modelPolicy.allow is a hard allowlist, and it wins over primary. When the primary isn't on the list, the gateway doesn't fail or warn — it quietly picks something that is allowed. Every list entry was an old NVIDIA model, so it picked a dead one, and the failure surfaced as a timeout, three layers away from the cause.
What cost the hours is that every "what is my model?" check reported the primary, and the primary was fine. The resolved value and the dispatched value were two different things, and only one of them was visible.
The check that would have found it in ten seconds:
$ grep -n "kimi-k3" ~/.openclaw/openclaw.json
When a model change doesn't seem to take effect, grep the config for the old model id instead of reading back the new one. Any hit that isn't the line you just edited is the thing overriding you. The fix itself is one line: put the new primary on the allow list.
One related trap from the same afternoon: agents.defaults.model accepts only primary. Adding a fallback array fails schema validation and the gateway exits with code 78, so a list of fallbacks is not a way around the allowlist either.
Top comments (0)