200 OK from curl and wired them into two agent harnesses. Not one of them worked. Every failure was somewhere other than the key: a model picker offering models the provider had retired, an allowlist silently overriding the configured model, a per-minute budget that a single agent turn exceeds, and an error the harness relabelled into a different problem entirely. Here is each one, what it looked like, and how to check for it in about a minute.There is no shortage of lists of free AI APIs. We publish one. What none of them cover is the part that actually costs you an afternoon: the gap between having a working key and having a working agent.
We closed that gap the hard way — four providers, two harnesses, and a lot of errors that pointed at the wrong thing. Every failure below is one we hit, with the message it actually produced.
The keys were never the problem
Start with the baseline, because it is what misleads you. All four keys, called directly:
| Provider | Direct call | Inside the harness |
|---|---|---|
| Groq | ✅ 200 | ❌ "Context overflow" |
| Google Gemini | ✅ 200 | ❌ empty reply, then 120 s timeouts |
| Mistral | ✅ 200 | ❌ fetch failed |
| Zhipu GLM | ✅ 200 | ❌ fetch failed |
Four green checkmarks, four broken agents. If your debugging starts and ends at "is the key valid", you will spend the afternoon re-issuing keys that were fine.
Failure 1: the model picker offers models that no longer exist
Selecting "Llama 3.1 8B" from a harness's model list produced:
404 {"message":"The model `llama-3.1-8b-instant` does not exist or
you do not have access to it.","code":"model_not_found"}
The key was fine. The model was gone. Agent runtimes ship a bundled model catalogue so the picker can populate before you authenticate, and providers retire models faster than those catalogues are updated.
We compared the harness's Groq list against what /models returned on a live key:
| Offered by the harness | Exists on the provider? |
|---|---|
| Llama 3.1 8B | ❌ retired |
| Llama 3.3 70B | ❌ retired |
| Llama 4 Scout 17B | ❌ retired |
| Qwen3-32B | ❌ retired |
| GPT-OSS 120B / 20B / Safeguard 20B | ✅ |
Four of seven were dead — and five models that do exist (qwen3.8-27b, qwen3.6-27b, compound, compound-mini, allam-2-7b) were not offered at all. The picker is not a source of truth. Before trusting it:
curl -s https://api.groq.com/openai/v1/models \
-H "Authorization: Bearer $GROQ_API_KEY" | jq -r '.data[].id'
Then pin your config to that list rather than the bundled one. Most harnesses let you replace the catalogue per provider.
Failure 2: an allowlist that silently wins
This one cost the most time. The config file said the primary model was Groq. The CLI agreed:
$ openclaw config get agents.defaults.model.primary
custom-groq/openai/gpt-oss-120b
The runtime log said otherwise — every request went to a completely different provider and a model that had been retired, timing out at 120 seconds each. The cause was a separate model allowlist elsewhere in the config, left over from an older setup. It takes precedence over the primary setting, and when the primary is not on the list, the request falls back to whatever is — with no warning that a substitution happened.
The lesson generalises past one product: when a model change appears not to take effect, grep the whole config for the old model name rather than trusting the resolved value. The resolver was reporting the setting, not the decision.
Failure 3: a model that answers "hello" can't carry an agent turn
An agent request is not a chat request. It carries a system prompt and every tool definition on every call, and a loop replays a growing transcript. That is a different order of magnitude, and free tiers are priced per minute.
Groq's free tier caps tokens-per-minute at 8,000, counting the prompt plus the max_tokens you ask for. So a 20-token question with a generous completion ceiling is rejected before a token is generated:
Request too large ... on tokens per minute (TPM):
Limit 8000, Requested 8271
Walking prompt size up a ladder, it served 5,111 tokens and refused at 10,000 — an effective working set of about 7,500 tokens against an advertised 131,072. Mistral and GLM served 30,000 without complaint on the same ladder. We covered the measurements in detail in the Groq free tier breakdown.
The rule to take away: your effective context on a free tier is the rate budget, not the model's context window. Test with a realistic prompt, not with "hi".
Failure 4: the error you see is not the error that happened
When that 413 reached the harness, it was reported as:
Context overflow: this conversation is too large for the model.
Try /compact, or /new to start a fresh session.
The session held 1,400 tokens. We went hunting for an oversized system prompt that did not exist, compacted a transcript that was already tiny, and only found the truth by calling the API directly and reading the raw status code.
Harnesses map upstream errors onto their own vocabulary, and a rate-limit rejection lands convincingly in the "too much context" bucket. If an error contradicts a number you can measure yourself, reproduce the call outside the harness. One curl settles it.
Failure 5: Node's fetch ignores your proxy
Two providers failed with a bare fetch failed while curl reached them from the same shell, with the same environment, seconds apart.
Node's built-in fetch does not read HTTP_PROXY / HTTPS_PROXY. Setting those variables configures curl and most language SDKs; it does nothing for a Node-based agent runtime, which is most of them. On Node 24 the fix is one variable:
export NODE_USE_ENV_PROXY=1
If your harness runs as a service rather than from your shell, note that it will not inherit the variables at all — they have to go in the unit file or the container environment. This is worth knowing even if you do not use a proxy at home: it is the default situation on a corporate network, and "curl works but the app doesn't" is otherwise a genuinely baffling symptom.
One more thing free tiers do: run out
Midway through testing, Gemini began returning 429 You exceeded your current quota at every prompt size, including ones it had served minutes earlier. Nothing was misconfigured — a day of benchmarking had simply consumed the daily free allowance.
It is an obvious failure in hindsight and an invisible one in the moment, because it looks exactly like a broken setup. If a provider that worked this morning fails at every size this afternoon, check the quota before you check the config. It also means a free tier that comfortably handles your testing may not handle your testing plus your actual usage — the two share one budget.
The one-minute checklist
Run these in order before assuming the key or the model is at fault:
- Does the model exist? Call
/modelson the provider and confirm the exact id string appears. Do not trust the picker. - Is the model you configured the model being used? Find the request in the harness's log. If it names something else, grep the config for that name.
- Does it survive a realistic prompt? Send ~10,000 tokens with your real
max_tokens, not "hi". - Does the error survive leaving the harness? Reproduce with
curland read the raw status code. - Behind a proxy? Set
NODE_USE_ENV_PROXY=1for Node runtimes, in the service environment if it runs as a service. - Quota intact? Check the provider console before assuming a regression.
Bottom line
A free API key is the easy part, and it is the part every guide covers. The failures that stop you are elsewhere: stale catalogues, config that silently overrides itself, rate budgets that a single agent turn exceeds, errors renamed on the way through, and a proxy layer that treats curl and Node differently.
None of these produce an error message that says what is wrong. All of them are findable in under a minute once you know to look. For which free models hold up once the plumbing works, see our agent test across free models; for what remains genuinely free at all, the free API comparison.
Tested 1 September 2026 across Groq, Google Gemini, Mistral and Zhipu GLM free tiers, driving DeepSeek Harness and OpenClaw. Error messages are quoted verbatim. Provider limits change without notice — verify against your own key rather than trusting these figures later.