Rightshold™ Sign up

Answers · agent safety

How do I show a human the actual change (diff, target, amount) before they approve an AI agent's action, instead of the agent's summary?

Last updated

TL;DR: Build the approval screen from the exact tool call that will run, not from text the model wrote about it. The model's summary ('updating the config', 'sending the refund') is a claim; the tool name and arguments are the action. Render those arguments yourself, in a fixed layout: for a file change, a diff of the current file against the proposed one; for a message, the real recipients, channel and full body; for money, the payee, amount with currency and decimals, and network; for an API or database write, the resolved target (full URL, account, table, record ids) and the fields that change, with before and after values. Then bind the yes to what was shown: hash the canonical arguments, store the hash with the approval, and check it again right before execution, so an edited call needs a new approval. The MCP specification says clients SHOULD show tool inputs to the user before calling the server and prompt for confirmation on sensitive operations, and the OpenAI Agents SDK gives your code the tool name and arguments of each pending call to render. Treat those arguments as untrusted display content: escape them, show hidden characters, and never let a description or summary field decide what the approver sees.

What should I check, step by step?

1. Render from the pending tool call: the tool name and the parsed arguments your runtime will execute (OpenAI Agents SDK interruptions expose name and arguments; a LangGraph interrupt() payload is whatever you put in it, so put the arguments there, not a summary).

  1. Show the model's explanation, if at all, in a separate box labelled as the agent's description, below the facts. If the two disagree, the facts win and the approver should be told.
  2. File edits: show a unified diff against the file as it is on disk now, with the full path, and flag new files, deletions, permission changes and files outside the project. Line counts alone ('12 changes') are not a review.
  3. Messages and posts: show every recipient (to, cc, bcc, channel, thread), the sender identity, the full body and attachments, not a preview.
  4. Payments and spend: payee or payTo address, amount with currency and decimals, network (mainnet or testnet), what is bought, and whether the figure is a ceiling or exact.
  5. API, database and infrastructure writes: the resolved target (full URL with host, account or project, environment, table and record ids), the operation, and before/after values for each changed field. For bulk actions, the count plus a sample, and a way to see all of them.
  6. Make hidden things visible: escape HTML, show invisible and look-alike characters (zero-width, bidi controls, homoglyph domains), and expand shortened URLs and templated variables to the values that will be sent.
  7. Bind the approval to the facts: hash the canonical JSON of the tool name plus arguments at display time, store it with the decision, and compare right before execution. Any change (another retry, an edited amount, a new recipient) means a new approval.
  8. Expire and single-use approvals, keep approval state on your server, and record who approved, what they saw (or its hash) and when.

Why the summary is the wrong thing to approve

The summary is written by the same model whose action is being checked. If the model was misled by injected text in a ticket, web page or tool result, or simply got the target wrong, its summary can be confidently wrong too, and it will usually describe what it meant to do rather than what the arguments do.

What the specs and SDKs say

MCP (2026-07-28, tools, security considerations): clients SHOULD prompt for user confirmation on sensitive operations and show tool inputs to the user before calling the server, to avoid malicious or accidental data exfiltration. The same page says a human SHOULD be in the loop with the ability to deny tool invocations.

Common ways the shown change and the run change drift apart

The model re-plans after approval and calls the tool again with different arguments. Fix: the approval carries a hash of the arguments, and the executor refuses a call whose hash isn't approved.

How do I ask Rightshold about this (free, no key)?

Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code, then ask: “Before you run this tool call, request my approval with the exact tool name and arguments as the action, and wait for my yes or no.”

One-click setup

{
  "tool": "request_human_approval",
  "arguments": {
    "action": {
      "tool": "<tool name>",
      "arguments": "<the exact arguments object you will send>"
    },
    "summary": "<one line, no personal data>",
    "expires_in_minutes": 30
  }
}

Rightshold records and signs approval requests and decisions and checks that an action matches its approved hash. It does not render diffs, run your tools or see your data. Not legal advice.

What are the sources?

Related

Not legal advice. JSON · Markdown · All answers

Get a free API key in one call

No card and no email needed. 100 free credits; the license and policy checks stay free without a key.

curl -s -X POST https://www.rightshold.com/v1/accounts/signup -H "Content-Type: application/json" -d '{"accept_terms":true}'
export RIGHTSHOLD_API_KEY=rs_...   # the api_key from the reply (shown once)
curl -s https://www.rightshold.com/v1/licenses/check -H "Authorization: Bearer $RIGHTSHOLD_API_KEY" \
  -H "Content-Type: application/json" -d '{"license":"MIT","intended_use":{"commercial_use":true}}'