The quiet misconception
People commonly believe an agent can tolerate an internal payload it does not fully understand. The loop can log a warning, preserve the payload in its history, and let the next model call work around it.
That sounds flexible. It is only safe when the unrecognized data is deliberately isolated and has no effect on the current state. An event that determines the next action, its result, or whether work is complete is different. Once the runtime admits that event, later iterations treat a malformed fact as part of the task.
The failure then looks like bad reasoning: the agent makes no progress, repeats itself, or cannot recover. The actual failure happened earlier, when the runtime accepted a state transition it could not describe.
What was the contract?
An agent loop carries more than chat messages. It records an action proposal, the authority that allowed it, an execution result, and a transition to the next phase. Each record has a shape and a meaning. An execution result, for example, must be recognizable as a result for a particular action before it can change the state of that action.
This is not an API contract in the usual client-server sense. The producer and consumer may live in the same process. It is still a contract because two separate parts of the runtime rely on it: one produces an event, and the state machine decides what that event permits next.
The important invariant is simple: an event the runtime cannot validate cannot change durable state.
A warning is useful only after the runtime has proved that the warned-about data is irrelevant to the current state.
Why does admitting the event make recovery worse?
The next model call is assembled from the state the runtime retained. If it includes an unrecognized tool result, a partial lifecycle event, or a completion record without its required information, the model is asked to reason from a false premise. A retry repeats the same setup. More context can make it worse by giving the bad record more opportunities to be interpreted as current.
That is why this class of failure is expensive to diagnose. The final symptom is usually generic: "agent failed to make progress." The useful evidence was available at the moment the event arrived, but the runtime converted a local format error into several turns of ambiguous behavior.
Resetting the run may be the right operational response, but it should not be the first way the system regains a known state. The runtime should retain the last valid state and record why it rejected the new event.
Where should the loop stop?
Validate at the translation boundary: after a provider response, tool result, queue message, or persistence record has been normalized into the runtime's internal event. The validator needs enough context to say which event was rejected, which required property or invariant failed, and which run and proposed action were affected.
Then stop the transition. Do not append the event to the active context, mark work complete, or initiate a recovery model call from it. Move to an explicit failed or operator-attention state, preserving the last valid snapshot for inspection or a deliberate retry.
This does not require treating every imperfect external response as fatal to the whole task. A provider timeout, a rejected tool call, and an invalid internal event are distinct cases. The first two can be represented as valid failure events and handled by a recovery policy. The last means the runtime does not know what happened. It must not invent a state transition.
What should the regression prove?
Send malformed versions of each event that can affect the loop: missing identities, invalid lifecycle transitions, tool results that do not match a pending action, and completion events without their required result. For each case, assert three things:
- The trace identifies the rejected event and the violated rule.
- The durable run remains at its last valid state.
- The malformed payload never appears in the next model context.
That final check matters. A validator that emits an error but still stores or replays the rejected payload has only made the corruption easier to find. It has not prevented it.
The one-line version
An agent can recover from a valid failure event; it cannot safely recover from an event whose meaning the runtime never established.
Previous: Agents Are State Machines With a Model in the Loop Next: An API Contract Is Only Real If It Is Enforced