Why an AI action approval should bind to the exact action
An assistant prepares a message, shows it to a reviewer, and receives approval. Before sending, it refreshes the recipient from a contact record. The record has changed. The message goes to a different person, even though the interface still displays an approved task. The model may have followed its instructions perfectly; the application nevertheless executed something the reviewer never saw.
The engineering question is what connects a human decision to the operation that eventually runs. A task label, conversation history, or green approval badge is insufficient if any of the operation's consequential fields can change underneath it. My preferred starting point is an executable proposal with a defined identity, followed by a decision attached to that identity and a final check at the execution boundary.
This article develops a synthetic document-sharing workflow to make those boundaries concrete. It is an original design exercise, not a description of an implementation I built at UpCube or Ethen. Ethen's public approval overview describes checkpoints whose availability depends on the workflow. That narrower product statement is useful context, but the argument below stands on the explicit contract and failure cases of the example.
Start with the operation, rather than the approval screen
Suppose a research assistant wants to grant read access to a draft diagram. The proposed operation contains a document identifier, the document's current version, a recipient identifier, the requested access level, an expiration time, and the account under which the change will occur. Together, these describe a meaningful action. “Share the diagram” does not.
Some fields belong to the operation's identity because changing them changes what happens. Others describe the interface. The reviewer might see a friendlier document label tomorrow without any change to the underlying resource. That label should not necessarily invalidate the approval. However, a label must never be the only thing identifying the document. A stale or misleading label can cause a human to approve the wrong stable identifier just as easily as a substitution can cause the executor to use the wrong one.
For this example, I would present both the readable label and an unambiguous resource summary: which account owns it, which version is being shared, who receives access, what access means, and when it expires. The operation's machine representation and the human summary should be generated from the same validated proposal. Maintaining separate representations manually creates another place for them to disagree.
A preview is therefore part of the control, not decorative text surrounding it. Reviewers need enough information to understand the effect. The executor needs an exact object to validate. Both must refer to the same proposal version.
An illustrative operation contract
| Field | Meaning in the reviewed effect | Change requires new approval? |
|---|---|---|
| Account and document ID | Which account grants access to which document | Yes |
| Document revision | The content version the reviewer saw | Yes, unless an explicit policy permits later revisions |
| Recipient account ID | The actual recipient, not a display label | Yes |
| Permission | Read-only access in this example | Yes |
| Grant expiry | When the recipient loses access | Yes |
| Decision expiry | Last time the executor may use the approval | Recheck at execution; it is distinct from grant expiry |
These fields describe a synthetic design, not a complete service API. Grant expiry belongs to the proposed effect; decision expiry limits admission to execution. A decision that expires tomorrow must not accidentally grant access only until tomorrow when the reviewed grant lasts a week. Both dates need unambiguous interpretation, and the executor must enforce the intended relationship.
Validate the schema before recording a decision
There is a subtle way to defeat otherwise careful binding: accept fields that the approval representation ignores but the execution handler still uses. Suppose the preview supports a read-access operation, while the executor also accepts an undocumented setting that forwards the document to another account. If that setting never enters the approved identity, the fingerprint can remain unchanged while the external effect expands.
For the synthetic design, I would reject unexpected fields rather than silently discard them. Required fields need explicit types and bounded values. A recipient identifier should not sometimes mean an account identifier and sometimes mean a display name. An expiration should not depend on a locale-specific string format. Missing access level should not fall back to an administrator permission because that happens to be the document service's default.
The schema validator, preview generator, fingerprint builder, and executor should agree on a versioned operation contract. A migration needs to state whether an older decision can still authorize a newer handler. If that compatibility cannot be demonstrated, the older proposal should remain non-executable until it is regenerated and reviewed. Treating schema migration as a routine serialization update can hide a change in authority.
I would include an unknown-field test and a missing-required-field test alongside the substitution tests. They check whether the application fails at admission rather than relying on a later component to interpret an ambiguous operation safely. This does not prove the entire parser is secure. It establishes a specific, testable rule: only the reviewed fields and their documented interpretation can determine the intended effect.
Define equivalence before choosing a fingerprint
Two proposals can look different in memory yet mean the same operation. A dictionary constructed in a different property order is a simple example. Conversely, two proposals can share a label while referring to different recipients. Before using a digest, define which differences count as changes in authority.
In the synthetic workflow, property order is irrelevant, but recipient, access level, document version, account scope, and expiry are consequential. The operation type also belongs in the identity. Otherwise, a representation intended for adding access could accidentally be interpreted by a different operation handler. Schema version belongs there because changing the interpretation of a field can change the effect without changing its text.
Canonicalization makes a chosen representation reproducible. RFC 8785 specifies a JSON canonicalization scheme with defined serialization and ordering rules. An implementation claiming compatibility must follow those rules; a quick sorted-key JSON serializer is not automatically a conforming implementation. The small test in this illustrative exercise uses a deliberately restricted, ASCII-only schema, rather than claiming full canonicalization coverage.
There is a second decision: whether an approval covers a snapshot or a bounded future range. “Share document version seven with this recipient” is a snapshot. “Share any later revision with the same recipient” grants broader authority. Neither should emerge accidentally from a missing version field. If the product needs the second behavior, the interface must explain that scope and the validator must enforce its bounds.
A digest identifies bytes; it does not grant authority
After validating the proposal, the application can serialize it consistently and calculate a fingerprint. The decision record can then refer to that fingerprint, the proposal version, the approving principal, the relevant account, and the decision's expiration.
The fingerprint is an integrity reference. It does not establish who approved anything. An attacker who can replace both the proposal and an unprotected decision record can make their values agree. Authentication of the reviewer, authorization to approve the operation, protection of the decision store, and enforcement at the executor remain separate requirements. Adding a hash does not remove any of them.
I would also avoid treating a fingerprint as a privacy measure. A digest of a predictable recipient or small set of possible operations can expose information through guessing. The proposal still needs appropriate access controls, retention rules, and redaction in logs. The normal debugging view should not display document contents or sensitive recipient data merely because a developer wants to investigate a mismatch.
One practical record might identify proposal P17, revision three, a specific account, an approving user, a bounded execution window, and an unused execution allowance. The exact record format depends on the application. The essential point is that the system can answer two different questions: does this decision refer to these proposed bytes, and does this reviewer have authority to approve this operation here?
Check again where the side effect becomes possible
A check performed when rendering the preview establishes what the reviewer saw at that moment. It cannot establish that the proposal is still unchanged when a worker later acquires permission to modify the document service.
The worker should load the approved proposal and the decision, verify their binding, check current authority, and confirm relevant preconditions before executing. In this example, the document version and current access state are preconditions. If the resource has changed, the product must either reject the stale proposal or follow a separately defined rebasing policy. Silently applying the old approval to a new document revision would expand its meaning.
Concurrent execution complicates this step. Two workers might both observe an unused decision, then both perform the change. A design needs an atomic claim or an equivalent coordination mechanism around consuming the execution allowance. A digest comparison alone does not provide that coordination. Nor does marking the decision consumed after the external service returns close every failure window.
The illustrative exercise accompanying this article verifies that changed recipient, permission, document revision, account, and expired authority are rejected by its simplified admission predicate. Those tests demonstrate only the predicate's behavior on specified inputs. They do not reproduce a distributed transaction or certify an external document-sharing integration. The distinction prevents a useful example from becoming an unsupported production-security claim.
Separate attempts from effects
Imagine that the worker calls the document service, the service grants access, and the network connection fails before a response reaches the worker. The local operation is now uncertain. It is not safe to infer that the grant failed merely because the application did not receive confirmation.
A new attempt should refer to the same intended effect while retaining its own attempt identity. Where the external service supports an appropriate idempotency mechanism, the application can use it within that service's documented scope. Where it does not, recovery may require querying the resulting access state or asking a person to resolve the ambiguity. An approval receipt is not a substitute for understanding the remote operation's semantics.
The synthetic document grant happens to be inspectable: the system can check whether the recipient has the intended access level. That makes reconciliation possible. A message delivery or a physical operation may be harder to inspect. The recoverability of one action should not be generalized to every action an agent can propose.
The decision record should make this difference visible. “Approved,” “execution attempted,” and “effect confirmed” are distinct states. An interface that compresses them into “done” deprives the reviewer of exactly the information needed after a failure. For a fuller treatment of the resulting record, see the methods and evidence themes collected on the site's research page.
Expiry, revocation, and changed policy need explicit rules
Approval can become invalid even when the proposal remains byte-for-byte identical. The reviewer might revoke it. The approving account might lose authority. The execution window might end. A policy governing document sharing might change.
I would evaluate these conditions separately from the proposal fingerprint. Binding every volatile account attribute into the proposal would make harmless changes invalidate the action, while failing to check current authority could let an old decision survive a meaningful change. The appropriate split is between the intended operation and the conditions under which executing it remains permitted.
Revocation also has a timing boundary. If a worker has already crossed the external commit point, a subsequent revocation cannot retroactively prevent that effect. The product should say whether revocation cancels queued work, interrupts a cooperative worker, or creates a request to reverse an already completed change. These are different capabilities, and a single “cancel” button should not imply all of them.
Policy versioning makes investigation easier, but storing a policy version is not the same as enforcing current policy. The decision record can retain the rule set under which approval was granted, while the executor applies the current admission rule. If the product permits exceptions, they need their own bounded authority and audit trail. They should not be manufactured by interpreting a broad conversation instruction as a permanent exemption.
Design the changed-proposal experience
When the proposal changes, the interface should explain the consequence in terms the reviewer can assess. “Recipient changed from the intended collaborator to a different account” is more useful than “hash mismatch.” The machine comparison can drive a field-level change summary without showing every incidental difference in serialization.
A changed operation should receive a new proposal version. The previous decision remains historical evidence of what was approved, rather than being overwritten to make the current view look tidy. The new version can point back to its predecessor and explain why it was generated. That preserves the distinction between a rejected operation, a withdrawn operation, and a revised operation awaiting a fresh decision.
The product should also avoid making reapproval automatic through frictionless defaults. A reviewer presented with twenty inconsequential label changes may learn to approve without reading. One reason to define semantic identity carefully is to reserve interruptions for changes that actually affect authority, scope, or expected effects. Precision improves both enforcement and the human decision process.
For repeated tasks, a bounded standing authorization may be more appropriate than individual approval for every operation. It should still define permitted resources, recipients, operation types, budgets, and duration. The executor then checks whether each proposal is inside those bounds. Standing authorization is a different contract, not a shortcut that lets an old one-off decision silently cover a new task.
Test substitutions, stale state, and recovery independently
A useful test matrix starts with one known-good proposal and changes each consequential field individually. Change the recipient while keeping the label. Change the permission while keeping the document. Change the account while keeping the recipient. Change the resource revision while keeping the document identifier. Each mutation asks whether an unchanged approval can authorize a different effect.
Then test conditions outside the fingerprint. Use an expired decision, a revoked decision, an unauthorized reviewer, and an already consumed allowance. Test policy changes separately. These cases expose missing admission checks that a representation test alone would never reveal.
Concurrency and recovery need another layer of evidence. Introduce duplicate queue delivery, a worker crash before calling the external service, a lost response after a possible effect, and a worker crash while saving its receipt. Observe whether the system can distinguish “not attempted” from “outcome unknown.” A successful happy-path demonstration provides almost no evidence about these windows.
Finally, test the review surface itself. Does the summary show the same recipient and revision that the executor checks? Can translated labels conceal a changed scope? Is the expired status understandable with a keyboard or screen reader? Does the reviewer see whether a previous attempt may already have succeeded? These are functional questions about the control, not polish to add after its security logic is finished.
Keep the conclusion as narrow as the evidence
An exact-action approval design can establish a useful relationship: this authenticated decision refers to this defined proposal within these execution conditions. It cannot establish that the proposal is wise, that all possible harmful operations are covered, or that the surrounding system is immune to manipulation.
I would judge the design by whether its records and failure behavior preserve that narrow relationship. A changed operation should require new authority. An uncertain outcome should trigger reconciliation. A consumed or revoked decision should not remain an executable permission. A reviewer should be able to distinguish the intended action from what actually happened.
That standard makes approval a concrete engineering boundary instead of a vague promise that a human is somewhere in the loop. The next implementation decision is not which badge to display. It is which fields define the effect, which preconditions must still hold, and what evidence the executor will leave when the world does not cooperate. More technical writing on these boundaries is collected in the Articles and archives hub.
Sources
- Ethen — Approvals — company-authored context; not independent implementation evidence.
- RFC 8785 — JSON Canonicalization Scheme — primary methodological or standards source.
- Ethen — Binding Computer-Use Approvals to Specific Actions — company-authored context; not independent implementation evidence.