PRACTICAL
INTELLIGENCE.
← All guides

ORIGINAL GUIDE / Agents & automation

Design an automation with a clear approval step

Separate a proposed action from permission to execute it, and design rejection, expiry, retry and audit paths before connecting an agent.

Practical Intelligence · Published · Illustrative examples, not customer performance claims

Related research signals ↗

Drawing an approval button is easy. Building a workflow that respects an approval requires a clear contract between the proposal, the reviewer and the executor. Start with an action you can describe completely, such as drafting a support reply or proposing how to route an incoming request.

1. Show the exact proposed action

The review screen should state the destination, the fields or message to be sent, the reason and the source information used. Give the proposal a unique identifier and a state: proposed, approved, rejected, expired or executed. Changes to its important fields should invalidate the previous approval.

Define who may approve, how long an approval is valid, and what happens if the underlying source changes. A reviewer should not approve a vague instruction such as “do the appropriate thing” when the executor is capable of making several consequential changes.

2. Enforce permission outside the model

The execution layer should check the approved proposal, permissions, destination and current limits itself. Text generated by a model is not proof that approval exists. Give the model only the access required to prepare the proposal.

The OWASP prompt-injection guidance describes how external content can influence a model and recommends measures such as least privilege and validation. Retrieved text and incoming messages should be treated as data, rather than as authorization to expand the workflow.

Worked example: routing a support request

In this illustrative workflow, a message asks for a billing correction. The assistant proposes routing it to Billing with the message reference and a short summary. A reviewer can change the destination or reject the proposal. Approval applies to that routing operation only; it does not authorize a refund, an account edit or a response containing confidential information.

3. Decide what a retry means

Use a stable operation identifier so retrying the same accepted action does not create a second ticket or send a duplicate reply. After a network timeout, check whether the destination already accepted the operation before trying again. A timeout is an unknown outcome, not proof that nothing happened.

Keep rejection and expiry visible. An expired proposal should return to review if it is still useful, rather than executing automatically. Provide an operator with a way to inspect uncertain outcomes and pause new proposals while resolving them.

4. Test the awkward paths first

Record who approved, what was approved, the execution identifier and the observed outcome. Avoid placing secrets or unnecessary personal data in the audit record. Measure rejected and uncertain cases alongside successful ones.

A small next step

Build the state transitions using a synthetic request and a fake destination before connecting a model. If that version cannot handle rejection and retries predictably, adding a stronger model will not repair the action contract.