A human developer reads the error body, checks the docs, and fixes the call. An agent does something different: it reads the status code and the body, weighs them against whatever branching rules its prompt or orchestration layer contains, and picks the next action. That next action is chosen from a small menu, usually "retry," "call a different tool," "rewrite the arguments," or "stop and ask." If your API returns a code that does not map cleanly onto that menu, the model guesses, and guessing is where loops come from.
The HTTP specification defines five classes of status codes by first digit: informational, success, redirection, client error, and server error (RFC 9110 as summarized by Olostep). The important split for an agent-facing API is between the fourth and fifth classes, because that is the boundary between "I did something wrong" and "the server did something wrong." A retry only helps in the second case.
The failure modes are easy to describe. When a 4xx code is returned for a temporary condition, the agent may treat its own request as broken, rewrite the payload over and over, and never recover. When a 5xx code is returned for a permanent condition, the agent retries a request that can never succeed until its step budget runs out. Practitioners building agents against real APIs have documented exactly this: a 422 with no field detail is invisible to the model, while a 422 carrying the missing field lets it self-correct (lessons from the field on agent HTTP errors).
The design goal is therefore simple to state: every status code your API can return should imply exactly one agent action.



