A 404 After Receipt: What to Read Back Before an AI Agent Retries
Netsujo Inc. ·
An AI agent calls an external API and gets an error. Should it call the API again? While developing and evaluating Agent Role Contracts (ARC), we found reasons to resist that instinct. In one local fixture, the receiver recorded a request body and then deliberately returned HTTP 404. In another, a SQLite write committed successfully before the application lost the response. The outcome visible to the calling agent depends on the evidence it can retrieve afterward.
The design history of the retry conditions is covered in Testing AI agent trust through public dialogue, and the full contract-to-recovery picture in How much should an AI agent be allowed to do?. This article is limited to the two synthetic fixtures and the comparison of the two lost-response cases.
A 404 that arrived after receipt
The local experiment merged on October 28, 2026 (UTC) in ARC PR #92 records a fictional request body at the receiver, then returns HTTP 404 by design. The verified observation is body receipt in that test environment. It is not a claim that a business ticket was completed or that an external system committed a real-world side effect. Still, the experiment rules out one unsafe inference: “HTTP 404 proves the receiving system did nothing.”
External feedback sharpened the question. A public self-report documented in ARC #69 described a comment-posting API that returned 404 even though a subsequent thread readback found the comment. Matching the author name is a separate check, and it remains unresolved. We have not independently reproduced that external implementation. Its useful lesson is that the existence of a post and the identity attributed to it are two separate findings.
One committed write, two different conclusions
The SQLite fixture merged on November 7, 2026 (UTC) in PR #118 uses a temporary database and Python's standard library. It simulates a lost response after committing a write. Two of its six published cases matter particularly:
| Case | Application status | What a separate read-only connection observes |
|---|---|---|
response_lost | READBACK_CONFIRMED | One committed operation |
reader_unavailable | HOLD_UNKNOWN | One committed operation |
The test oracle can see one committed operation in both cases. The application can confirm it in the first case and leaves the result unknown in the second. UNKNOWN does not mean that no write happened.
Reproduce the public fixture from the repository root:
python3 experiments/cross-tool-effects/sqlite-readback/reproduce.pyThe published expected output ends in 6/6 matched; network=0; resend=0. Those last two values describe how this synthetic test was constructed: it performs no network request or resend. They do not demonstrate exactly-once remote execution.
Reconciliation and permission to retry are separate decisions
For a tool-using system, first ask what happened to the prior logical operation. Only then ask whether another execution is authorized now. Keep the original operation ID and request, obtain trustworthy receiver-side evidence, and preserve UNKNOWN whenever the evidence does not settle the result. If a retry is considered, evaluate current authority and the receiver's idempotency or reconciliation contract separately.
This distinction also matters when work passes from agent A to agent B. B's identity, permissions, and approval can be revalidated, but that cannot tell us whether A's previous request committed. Issuing a fresh operation ID simply because the previous response went missing can produce a duplicate effect.
The order we propose from these two fixtures: (1) keep the original logical operation ID and request, (2) reconcile against the receiver's authoritative record, (3) record an unsettled result as UNKNOWN, (4) if retrying, check current authority and the receiver's duplicate-prevention contract separately.
The SQLite experiment is deliberately bounded. The application and oracle share the same process and read function, and the unavailable-reader case skips application readback with a flag. It does not cover crash recovery, credential separation, OS isolation, real services, every duplicate-operation branch, or network retries. It does not invoke ARC modules at all. ARC's checker validates the consistency of supplied declarations such as roles, authority, scope, review separation, and handoffs. Runtime side-effect enforcement and authoritative readback remain responsibilities of the runtime and receiver.
A useful exercise for your own agent workflow
Choose one mutating API call and inspect what happens after a timeout. Can your system look up the logical operation ID? Can it obtain an authoritative result without sending the command again? Does it preserve uncertainty when the reader is down? Does a handoff create a new operation ID unnecessarily?
Does your system rely on operation-ID lookup or on an independent data readback? What is the minimum evidence your receiver needs before allowing an agent to retry? Share a concrete example in ARC Issue #120, including cases where existing idempotency keys and durable workflows already solve the problem.
Sources and disclosure: PR #92, PR #118 fixture and limitations, external self-report record. Netsujo develops ARC. AI editorial assistance was used in preparing this article; the evidence boundaries are described above.