An OpenClaw automation survives retries when running it twice produces one intended outcome. That property is called idempotency. You need it before you automate anything that sends, publishes, charges, deletes, merges, or writes to shared state.
The dangerous failure is rarely a clean crash before work begins. It is a timeout after the side effect happened but before the agent recorded success. The next run sees no completion marker and does the same thing again. Congratulations, your weekly report has become a two-email tradition.
Start with an outcome key
Every run should derive a stable key from the outcome it intends to create. A daily report might use report:2026-08-08. A deployment might use deploy:repo:commit-sha. A content publish might use site:slug. The key describes the business effect, not the attempt number.
job: weekly-ops-report
outcomeKey: weekly-ops-report:2026-W32
attempt: 2
state: running
expectedArtifact: reports/2026-W32.md
sideEffect: email:jake@example.com:weekly-ops-report:2026-W32Attempts get unique folders and logs. Outcomes keep the same key. That lets you investigate attempt two without letting it create a second outcome.
Separate the phases that people usually blur together
| Phase | Question | Durable evidence |
|---|---|---|
| Plan | What outcome are we trying to create? | Outcome key and acceptance checks |
| Prepare | Is the artifact complete and valid? | File, checksum, test output, preview |
| Commit | May the external side effect happen? | Approval or explicit authority |
| Execute | Did the side effect happen? | Provider ID, commit SHA, message ID, URL |
| Close out | Does the result satisfy the original outcome? | Terminal status plus independent verification |
For an email job, rendering the report and sending it are different phases. For a blog job, writing a post, committing it, deploying it, and seeing the production URL are different phases. A single 'done' boolean cannot explain where the run stopped.
Check before you act
- Look up the outcome key in your local status store.
- Look up the external system when possible. Search the sent mailbox, deployment provider, git log, or publishing API.
- If the effect already exists, verify it and close out without repeating it.
- If state is ambiguous, stop and surface the ambiguity. Do not guess with a second irreversible action.
- Only execute when both local and external checks say the outcome is absent.
This is why provider-generated IDs matter. Save the email ID, payment idempotency key, deployment ID, pull request number, or post URL immediately after the call succeeds. A prose note saying 'sent email' is much harder to reconcile after a crash.
Use safe writes for local state
Do not let retries overwrite the same mutable attempt folder. A timed-out process may still be writing after the scheduler marks it failed. Give each attempt its own path, then maintain a small parent summary that points to the accepted attempt.
runs/weekly-ops-report/2026-W32/
summary.json
attempt-1/
status.json
report.md
attempt-2/
status.json
report.mdWrite terminal status before optional cleanup. If the required artifact and checks pass, mark done, then write the nice summary. Otherwise a timeout during summary writing can make completed work look abandoned.
Retry policy by side effect
| Action | Automatic retry? | Guard |
|---|---|---|
| Read API data | Usually | Backoff and bounded attempts |
| Write a local attempt file | Yes | Fresh attempt path |
| Create a git commit | With care | Check intended paths and existing commit |
| Send email or message | Only with dedupe | Stable message key or sent-item lookup |
| Publish a post | Only with slug lookup | Canonical slug and production check |
| Charge or transfer money | Provider support required | Provider idempotency key and strict authority |
| Delete data | No blind retry | Explicit target verification and recovery plan |
The parent must verify the child
A worker's final sentence is not evidence. The parent or controlling run should reconcile the task record, terminal status, expected artifact, repository state, and external side effect. This sounds fussy until the first time a worker finishes the work and times out while trying to report it.
OpenClaw gives you task records and automation run history. Use them, but do not confuse platform success with business success. A run can execute cleanly and still produce the wrong report. It can also time out after producing the right one. Your acceptance check closes that gap.
A small template for the automation prompt
Outcome: create exactly one weekly report for {{week}}.
Before acting:
1. Derive outcome key weekly-report:{{week}}.
2. Check summary state and sent-mail records for that key.
3. If already sent, verify and close out without sending again.
Execution:
4. Work in a fresh attempt folder.
5. Validate the report before any external action.
6. Send once, record the provider message ID, then mark done.
On ambiguity:
7. Stop with state blocked and report the exact reconciliation needed.The wording is deliberately dull. Reliable automation is mostly clear ownership, durable evidence, and refusing to improvise around ambiguity.
Frequently asked questions
What does idempotent mean for an AI agent?
It means repeating a run does not repeat the intended side effect. The workflow checks a stable outcome key and external evidence before sending, publishing, charging, or changing shared state again.
Should OpenClaw automatically retry failed jobs?
Retry read-only and safely isolated work with bounded backoff. Retry external side effects only after adding a reliable deduplication or provider idempotency mechanism.
Is a successful task record enough to prove completion?
No. Verify the expected business artifact, such as the sent message ID, deployed URL, commit SHA, or generated report, in addition to the task record.