Forum Discussion

sev7en's avatar
sev7en
Brass Contributor
Oct 26, 2026

MCP action approvals after expiry: review and replay tests from a Copilot Studio pilot

I am testing an approval and recovery pattern for a Copilot Studio agent calling a custom MCP endpoint on Azure. I would appreciate feedback on the failure cases to add before qualifying the approved execution and replay path.

Context

I built PALO, an independent governance project. This private pilot uses a synthetic catalogue with one price and resource version. Microsoft Entra supplies delegated identity; the runtime checks the admitted caller, delegated scope, time-bound mandate and exact proposed action. The connector uses federated authentication without a client secret. A separate reviewer interface records decisions; approval itself does not write the catalogue.

Observed cases

• The actual Copilot test agent invoked a catalogue read and returned price 100/version 1.

• Proposal 151/version 1 was denied, with zero target writes confirmed independently in persistent records.

• Proposal 120/version 1 required review and expired without execution.

• We reproduced a withdrawal defect for the expired-approval state. The correction permits withdrawal in that state only when the action claim has also expired, while preserving the authorization, version and unresolved-effect checks. The same 89-test suite passed locally and on Azure Linux, followed by a reviewer withdrawal confirmed in UI and persistent records.

Lessons so far

1. A connection shown as configured did not qualify the consuming-agent path. We retained the actual tool-call trace and checked target state separately.

2. MCP media negotiation mattered: the connector request Accept policy needed application/json and text/event-stream.

3. The five-minute action-claim validity, approval record lifetime and authentication freshness are different clocks. An expired request must not be silently renewed or automatically resubmitted.

Next qualification gate

We still need one fresh linked successor, a new reviewer decision, execution of that exact request, independent verification of one target effect, and a replay with no second effect. Two identities are operated by the same person in this pilot, so this only tests technical role separation. Incremental benefit over native identity, workflow and logging controls has not yet been measured.

Questions for builders

• Which expiry, revocation, concurrent-update or ambiguous-outcome cases would you prioritize before approving the live execution and replay test?

• What native-control baseline would make an incremental-value comparison credible?

Configuration record and dated evidence:

https://paloframework.org/docs/palo-azure-copilot-pilot.html

Two-minute report, narrated with my own voice:

https://youtu.be/cfkms-cWp-I

Disclosure: I built PALO. This is a private synthetic-data pilot, without a Marketplace listing or Microsoft certification. AI assisted the drafting and technical review; claims were checked against retained pilot records. The post requests engineering feedback rather than announcing production readiness.

2 Replies

  • 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.

    • sev7en's avatar
      sev7en
      Brass 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?