Approve the action, not the conversation
An incident assistant recommends restarting worker-7 to reduce a queue backlog. An operator clicks approve, but before execution the assistant changes the target to worker-8 or expands the operation to every worker. A generic approved flag cannot distinguish those proposals. Human involvement is not an effective control unless the system binds the decision to the exact action that was presented.
Our proposed approval record includes a proposal fingerprint, workflow revision, assigned reviewer, expiry and state. The model may draft the proposal, but trusted application code determines the reviewer and validates the eventual decision. Approval applies to a bounded action in a known context. It is not a standing permission for the assistant to pursue the same broad goal by any means it later chooses.
Architecture and request sequence
Read the architecture as text
- Proposal adapter: Suggest a bounded operation
- Approval record: Digest, revision and expiry
- Reviewer interface: Authenticated human decision
- Decision validator: Identity and context checks
- Dispatch marker: Single local consumption
- Proposal adapter → Approval record: persist proposal
- Approval record → Reviewer interface: present exact action
- Reviewer interface → Decision validator: submit decision
- Decision validator → Approval record: approved or rejected
- Approval record → Dispatch marker: consume if current
Read the sequence as text
- Agent → Store: Create pending proposal
- Reviewer → Store: Read exact action
- Reviewer → Store: Submit bound decision
- Dispatcher → Store: Recheck and consume
- Store → Dispatcher: Return local marker
Bind the proposal to its context
The action is serialized with sorted keys and compact separators, then hashed. Equivalent key ordering yields the same fingerprint, while a changed target yields another fingerprint. The workflow revision is checked separately because identical action arguments can have different implications under changed code or policy. The reviewer must see a readable action summary, target and consequence; a cryptographic digest is a binding mechanism, not a usable explanation.
Decide which contextual changes invalidate consent. A fresh incident severity, changed deployment version or expired maintenance window may require a new review even when the action text is unchanged. The lab uses one revision string and an expiry timestamp to keep this boundary visible. A production design should derive those values from trusted state rather than accepting model-generated claims that the proposal remains current.
The dispatch boundary needs its own receipt
Consumption atomically changes approved to consumed only when the fingerprint, revision and expiry still match. The returned object is explicitly a local dispatch marker. It does not restart a worker, call a cloud API or prove that a remote action happened. This distinction prevents a successful authorization check from being mislabeled as successful remediation.
For a remote effect, combine approval consumption with a durable dispatch record, then send a stable operation identifier through an idempotent adapter. A crash after marking approval consumed but before sending needs a recoverable pending dispatch, not a second approval bypass. A crash after sending needs reconciliation with the destination. Our module intentionally stops before that distributed boundary; integrating the transactional outbox pattern is a separate engineering step.
Capacity and reviewer experience
Assume a team can review twenty proposals per hour and the assistant generates fifty. A durable queue prevents loss but does not create reviewer capacity. Prioritize by incident risk, combine redundant proposals and suppress requests that lack sufficient evidence. Track age and expiry so an operator does not approve a stale action simply because it finally reached the top of the queue.
Present enough information for a decision: incident identity, exact target, proposed operation, evidence references, expected impact, expiry and available alternatives. Avoid approval fatigue by requiring review where it changes risk, while allowing already authorized read-only investigation to proceed. The escalation policy should be explicit. Automatically changing a pending request to approved after a timeout defeats the purpose of the boundary; expiry should lead to a defined nonexecution path.
Acceptance before live tools
The original example requires matching reviewer identity, action digest, revision and time, and makes local consumption single-use. Its tests cover changed proposals, expired approval, rejection, duplicate decisions and restart persistence. The reviewer identity in the fixture is supplied by trusted test code; the module does not authenticate a browser user or verify a signed token.
Before adding live tools, test the UI-to-service identity path and a replayed approval response from another session. Evaluate whether operators can actually understand the proposed consequences through the evaluation process, not just whether the database accepts a boolean. A safe pause is only the first half of this pattern. The resume path must prove that the same bounded action is still authorized at the moment of dispatch.