7 things to check before you blame the model

I spent an entire evening last month watching an agent crawl through a task at a pace that felt personal. The model kept returning half-finished answers, truncating tool calls, and generally behaving like it had given up on life. I was ready to switch providers. Then I checked the dashboard and discovered the job had been silently retrying against a dead route for two hours. The model was fine. My plumbing wasn't.

Here's the order I work through now, cheapest checks first.

Is the job even running?

This sounds insulting. It isn't. I once spent forty minutes convinced a model was hallucinating permissions errors, when in fact my worker had crashed on boot and the queue was red but nothing was consuming it. A dead job looks exactly like a stuck job from the outside.

Check whether your agent process is actually alive:


ps aux | grep -E "worker|agent" | grep -v grep

Then look at your queue depth. If messages are piling up with no consumer attached, your problem is upstream of any model. Fix the supervisor, restart the worker, and the "broken model" starts working again.

Is the route alive?

Your agent talks to a model through some path — an API endpoint, a proxy, a self-hosted endpoint behind a load balancer. That path can be down while the model itself is perfectly healthy. I've seen a DNS record expire on a Friday night and spend half of Saturday debugging "degraded model output" that was actually a connection timeout being retried with exponential backoff.

Hit the endpoint directly, the same way your agent does:


curl -s -o /dev/null -w "%{http_code} %{time_total}s\n" https://your-endpoint/v1/models

A 200 means the route is alive and the problem is downstream. A 502 or a timeout means you've found your culprit before you ever touch the model config.

Is the chain still the current one?

Agents are pipelines. Output from step one becomes input to step two. If something upstream changes its format — a tool returns JSON where it used to return plain text, a schema gets an extra required field — the next step in the chain starts choking. The model isn't wrong. It's being fed something it wasn't expecting.

I learned this when I updated a function-calling wrapper and didn't update the system prompt that described the output format. The model spent three cycles trying to parse responses that no longer matched what it had been told to expect. The fix was one line in a prompt file.

When output looks garbled, diff the actual payloads between steps. Not what you think is being sent — what is being sent.

Did a context rebuild eat the budget?

This one bit me hard. An agent will sometimes rebuild its context mid-task — re-summarize earlier turns, re-fetch system instructions, reassemble the tool definitions. If you're on a token-capped plan, that rebuild can consume your remaining budget in one shot. The model then starts truncating because it has no room left.

If a job was working fine and suddenly the responses get shorter and dumber, check your token ledger:


# hypothetical — your tracker will differ
grep "context_rebuild" jobs.log | tail -5

If a rebuild fired, look at what triggered it. A context window limit hit, a manual reset, an automatic summarization threshold. Once you know the trigger, you can either raise the cap or pre-empt the rebuild by splitting the job into smaller pieces that fit without one.

Is the source throttled or empty?

Your agent pulls data — files, APIs, documents, whatever. If that source starts returning 429 (rate limited) or 402 (payment required, for metered APIs), your agent sits there waiting on input that will never come. Then the model times out or produces garbage because it's trying to work with nothing.

Watch the source's response codes:


# what is your fetch layer actually getting?
tail -f agent.log | grep -E "429|402|503"

A 429 means you're being throttled — back off, cache more aggressively, or add a second key. A 402 on a metered source means the bill wasn't paid or the quota was hit. Neither is a model problem.

Is the primary path throttled too?

Sometimes the source is fine but the path between your agent and that source is degraded. A rate-limited proxy, a VPN that's congested, a Cloudflare rule that's suddenly challenging your requests. The agent can't reach what it needs, so it stalls, and you blame the model for being slow.

I run a simple health check that pings the full path — not just the endpoint, but the agent's actual route through whatever proxy or tunnel it uses:


# time a full round trip through your agent's route
time curl -s https://your-proxy/source-endpoint \
  -H "Authorization: Bearer $KEY" \
  -d '{"query":"ping"}' | jq .

If the round trip is slow or failing while the direct endpoint is fast, you've found a routing issue. The model is waiting on a network problem, not thinking slowly.

Then, and only then, the model

I've talked myself out of blaming the model six times out of ten. The model gets the blame when the job is running, the route is alive, the chain is current, no rebuild has eaten the budget, the source is returning real data, and the path to it is fast. If all of that checks out and the output is still broken — inconsistent reasoning, repeated failures on the same task, refusal to use tools correctly — then you can look at whether the model itself is the bottleneck.

That last step is the one I used to start with. It's the hardest to diagnose, the most expensive to fix, and the least likely to be the actual problem.

← Cleo's Blog · Cleo's Nine