Forum Discussion
MCP action approvals after expiry: review and replay tests from a Copilot Studio pilot
Good way to test it: checking target state independently of the agent trace is the right habit. A few failure cases I would add before qualifying the approved execution and replay path:
- Approve versus expire race. Test a reviewer approving exactly at, just before and just after the expiry boundary, and make sure there is one clock for both decisions (the runtime or the store, not the browser or the reviewer UI). Clock skew between components is a common source of approvals that look valid in one place and expired in another.
- Concurrent execution. Two workers or a double click both presenting the same approved claim. Consuming the claim should be an atomic compare and set, so one wins and the other gets a clear "already used", and the write should also carry an idempotency key.
- Crash between the write and the mark complete. The write lands but the response is lost, or the process dies before the record is updated. A retry must detect the unresolved effect and verify the target state rather than writing again.
- Stale target. Approved at version 1, but the catalogue moved to version 2 before execution. You already carry versions, so test that execution fails closed and the reviewer sees why, instead of silently applying the old action.
- Modified proposal. Any change to the action after approval, including field order or whitespace in the payload, should invalidate it. Binding the approval to a hash of the canonical form of the exact action is simpler than comparing fields.
- Authority changes. The approver is removed or the delegated scope is revoked between request and decision, or the requester approves their own proposal.
- Token lifetime. The delegated token expires between approval and execution, and the runtime must not fall back to broader app permissions to finish the job.
- What the reviewer sees. The reviewer should see the structured action to be executed, not the model's description of it, so that text injected through a tool result cannot make a harmful action look harmless.
If those pass on both the local suite and Azure, the remaining risk is mostly operational, such as alerting on expired and unresolved items.
- sev7enOct 27, 2026Brass Contributor
Thanks, WinEndpointOps. The expiry case connects directly to my recent work on PALO. I corrected the withdrawal path for an expired review request and verified that the catalogue remained unchanged. The same 89-test suite passed locally and on Azure Linux. Approved execution and replay are the next qualification step.
I would test concurrent execution and a lost response separately. An atomic claim handles competing workers; a write followed by a crash needs durable evidence from the target before a retry. The final value alone can be ambiguous if another actor could have produced it. On canonicalization, JSON property order and insignificant whitespace should keep the same digest when the agreed rules treat them as equivalent. Changes to the operation, target, parameters or expected version must invalidate the approval.
For the native-control comparison, I would keep identity scopes, actions and injected failures identical, including revocation and recovery checks. Which baseline would you prioritize: a workflow approval tied to the exact action, or an application-level approval record with target-side idempotency?