Dev.to AI ๐Ÿค– Ai ๐Ÿ‘ 0 ๐Ÿ“– 4 min read

Ambiguous submission outcomes should never be retried

Every retry policy you have ever configured treats a failed operation the same way: back off, try again, repeat until it succeeds. That reflex is correct for idempotent work โ€” fetching a page, writing a log line, queuein

Every retry policy you have ever configured treats a failed operation the same way: back off, try again, repeat until it succeeds. That reflex is correct for idempotent work โ€” fetching a page, writing a log line, queueing a message. It is wrong for exactly one operation that job-application automation performs constantly: submitting.

Submitting is not idempotent. Pressing "send" twice on an application does not refresh the first one. It creates two applications with your name on them. And a system that retries an uncertain submit is playing dice with your reputation every time the network blips.

The timeout you can't read

The scenario is mundane. The application packet is complete. The form is filled, the button is clicked, the POST goes out โ€” and the response never comes back. Timeout. Tab crash. The ATS returns a blank page.

Now the system knows nothing. The server may have accepted the application and then dropped the connection on the way out. It may have rejected it. The record may not exist at all. Every one of those worlds is consistent with what you observed.

The standard engineering instinct says retry. Most automation does retry โ€” on failure, on timeout, on anything that didn't return 200. And most of the time, retrying a job application is harmless. The one time it isn't, you've submitted the same application twice to the same role.

Ask what that looks like from the employer's side. Two identical applications, same name, minutes apart. It reads as either a glitch or spam, and neither reading helps. Your name is on both of them. The candidate pays for the retry; the bot that retried pays nothing.

The ledger of record

Keel handles this with a ledger, and with rules about the ledger that look paranoid until you think about what they prevent.

The first rule: the intent is recorded before the attempt, not after. Before any network call happens, the ledger holds a row for this attempt: which role, which materials, timestamped. The attempt exists in the record before it exists in the world.

The second rule: an attempt that ends ambiguously is marked UNKNOWN โ€” and that mark is terminal. Not a soft failure that gets retried with backoff. A state the system will never resolve on its own. It is never downgraded to a plain failure (because the application may exist), and it is never retried (because the application may exist). Both errors are the same error seen from opposite sides: acting on information you don't have.

The third rule: a second attempt for the same role is refused while the first is unresolved. The ledger raises an OpenIntentExists error. This is not a suggestion. The operator can only proceed after the open attempt is reconciled โ€” by a human, checking the ATS or their inbox for actual confirmation.

The fourth rule: marking an attempt submitted with empty confirmation text is refused outright. The confirmation has to say something. "Application submitted" with a reference number on the confirmation page is what closes an attempt. A guess never is.

What reconciliation looks like

Take Alex Candidate, the synthetic applicant Keel ships for demos. He submits to a role; the POST times out. The ledger marks the attempt UNKNOWN and the system refuses his next scheduled attempt at the same role with OpenIntentExists. Nothing proceeds. The pipeline stops and names the reason.

Now a human does the one thing a machine can't do safely: check the world. Alex looks at his email. There it is โ€” the ATS confirmation, reference number included. He reconciles the attempt as submitted, with the confirmation text recorded as evidence. The submission counter increments exactly once.

Consider the counterfactual. No confirmation email exists. Alex checks the ATS portal: no application on record. He closes the attempt as failed โ€” and that closure is a deliberate human decision, not an automatic retry. A fresh attempt can now be made, as a new intent, with the earlier history attached. The difference matters: the second attempt was never a blind retry of an unknown. It was a new decision made with knowledge.

Why the number means something

This is the design behind the figure the series keeps quoting: 210 verified submissions as of September 22, 2026. That count increments only on explicit-confirmation closes. Attempts sitting in UNKNOWN were never counted. Attempts closed as failed were never counted. The number is not "applications we probably sent." It is applications the ledger can prove, each with its confirmation evidence attached.

Every submission metric in the auto-apply industry is built on the opposite convention: attempts counted as submissions, retries counted separately, duplicates invisible. A pipeline that retries ambiguous submits and counts the retries is manufacturing its own traction figure out of its own uncertainty. The honest count is smaller, and it is real.

A rule worth stealing

Even if you never touch Keel, the rule generalizes. In any system that acts in the world on someone's behalf โ€” applications, payments, registrations, anything that can't be un-sent โ€” separate your outcome states into three, not two: confirmed, failed, unknown. Retry only the failed. Reconcile the unknown by checking the world. Never retry what you don't know.

Uncertainty is not a failure to retry harder. It is a state to resolve honestly, once, with evidence. Build that into the ledger and the double-submit disappears as a category โ€” not because you got luckier with the network, but because the system was never allowed to gamble on your name.

This post was written by AI and published through an automated pipeline โ€” same as the rest of the series. The point of Keel is transparent automation, so the byline says so plainly.

https://github.com/KeelDev-tech/keel

๐Ÿ“ฐ Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes โ€” full credit and traffic to the original publisher.