{"slug": "stale-approvals-re-check-the-draft-before-you-execute-it", "title": "Stale Approvals: Re-Check the Draft Before You Execute It", "summary": "A developer outlined a fingerprinting technique for preventing \"stale approvals\" in AI workflows, where a human approves an AI-drafted action that becomes invalid before execution. The approach hashes the action together with its context—such as the latest message ID, order status and amount—at approval time, then recomputes the fingerprint before execution and routes the action back to the reviewer if anything has changed. The code also uses the action ID as an idempotency key to avoid duplicate execution.", "body_md": "A reviewer approves an AI-drafted refund at 4 pm. The workflow executes it at 4:05. Between those times, the customer wrote \"never mind, found it.\" Who is right? This is the stale approval problem, and it shows up in almost every [human-in-the-loop approval step in an AI workflow](https://www.nxflowai.com/blog/custom-ai-vs-off-the-shelf-chatbots) once volume grows.\n\nApprove a specific snapshot, not \"the refund for customer X.\"\n\n``` python\nimport hashlib, json\n\ndef fingerprint(action, context):\n    payload = {\"action\": action, \"last_msg_id\": context[\"last_msg_id\"],\n               \"order_status\": context[\"order_status\"], \"amount\": action.get(\"amount\")}\n    return hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest()\n\ndef request_approval(store, action, context):\n    fp = fingerprint(action, context)\n    store.save(action_id=action[\"id\"], fingerprint=fp, status=\"pending\")\n    return fp\npython\ndef execute_if_still_valid(store, action, load_context, run):\n    record = store.get(action[\"id\"])\n    if record.status != \"approved\":\n        return \"not_approved\"\n    if fingerprint(action, load_context(action)) != record.fingerprint:\n        store.update(action[\"id\"], status=\"needs_review\")\n        return \"stale_back_to_reviewer\"\n    run(action, idempotency_key=action[\"id\"])\n    store.update(action[\"id\"], status=\"done\")\n    return \"done\"\n```\n\nWe write about scoping these decisions in our guide to auditing a workflow first.", "url": "https://wpnews.pro/news/stale-approvals-re-check-the-draft-before-you-execute-it", "canonical_source": "https://dev.to/ujjwal_dubey_9/stale-approvals-re-check-the-draft-before-you-execute-it-1g0", "published_at": "2026-10-25 11:04:15+00:00", "updated_at": "2026-10-25 11:12:35.177071+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "artificial-intelligence"], "entities": ["nxflowai.com"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/stale-approvals-re-check-the-draft-before-you-execute-it", "markdown": "https://wpnews.pro/news/stale-approvals-re-check-the-draft-before-you-execute-it.md", "text": "https://wpnews.pro/news/stale-approvals-re-check-the-draft-before-you-execute-it.txt", "jsonld": "https://wpnews.pro/news/stale-approvals-re-check-the-draft-before-you-execute-it.jsonld"}}