Thrive AI Engineering
← All questions

agentic-ai · Editorial starter

How do I prevent an agent from changing an action after a human approved it?

By Thrive AI Editorial · Created 2026-10-07 · Updated 2026-10-07

Thrive AI Editorial · AI-assisted worked example, not a member conversation.

A reviewer approves a proposed tool action. Before execution, the agent recomputes its arguments and changes the destination or amount. A stored boolean still says approved. What exactly should the approval be bound to?

This editorial scenario uses a harmless work-item operation and no external service. It is about approval integrity, not a complete identity or payment system.

0 score

Sign in to vote or contribute. Scores count actual member votes, not editorial endorsements.

1 published answer

A selected solution is chosen by the question author or moderator, not an independent certification. Check assumptions before using any code in production.

Thrive AI Editorial

Thrive AI Editorial · AI-assisted worked example, not a member conversation.

2026-10-07

An approval must describe a particular action

A boolean such as approved=true is incomplete unless it refers to an immutable proposal. Bind the decision to the authenticated actor, tool, target, normalized arguments and proposal version. At execution, compare the exact proposal with the approved record. A changed proposal needs a fresh decision.

Human-in-the-loop pauses are useful orchestration primitives, not substitutes for execution authorization. LangGraph documents that a resumed interrupted node restarts from its beginning. Code before the interrupt may run again. Do not put an unprotected external side effect before a pause and assume resuming will skip it.

Code / output
propose -> freeze payload -> human review -> verify same payload -> execute
                    changed payload -> require another review

Test approval binding

Python 3, standard library only. This local example detects mutation of JSON-compatible data. It is not a signed token and does not authenticate a caller.

Code / output
import hashlib
import json

def fingerprint(proposal):
    encoded = json.dumps(proposal, sort_keys=True,
                         separators=(",", ":"), allow_nan=False).encode()
    return hashlib.sha256(encoded).hexdigest()

proposal = {"actor": "reviewer-a", "tool": "create_work_item",
            "target": "project-alpha", "title": "Review run", "version": 1}
approved = {"digest": fingerprint(proposal), "used": False}

def consume(record, action):
    if record["used"]:
        raise ValueError("approval already used")
    if record["digest"] != fingerprint(action):
        raise ValueError("proposal changed")
    record["used"] = True

changed = dict(proposal, target="project-beta")
try:
    consume(approved, changed)
except ValueError as error:
    print(error)
assert not approved["used"]
consume(approved, proposal)
assert approved["used"]
try:
    consume(approved, proposal)
except ValueError as error:
    print(error)

Expected output:

Code / output
proposal changed
approval already used

What the simulation deliberately leaves out

In production, checking and consuming the approval must be atomic. Two workers must not both observe unused=true and both execute. Persist the reviewed proposal, expiry, reviewer identity and execution state. Recheck current authorization; a previously approved actor may have lost access.

Consuming approval before an external tool call introduces an uncertain-outcome problem if execution times out. Do not simply unconsume it and run again. Use an operation identifier, a provider idempotency mechanism where supported, and reconciliation. Approval integrity and exactly-once effects are separate concerns.

Define normalization rules before review. A digest of unstable serialization, floating-point amounts or differently ordered semantically equivalent data can produce confusing approvals. Our small JSON example avoids those application-specific questions rather than claiming to solve them.

Test the boundary, not the button

Change each material argument after approval. Replay a decision. Try an expired decision and a revoked reviewer. Race two execution workers. Restart during the approved-but-not-executed state. Assert that changed actions require review and uncertain effects are reconciled instead of blindly repeated.

Source checked 2026-10-08: LangGraph interrupts. The node restart and persistence behavior comes from the documentation. The proposal digest, atomic-consumption design and runnable example are our original AI-assisted engineering explanation, not built-in security guarantees of LangGraph.

0 score

Sign in to vote or contribute. Scores count actual member votes, not editorial endorsements.

Verify your sign-in to contribute an answer

Reading is free. Posting requires a verified account and moderation; no course purchase is required.