# Human approval for AI agent actions: the layers

> Human approval for AI agent actions comes in layers: a prompt for the person asking, then the role rules, frozen values and requests an admin decides.

**TL;DR** Claude, ChatGPT and Cursor can ask before a tool runs, but the person who approves is the person who asked. Elaichi adds the decisions an admin makes ahead of time: a restriction takes a write away from a role, frozen parameters narrow a write to its safe version, and access requests let someone with member:manage open a restricted tool for one person. The audit log then records every attempt and how it was approved.

## How do you get human approval for AI agent actions like CRM writes and email?

Human approval for AI agent actions comes in two kinds. The first is a prompt in the AI client, answered by the person who asked. The second is a decision an admin makes ahead of time about which roles may run the write at all. Elaichi handles the second kind, and its audit log records how each call was approved.

A RevOps lead sees the request coming. Reps want Claude to update close dates in Salesforce and to send follow-up email from Gmail. The lead wants a person to sign off before either happens. Security wants the same thing, written down somewhere an auditor can read.

MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves every connected app through one organization endpoint, the single address each client signs in to. Claude, ChatGPT, Cursor, any MCP client, and the Elaichi Agent all use it. The [MCP specification](https://modelcontextprotocol.io/specification/2026-07-28/server/tools) asks for a human in the loop who can deny a tool call. It also says servers must implement proper access controls. Approval needs both halves, and they live in different places.

## What does an approval prompt in Claude, ChatGPT or Cursor check?

It checks with the person in front of the client, at the moment of the call. That is useful, and it is not a second pair of eyes. The approver is the same person who asked for the action.

Each client handles it differently (all checked October 2026):

- **Claude.** Each connector has tool permissions set to Always allow, Needs approval or Blocked, per tool or per group ([Claude Help Center](https://support.claude.com/en/articles/11176164)). On Team and Enterprise plans, owners can restrict a connector's tool actions for the whole company, and members cannot override that.
- **ChatGPT.** For a write, ChatGPT may ask for confirmation, depending on the app's permissions and the context. Some risky actions are refused rather than offered for approval ([OpenAI Help Center](https://help.openai.com/en/articles/12584461-developer-mode-and-mcp-apps-in-chatgpt)).
- **Cursor.** "Cursor asks for approval before using MCP tools by default" ([Cursor docs](https://cursor.com/docs/mcp)). In its Auto-review mode, allowlisted tools run without asking, and Enterprise admins can limit which tools may run automatically.

There is one catch with Elaichi behind any of them. In Elaichi, connected tools are never listed one by one, however few there are. The model finds a tool with `search_tools` and runs it with `execute_tool`. A client permission therefore names `execute_tool`, so one setting covers a Salesforce read and a Gmail send alike. The real tool name sits inside the call's arguments.

A client prompt suits a careful person double-checking their own request. It is not a second person's decision on that call.

## Does the Elaichi Agent ask before it writes?

Yes. In the Elaichi Agent, a write stops at an approval card before it runs. The card offers Deny, Allow once and Always allow. The person can also edit the arguments first, and the button then reads "Save & allow once".

Deletes get stricter treatment. Always allow is offered for writes only, so a delete asks every time. Always allow is remembered per person and per operation.

Calls from Claude, ChatGPT or Cursor take a different route. Over MCP, Elaichi cannot put an approval step in the client's own window. So the approval is the OAuth grant (the permission a person gives a client at sign-in). On Elaichi's consent screen, the person ticks what the client may do. "Create and change data" covers writes, and "Delete data and remove access" is never ticked in advance. A client signed in without the write box cannot write.

Both routes still ask the person who started the request. The layers below are the ones an admin holds.

## How do you take a write away from a role?

Write a restriction. A restriction decides which connectors and which individual tools a target may reach. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything. Restrict the write on the Sales role, and no rep's client is offered it again.

For a sales team, the rule names four tools. `update_a_salesforce_opportunity_by_id` changes close dates, stages and amounts. `create_a_gmail_message` sends a message straight away, and `gmail_drafts_send` sends a saved draft. `create_a_gmail_batch` groups Gmail requests, including sends, into one call. Reads stay, and so does `create_a_gmail_draft`.

That is the answer to read but not delete or send. Restrict the send and delete tools by name, and keep the reads. A restricted tool is withheld before search, so the model never sees it. It looks exactly like a tool the connector never had. Within the winning layer, blocks always beat allows.

Here, the draft is where the human approval happens. The agent writes the email into Gmail. The rep reads it there and presses send. While the send tools are restricted, the agent cannot send. It can only save a draft. No setting in a client can skip that step.

This follows [OWASP's guidance on excessive agency](https://genai.owasp.org/llmrisk/llm062025-excessive-agency/). It advises putting authorization in the downstream system, not in the model's judgment. Its mailbox example makes the same cut: read, do not send. A saved restriction reaches every surface within about two minutes. [Restricting one tool or the whole app](/blog/per-tool-vs-per-app-restrictions/) covers when to name tools and when to name the connector.

## Can you narrow a write instead of removing it?

Yes, with frozen parameters. A frozen parameter is a value an admin fixes on one tool inside a toolbox, a saved set of tools paired with connected accounts. Elaichi removes the field from what the model sees. It then writes the frozen value over the call's arguments, so sending the field anyway changes nothing.

Take a support team that hands leads to sales and holds no Salesforce login. RevOps connects its own Salesforce account and keeps that connection unshared. It pins `create_a_salesforce_task` into a toolbox and freezes the owner field to the deal desk's Salesforce user, using the field name from the tool's schema. It then shares the toolbox with the support team at `use`. Every task the support team's agent creates lands with the deal desk. The write itself becomes the request for a person to look.

A template carries the same tool list, with renames, defaults and frozen values, and no account. In Elaichi, a freeze binds only calls made through its toolbox entry, so share the toolbox with the people it governs, not the connection itself. A rep with their own Salesforce connection reaches the same tool unfrozen. [Locking a tool argument](/blog/frozen-parameters-wire-transfer-receiver/) works the payment version through.

## What happens when someone needs a restricted tool?

They file an access request, and someone else decides it. Any member can file one with no permission needed. Resolving it needs `member:manage`, which People Admin, Org Admin and Org Owner hold. An admin cannot decide their own request.

Approving a request caused by a restriction opens the tool or connector for that one requester only. A rep restricted through the Sales role gets an exception for that one tool, so the role's other rules still bind them. Like any restriction change, it reaches every surface within about two minutes.

Two limits keep this honest. First, a request caused by a restriction cannot be approved from the Elaichi Agent or an MCP client. Restrictions stay read-only on every AI surface, so a model cannot approve its own access. Second, an approval opens the tool until an admin removes the exception. It is a standing decision, not approval of one call.

## What does the audit log show after the fact?

Every attempt, and how it got past the approval step. The audit log is the record Elaichi keeps of each action. It holds one entry per tool-call attempt, succeeded or failed, naming the person, the client and the account reached.

Each tool call states its approval in plain words:

| Route | What the audit log says |
| --- | --- |
| A read | Didn't need approval because it only read data |
| Elaichi Agent card | Approved by the person, in chat |
| Edited arguments | Edited by the person before it ran |
| Remembered choice | Allowed automatically by an "always allow" choice |
| Claude, ChatGPT or Cursor | Allowed by the access that client was granted |

Elaichi logs argument names and counts, and never argument values. So the log shows that an opportunity update ran, through which account. It does not show the new close date. Give the reviewer an Auditor seat, which is read-only, cannot call tools and costs no license. [What an AI audit log must capture](/blog/what-an-ai-audit-log-must-capture/) covers the full record.

## How does the setup look for a sales team?

Two roles, four restricted tools and one review habit. Each member holds exactly one role, so a role describes a whole job. Custom roles are a Gold feature.

| Role | Read Salesforce | Draft email | Update opportunities | Send email |
| --- | --- | --- | --- | --- |
| Sales (custom) | Yes | Yes | Restricted | Restricted |
| Sales Ops (custom) | Yes | Yes | Yes | Yes |
| A rep with an approved request | Yes | Yes | Opened for them | Restricted |

Set it up in this order:

1. Create both as custom roles carrying Member's permissions, including `tool:execute`.
2. Restrict `update_a_salesforce_opportunity_by_id`, `create_a_gmail_message`, `gmail_drafts_send` and `create_a_gmail_batch` on the Sales role.
3. Have each rep connect [Salesforce](/connectors/salesforce/) and [Gmail](/connectors/gmail/) under their own login. Each rep's own Salesforce permissions then apply to what they reach.
4. Wait about two minutes. Then, as a test rep, search for a restricted tool and confirm it does not come back.
5. Each month, filter the audit log by the Salesforce connection and read the writes.

The same shape answers how to give sales, engineering and HR different AI tool access. Give engineering and HR their own roles and restrict the Salesforce connector for both. The CRM then disappears from their clients. [Designing roles for AI agents](/blog/designing-roles-for-ai-agents/) covers the role chain. For the full Salesforce tool list a sales role should lose, see [the sales team playbook](/blog/sales-team-chatgpt-salesforce-accounts/).

## When is a client prompt enough?

When one team uses one client, and the source app already says no. A Claude Team owner can restrict a connector's tools for the whole company in Claude's own settings. If reps hold a read-only Salesforce profile, the write fails at Salesforce too. A restriction layer on top would add review work and little safety.

The admin layers earn their cost later. That point comes when more than one client reaches more than one app, and a reviewer asks who approved last Tuesday's change. The [MCP control plane overview](/blog/what-is-an-mcp-control-plane/) explains where Elaichi sits. The risks these layers answer are listed in [the MCP security risks guide](/blog/mcp-security-risks/), and [pricing](/pricing/) has the price for your region.

## FAQ

### Can an admin approve AI agent actions before they run?

In Claude, ChatGPT and Cursor, an approval prompt goes to the person using the client, who is usually the person who asked for the action. In Elaichi, an admin decides ahead of time instead. A restriction takes a tool away from a role, and a member who needs it files an access request that someone with the member:manage permission approves or denies. Every call is then recorded in the audit log with how it was approved.

### How do I let an AI agent read the CRM but not send email?

In Elaichi, write a restriction on the role that withholds the send tools, which for Gmail are create_a_gmail_message, gmail_drafts_send and create_a_gmail_batch, and leave the read and draft tools alone. A restricted tool is withheld before search, so the model never sees it. The person then reviews each draft in Gmail and sends it by hand.

### Does a Needs approval setting in Claude work per tool through Elaichi?

Not per connected tool. Elaichi serves connected tools through two tools, search_tools and execute_tool, so a Claude tool permission on execute_tool covers every connected tool at once. Use the client setting as a prompt for the person in the chat, and use an Elaichi restriction on the role to decide which tools that role can reach at all.

### Who can approve an access request in Elaichi?

Anyone whose role holds the member:manage permission, such as a People Admin, Org Admin or Org Owner, and never the person who filed it. Any member can file a request. Approving a request caused by a restriction opens the tool or connector for that requester only. A request caused by a restriction cannot be approved from the Elaichi Agent or an MCP client.

### How do you give sales, engineering and HR different AI tool access?

In Elaichi, give each department its own role and write restrictions for each role. Each member holds exactly one role, so a rule on the Sales role reaches every rep and nobody else. Custom roles are a Gold feature. A role or restriction change reaches every surface within about two minutes.

## Read next

- [Restrict one AI tool or the whole app? Six cases](/blog/per-tool-vs-per-app-restrictions/) — Restrict one AI tool when a role needs part of an app, and block the whole app when it needs none of it. Six cases, and what new tools do to each rule.
- [Lock AI agent tool arguments, like a wire's payee](/blog/frozen-parameters-wire-transfer-receiver/) — Lock AI agent tool arguments with frozen parameters: Elaichi hides the field from the model and writes your value over whatever the call sends.
- [What an AI agent audit log must capture](/blog/what-an-ai-audit-log-must-capture/) — An AI agent audit log must capture who acted, which client called, which account was reached, what was tried and how it ended. Argument values stay out.
