The situation a RevOps lead is actually in
Reps are already asking Claude to summarize an account before a call. Someone has asked why it cannot just update the next step while it is in there. That is a reasonable request. It is also the moment where a CRM gets quietly worse: a model writing into opportunity fields with whatever permissions a shared service account happened to carry.
The question is not whether to let AI agents write to Salesforce. It is whose permissions the write runs under, which tools are reachable at all, who sees the change before it lands, and what the record of it looks like afterwards. Those are four separate controls in Elaichi, set in a specific order:
- Identity binding: which Salesforce account the call executes as
- Reachability: which tools exist for that role at all
- Pre-execution visibility: who sees the write before it runs, if anyone
- Audit record: what gets logged once it does
MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps. Elaichi serves it at one address, POST https://api.elaichi.ai/mcp, and the same address serves every organization. Which organization, person and tools a client reaches comes from the OAuth grant behind its token, not from the URL.
How do AI agents write to Salesforce under each rep's own permissions?
Each rep connects their own Salesforce account, and every call through that connection runs on that account. Each person's own permissions in Salesforce then apply to what the call can do. If the rep cannot change a deal stage, neither can the model acting for them.
The mechanic in Elaichi is that a connection carries the credential, not the caller. Every call through a connection fetches credentials from that one connection row's bound account, whoever is calling. So a connection Maria created with her own Salesforce sign-in acts as Maria. A connection shared with the team acts as whoever owns it, for everybody.
That second behavior is the trap. If one sales ops person connects Salesforce once and shares the connection with the team at use level, every rep's AI writes land as that one person. Every opportunity the AI touches is written by the connection owner's account, not by the rep who prompted it. The owner's permissions are the ones that apply. For per-rep enforcement you need per-rep connections. Two ways to get there:
- Each rep adds their own Salesforce connection under Connections. Their All tools toolbox then holds the Salesforce tools, running on their account.
- You build a template, share it at use, and each rep stamps their own toolbox from it, picking their own Salesforce connection for the Salesforce entries. The stamper is recorded as the delegator on each entry they pin.
Sharing a template at use gives teammates the right to stamp it. It does not create a toolbox for anyone, and it never fills in a connection by itself. The stamp dialog shows one connection picker per connector, each starting at "Skip and add a connection later." That is deliberate. A template share delegates nothing, because a template stores no connection at all.
If the Salesforce side is the part you need to get exactly right, the mechanics post on Salesforce field-level security for AI agents goes deeper than this playbook does.
Why one address for Claude, ChatGPT and Cursor
One endpoint means one place to change the rules, and one place where every call is checked. Claude, ChatGPT, Cursor, Microsoft Copilot, any MCP client, and the Elaichi Agent inside the app all work against the same governed catalog.
Each rep connects their client once and approves their own grant on Elaichi's consent screen. Clients register themselves through OAuth dynamic client registration (RFC 7591), so there is no client ID, secret or header for a rep to look up or paste. Each grant covers exactly one organization, picked on the consent screen. Reaching a second organization takes a new connection.
The practical effect for a RevOps lead: when you change which Salesforce tools the sales role may reach, you change it once. You do not chase the setting into Claude's connector settings, then ChatGPT's plugin settings, then each developer's Cursor config. Client-side settings still exist and still matter, but they are not where your Salesforce rules live.
Setup for each client is written up separately: Connect Elaichi to Claude, connecting ChatGPT, and a Cursor rollout for a whole team.
Two kinds of connector, one set of rules
| Connector type | Who builds/runs the server | Example | Governance applied |
|---|---|---|---|
| Elaichi-authored | Elaichi | Salesforce, Slack, Jira | Full: roles, restrictions, scopes, audit log |
| Native MCP (vendor-run) | The vendor, published once for all orgs | Datadog, Linear | Same as above: Elaichi sits in front for sign-in, access and audit |
| Bring-your-own remote MCP | The org itself (Gold/Black plan, Org Owner or Org Admin only) | Any custom internal MCP server | Same as above: restrictions, scopes and audit apply before the call leaves Elaichi |
That matters here because a sales stack is rarely one vendor. Salesforce sits beside Slack, Jira and whatever the team uses for sequences. All three connector types come through the same /mcp address and the same search and run tools. Restrictions bind them identically. A block rule on the sales role works the same way whether it targets a Salesforce tool or a bring-your-own connector's tool.
The argument for running vendor servers behind one plane rather than one at a time is in vendor MCP servers through Elaichi. A worked example of the vendor-run case, where the vendor builds the server and Elaichi handles sign-in and audit, is the Linear MCP server rollout for an engineering team.
Blocking deletes for the sales role
A restriction on the sales role names the Salesforce delete tools and blocks them. In Elaichi, restriction targets are role or user only; the organization default is the absence of a rule, which means allow everything.
Write it as a block rule, not an allow rule. The two behave differently enough that picking the wrong one is the most common misconfiguration:
| Block rule | Allow rule | |
|---|---|---|
| Matches by | Name or operation (renaming a tool does not evade it) | Name or operation |
| Effect on other tools | No side effect: everything else stays reachable | Flips the entire layer into allowlist mode: every connector and tool not named by any allow rule becomes unreachable for that role, across all connectors |
| Use when | You want to remove one specific capability (e.g., deletes) and leave everything else as-is | You want to restrict a role to a fixed, named set of tools |
| Risk of under-specifying | Low: only the named tool is affected | High: forgetting to name a tool the role legitimately needs silently breaks it |
If you only want to stop deletes, a block rule is the smaller, safer change. The trade-off is this: in Elaichi, a layer with only block rules has no allowlist, so everything it does not block passes it. To hold the role to reads only, you need allow rules naming those read tools, plus allow rules for every other app the role uses. That is a larger surface to maintain correctly. The read-only shape is worked through end to end in the read-only Looker rollout for Claude.
The post on MCP tool allowlist vs blocklist walks through which shape fits which goal.
Three things govern how a block behaves:
- A restricted tool is left out of the tools Elaichi offers a client and cannot be called. Search still names it, flagged restricted, with no schema. A call to a blocked tool by name is refused with a restriction message, not "Unknown tool." The refusal states whether the block comes from the role or the person's own rules, and whether an admin can lift it.
- Restrictions are evaluated for the person calling, not for the connection's owner. A rep whose role blocks a delete cannot reach it through a shared toolbox either.
- A restriction change is not instant. Role, team, restriction and grant changes reach every surface about two minutes.
If a rep genuinely needs a blocked tool, they can file an access request from the client. Only a person in the Elaichi console can approve or deny it, under Governance, then Access requests. The route needs the member:manage permission and makes the admin confirm their identity first. No AI surface can decide a request. Approving creates an access grant that lifts exactly the approved connector or tool for that one person, without editing the role's rules or anyone else's access.
If you are writing restrictions for more than one role at once, the role-by-role ServiceNow rollout shows how the same rule shapes differ between an admin role and a service-desk one.
Holding risky writes for a person
Here is the honest boundary, and it is the one most RevOps leads get wrong when they plan this.
Over MCP, Elaichi has no per-call approval step. The person's OAuth grant is the approval: they chose the scopes on Elaichi's own consent screen for that named client, and every call that passes the scope check runs. There is no Elaichi prompt between the model and the Salesforce write. Any per-call confirmation a rep sees in Claude or ChatGPT is that client's own prompt, set in that client's settings, not Elaichi's. Claude sets connector tool permissions to Always allow, Needs approval or Blocked, per Anthropic's own documentation on connector permissions (support.claude.com, checked October 2026). ChatGPT may show an approval card before a supported app action runs, depending on the app permission setting and the action's context, per OpenAI's documentation on app permissions (help.openai.com, checked October 2026). Both vendor docs are subject to change independent of this post. Verify current behavior against the live article if the exact UI matters for your rollout.
The approval card is a feature of the Elaichi Agent, which runs inside Elaichi. There, a connected tool classified as a write stops at a card with Deny, Always allow and Allow once before it runs, and the person can edit the arguments first. A connected tool that deletes asks every time, and that approval is never remembered. A delete reached through elaichi__toolbox__execute is approved as one write instead, so the "asks every time" rule has that exception.
Plan it this way. For reps working in Claude or ChatGPT, your controls are set beforehand: which scopes the grant holds, which toolboxes it reaches, which tools the role may call, and which arguments are locked on a toolbox entry. For work that genuinely needs somebody to look before it lands, run it through the Elaichi Agent, or through a workflow with an approve step. Human approval for AI agent actions covers the shape of that in more detail.
One more control is set before any call runs: frozen parameters. A toolbox entry can carry argument values that a caller cannot override. Freeze an owner field or a record-type value and the AI cannot change it on calls that run through that entry. The AI can see that the value is frozen, and often what it is; it cannot change it. The freeze only holds on calls through that entry, so a member who can use the connection directly has the same tool without it. Locking AI agent tool arguments covers the pattern and its edges.
What plan tier each control needs
Features referenced above sit on different plans. Here is what gates what:
| Feature | Minimum plan |
|---|---|
| The audit log, with 90 days of history | Personal |
| Per-rep connections for a team of reps | Gold |
| Custom roles | Gold |
| Block and allow restrictions | Gold |
| Bring-your-own remote MCP connector | Gold |
| Elaichi Agent approval cards (Deny / Always allow / Allow once) | Black |
| Workflow with an approve step | Black |
| Forwarding audit logs to an external destination (e.g., Datadog) | Black |
Personal is the free plan, and it is for one person. It holds one member, cannot share a connection, toolbox or template, and cannot write restrictions. So a rollout with a connection per rep and a block rule on deletes starts at Gold. The audit log itself is not plan-gated, and a Personal workspace has the same 90 days of it. Black matters once you want a held-for-review approval step or log retention past 90 days.
How this compares to other ways of controlling AI writes to Salesforce
There are at least two other ways teams currently constrain what an AI agent can do in Salesforce. Each handles the four controls (identity, reachability, visibility, audit) differently:
| Approach | Identity binding | Reachability control | Pre-write visibility | Audit trail |
|---|---|---|---|---|
| Raw OAuth scoping against Salesforce's API directly | Whatever account the OAuth connected app was authorized against | Connected app scopes plus the authorized user's own access | None built in: any gating is custom code you write | None from the integration layer: you build it |
| A generic MCP gateway without per-connector connection binding | Often a single shared service credential per connector | Gateway-level allow/deny lists, if the gateway supports them | Depends entirely on gateway features | Depends entirely on gateway features |
| Elaichi | Per-rep connection bound to that rep's own Salesforce login | Role-based block/allow rules, evaluated per calling person | Elaichi Agent approval cards (Black) or workflow approve step (Black); no per-call gate over raw MCP | Every connected-tool call logged, 90 days retained, exportable |
The honest trade-off: if Salesforce is the only system your agents touch, Salesforce's own permission model is where this belongs, and a separate control plane adds a vendor you do not need. Elaichi's model pays off when reps also need the same enforcement across Slack, Jira or other connectors through the same client. It pays off again when you want one audit log that spans all of them rather than one per vendor. Raw OAuth scoping against the API is the most flexible and the most work: there is no block/allow abstraction, no role model, and no audit log. You build all of it.
Blocking deletes for the sales role: worked example
To make the restriction mechanic concrete rather than described only in prose: a block rule targets the sales role and names each Salesforce tool that deletes.
Name them one by one, or block by the operation the tool performs. In Elaichi's catalog, the Salesforce connector's delete-type tools include delete_a_salesforce_opportunity_by_id, delete_a_salesforce_account_by_id, delete_a_salesforce_record_by_id, salesforce_accounts_batch_delete, salesforce_sobject_collections_bulk_delete and salesforce_records_delete_by_external_id, plus the two merges, salesforce_accounts_merge and salesforce_contacts_merge. A tool the rule does not name stays reachable for the role, so list them all.
With that rule in place:
- A restricted tool is left out of the tools Elaichi offers a client and cannot be called. Search still names it, flagged restricted, with no schema. The rep's Claude session never sees Salesforce tools listed one by one in the first place; it finds them by searching.
- If the model calls delete_a_salesforce_opportunity_by_id by name anyway, Elaichi refuses the call with a restriction message naming the role as the source, before the call reaches Salesforce.
- The refusal writes no audit row. Only calls that pass the scope and restriction check and reach execution are logged.
What the audit log holds after a write
Every connected-tool call that reaches execution writes one row. In Elaichi, one entry for each connected-tool call that reaches execution (a call refused earlier writes none).
"What it touched" is a target: the resource type, an id taken from the one URL path argument that names the object, a title from the response, and the object's own link. No other argument values are recorded, and neither argument names nor an argument count. For a list or search call the row records only the resource type and how many items came back.
The console shows a call from an MCP client as a sentence, naming the client, the person, the action and the connection it ran through. The client's name is shown as verified only for the seven clients Elaichi recognizes by their registered redirect addresses. Anything else shows the name the client registered for itself, flagged as self-reported.
Two limits to plan around. Elaichi keeps 90 days of audit history. For longer, forward it to your own log service: logging destinations come with the Black plan (see table above), and Datadog is the destination that delivers. And a call refused at the MCP scope check writes no row, because that refusal happens before any executor runs. The log is a record of what ran, not of everything attempted.
Anyone can read their own events. Reading the whole organization's needs the audit:view permission, which Org Owner, Org Admin and Auditor hold. Auditor is a free seat, so adding a compliance reviewer does not add a billable seat. What an AI agent audit log must capture sets out what a reviewer will ask for.
When you do not need any of this
If one person runs RevOps, uses Claude alone, and connects Salesforce with their own account, you have per-person enforcement already. Every call runs under their own Salesforce permissions. Claude's own connector tool permissions can set a tool to Always allow, Needs approval or Blocked (see Anthropic's connector documentation, checked October 2026). Adding a control plane buys you nothing until there is a second person, a second client, or a rule you want to hold across both.
The case for Elaichi starts when reps split across Claude and ChatGPT, and when you want deletes blocked for a role rather than hoped against. It also starts when a security reviewer asks for one place that shows which person wrote to which record through which account. Until then, the honest answer is that you can wait. When you don't need an MCP gateway yet argues that case more fully.
If your next step is the read-only version of this rollout, each rep's own Salesforce access in ChatGPT covers it, and the Salesforce MCP access for Claude, per rep playbook does the same for Claude. The catalog is at /connectors/.