Best Practices for Building LLM Apps

Chapter 4 · Practice 3 of 5

Require human approval for irreversible or high-impact actions

From Tools, agents and least privilege

Why it matters

Some actions cannot be undone. These should pause for a person to confirm:

  • sending messages
  • moving money
  • deleting data
  • changing permissions
  • publishing content

OWASP's prompt injection cheat sheet adds a key detail: the approval must cover the specific operation, target and arguments, and the component that executes the action must check it.

Show the user exactly what will happen, such as the recipient and the full message, not a vague "Allow agent to send email?". Then bind the approval to that exact payload, so the model cannot change it after the user clicks Approve.

Example

TypeScript
const pending = await savePendingAction({ tool: 'send_email', args, userId });
// Later, after the user clicks Approve on a screen showing args:
const action = await loadPendingAction(pending.id, userId);
if (!action || hash(action.args) !== approvedHash) throw new Error('approval mismatch');
await sendEmail(action.args);