Human approval is a decision about one action under a particular set of facts. It is not a permanent permission bit.
Imagine an AI agent preparing a refund request:
Order: SO-1001
Amount: CNY 199.00
Reason: Duplicate payment
Enter fullscreen mode Exit fullscreen mode
The runtime classifies the action as high risk, pauses the task, and asks a human to approve the exact request.
At 10:00, the approver reviews the parameters and clicks Approve.
The task does not execute immediately. It remains paused, waits in a queue, survives a coordinator restart, and finally reaches dispatch at 15:00.
During those five hours, any of the following may have changed:
- the order may already have been refunded by another channel;
- the refund policy may now require an additional finance review;
- the approver may no longer hold the required role;
- the acting subject may have left the organization;
- the amount or currency may have drifted during task reconstruction;
- the tool implementation may have changed;
- the approval may have been valid for only 30 minutes.
Should the system execute merely because a database row still says approved = true?
No.
The approval was not a timeless grant. It was a decision about a specific action, represented by a specific subject, using a specific capability, with specific arguments, under a specific policy and set of business facts.
This distinction becomes essential when agents move beyond answering questions and begin creating real business consequences.
1. The dangerous simplification: approval = true
In conventional administrative software, approval and execution are often close together. A user submits a form, a manager approves it, and the system performs the action soon afterward.
That interaction encourages a simplified mental model:
approval = true
Enter fullscreen mode Exit fullscreen mode
Once that value is stored, downstream code treats the action as permanently authorized.
Agent tasks are different. A single task may cross several asynchronous boundaries:
understand intent
-> select a capability
-> construct arguments
-> request approval
-> wait for a human
-> resume the task
-> enter a dispatch queue
-> call the business system
-> record the outcome
Enter fullscreen mode Exit fullscreen mode
The lifecycle may last minutes, hours, or days. Processes may restart. Policies may be redeployed. Business objects may change through other channels.
In that environment, “approval happened” is only a historical fact. It does not prove that the action is still valid now.
A production design must distinguish at least five concepts:
Concept Question it answers Approval intent Does this kind of operation require human intervention? Approval decision Did a qualified person agree to this specific action? Approval evidence What subject, capability, arguments, policy, and time did that decision bind? Approval validity Does that evidence still apply at dispatch time? Final business authority May the business system create this consequence now?Collapsing all five into one boolean hides the most important failure modes.
2. Approval must bind an action, not a vague intention
An approval prompt such as this is not enough:
Approve the refund?
Enter fullscreen mode Exit fullscreen mode
It does not tell the approver:
- which order will be changed;
- how much money will move;
- which currency is involved;
- whose authority the agent represents;
- which capability will execute;
- which policy version produced the approval requirement;
- how long the decision remains valid;
- whether the task may execute more than once.
A useful approval record should bind a concrete execution envelope. Depending on the assurance level, it may include:
trusted_subject
capability
canonical_arguments
task_identity
policy_version
approval_time
expiry_time
approver
Enter fullscreen mode Exit fullscreen mode
Higher-assurance deployments may also bind:
tenant
business_object_version
tool_or_server_artifact
request_purpose
delegation_context
Enter fullscreen mode Exit fullscreen mode
Not every implementation needs the same representation. Some may use a signed object, some a durable database record, and some an external approval system. The invariant is more important than the format:
The system must be able to prove that what is about to execute is still the action that was reviewed.
3. A parameter hash protects structure, not time
A common safeguard is to canonicalize the arguments and store a hash:
args_hash = SHA256(canonical_json(arguments))
Enter fullscreen mode Exit fullscreen mode
Before dispatch, the runtime computes the hash again. If the value differs, the previous approval cannot be reused.
This prevents a dangerous class of drift:
At approval:
order_id = SO-1001
amount = 199.00
At execution:
order_id = SO-1001
amount = 19900.00
Enter fullscreen mode Exit fullscreen mode
But an identical parameter hash does not prove that execution is still safe.
The arguments may be unchanged while:
- the acting subject has lost access;
- the approval has expired;
- the applicable policy has changed;
- the order has already been refunded;
- the capability now points to a different implementation.
So argument equality is a necessary condition for approval reuse, not a sufficient one.
This is the core distinction:
Structural integrity:
Is this the same request?
Temporal validity:
Is the decision still applicable now?
Enter fullscreen mode Exit fullscreen mode
A robust system needs both.
4. Four kinds of drift can invalidate an approval
Approval freshness is not one check. It is a collection of checks owned by different components.
4.1 Request drift
The capability, canonical arguments, trusted subject, tenant, or task identity no longer matches the approved envelope.
Expected behavior: do not dispatch. Return the same durable task to an approval-required state or reject it before dispatch.
4.2 Subject and authority drift
The acting subject or approver no longer holds the role, membership, delegation, or authority required by current policy.
Expected behavior: re-resolve trusted identity and authorization from an authoritative system. Never trust model-generated identity fields.
4.3 Policy and capability drift
The risk policy, approval threshold, route allowlist, capability declaration, or tool implementation changed while the task was paused.
Expected behavior: compare the approved policy and capability context with the current context. If the change is material, require a new decision.
4.4 Business object drift
The order, invoice, account, inventory item, deployment target, or other business object changed after approval.
Expected behavior: the business system, or a fresh preflight API backed by the same authoritative data, must re-evaluate current state and final permission.
The ownership boundary can be summarized as follows:
What may have changed? Natural owner of the current truth Canonical arguments and task identity Agent runtime or shared execution control Trusted subject and delegation Identity and authorization systems Approval validity and policy version Approval authority and deployment policy Capability route or tool artifact Execution control and tool operator Business object state and final permission Business systemNo single approval service can safely manufacture all of these truths.
5. Dispatch is the real checkpoint
The most important validation moment is not when the human clicks Approve. It is immediately before the business action is dispatched.
A conservative resume path looks like this:
1. Load the same durable task identity.
2. Reconstruct the canonical execution envelope.
3. Verify that the capability and arguments still match the approval evidence.
4. Check whether the approval is expired or revoked.
5. Compare the approved policy context with the current policy context.
6. Re-resolve the trusted subject where required.
7. Dispatch with a stable business idempotency identity.
8. Let the business system recheck object state and final authority.
9. Record the outcome against the same task.
Enter fullscreen mode Exit fullscreen mode
If any pre-dispatch binding fails, the task must not silently continue.
The correct outcome is usually one of:
awaiting_reapproval
rejected_pre_dispatch
Enter fullscreen mode Exit fullscreen mode
The exact state name is implementation-specific. The safety property is not:
“We have an approval record.”
It is:
“No business dispatch occurs under approval evidence that is no longer valid.”
6. Expiry is not a retryable transport failure
Approval expiry must not be handled like a temporary network error.
Consider this sequence:
task T is approved
-> approval expires
-> dispatcher attempts to resume T
-> validation detects expiry
Enter fullscreen mode Exit fullscreen mode
Unsafe implementations may create a new task, retry automatically, or reuse the old approval because the arguments have not changed.
All three behaviors weaken the control boundary.
The safer rule is:
same durable task
-> expired approval detected
-> no dispatch
-> explicit reapproval or terminal rejection
Enter fullscreen mode Exit fullscreen mode
Creating a new task merely to bypass an expired decision destroys continuity. Treating expiry as a transport retry confuses policy failure with delivery failure. Reusing the old decision converts a time-bounded approval into permanent authority.
The task identity should survive. The authorization to execute may not.
7. Policy version is part of the approval context
An approval decision is usually produced under some policy version:
policy_version = refund-policy-2026-08-01
Enter fullscreen mode Exit fullscreen mode
When the task resumes, the runtime should be able to compare:
approved_policy_version
current_policy_version
Enter fullscreen mode Exit fullscreen mode
But a version mismatch does not always require the same response.
Policy change Example Possible response Non-material Wording or UI guidance changed Continue while preserving evidence More restrictive Finance approval is now required Require reapproval Less restrictive The no-approval threshold increased Reuse or re-evaluate according to deployment policyA portable contract can require implementations to preserve the relevant policy context. It should not attempt to standardize every enterprise’s definition of a material policy change.
That decision belongs to deployment policy and the authority that owns the rule.
8. Approval freshness does not replace business freshness
Even perfectly valid approval evidence cannot prove that an order is still refundable.
The approval layer may know:
the approver agreed to refund SO-1001 for CNY 199.00
Enter fullscreen mode Exit fullscreen mode
Only the business domain can reliably know:
whether SO-1001 still exists
whether it belongs to the current tenant
whether CNY 199.00 remains refundable
whether another refund already succeeded
whether the subject may perform this action now
Enter fullscreen mode Exit fullscreen mode
This is why an agent governance architecture must preserve the final business boundary.
Approval is evidence that a required human decision occurred. It is not a substitute for current object-level authorization, transaction constraints, tenant isolation, or domain invariants.
In short:
Approval controls whether execution may proceed.
The business system controls whether the consequence may exist.
Enter fullscreen mode Exit fullscreen mode
9. Make the boundary executable
Architecture diagrams are not enough. Approval validity should be expressed as failure scenarios that different implementations can run.
One useful test case is:
Scenario: approval expires while a task is paused
Given:
- one durable task identity
- approval evidence bound to a trusted subject,
canonical arguments, capability, and policy version
- implementation-defined validity metadata
When:
- the runtime attempts to resume or dispatch the task
- after the approval is no longer valid
Then:
- expiry is detected before dispatch
- dispatch_count remains 0
- business_effect_count remains 0
- the old approval is not reused
- the same task moves to reapproval or pre-dispatch rejection
Enter fullscreen mode Exit fullscreen mode
The test should also forbid these shortcuts:
- dispatching under expired approval;
- treating expiry as a retryable transport error;
- creating a new durable task to evade expiry;
- interpreting prior approval as current business authority.
Implementations may choose different clocks, leases, TTL formats, state names, and workflow engines. They should still be able to prove the same externally observable property.
That is the difference between saying “we support human approval” and demonstrating that approval remains meaningful under failure and delay.
10. What belongs in a portable contract, and what does not?
It is tempting to solve this by adding every runtime concern to a capability declaration:
approval:
required: true
ttl: 30m
workflow: finance-review-v7
approver_query: ...
policy_engine: ...
Enter fullscreen mode Exit fullscreen mode
That quickly turns a portable declaration into an organization-specific workflow language.
A cleaner boundary is:
Portable capability declaration
It can express that an operation carries approval intent and other stable governance semantics.
Runtime and approval authority
They implement evidence binding, validity metadata, expiry, revocation, pause and resume behavior, and policy-version handling.
Business system
It rechecks current subject authority, tenant boundaries, object state, domain invariants, and final permission immediately before creating the consequence.
The standard should describe the smallest portable meaning. Implementations should make the operational guarantee real. The business system should retain authority over its own state.
This division is deliberate. It keeps the contract interoperable without pretending that one schema can replace enterprise identity, approval workflows, or business authorization.
11. A practical review checklist
When reviewing an agent approval path, ask:
- Is approval bound to the exact capability and canonical arguments?
- Is the trusted subject sourced outside model-generated input?
- Does the approval carry validity or revocation semantics?
- Is the applicable policy version preserved?
- Are material policy changes detected before dispatch?
- Does task resume preserve one durable task identity?
- Does expired approval return to reapproval instead of automatic retry?
- Is a stable idempotency identity carried to the business boundary?
- Does the business system recheck current object state and final authority?
- Can tests prove that invalid approval produces zero business effects?
If the system cannot answer these questions, approved = true is not a governance guarantee. It is only a historical flag.
Conclusion
Human-in-the-loop is often presented as a screen with two buttons: Approve and Reject.
The real engineering problem begins after the click.
An approval decision must remain bound to the subject, capability, arguments, task, policy, and validity conditions that gave it meaning. When a paused agent task resumes, the system must determine whether those bindings still hold. If they do not, execution must stop before dispatch. If they do, the business system must still perform fresh, final authorization.
The governing principle is simple:
Approval is not a boolean. It is time-bound evidence for one concrete action, and its validity must be proven again at the moment of execution.
Further Reading
- What Is Missing Between MCP Tool Selection and Safe Execution?
- Agent Capability Contract (ACC)
- BailingHub on GitHub
Disclosure
I maintain ACC and BailingHub, two open-source efforts exploring portable capability-governance semantics and self-hosted execution controls for agents operating existing business systems. They are concrete design experiments, not the only valid architecture. The business system remains the final authority.
답글 남기기