Governing AI write-access to your CRM: what to allow, and how to prove what it did

HubSpot restores CRM changes for 14 days, and property restrictions do not apply to API writes. The controls to agree before an agent writes to a live record.

John Kelleher
John Kelleher

The decision has already been made somewhere above you. An AI agent is going to touch the CRM, and you are the person who has to say what it may touch, and the person whose name will be on the incident note if it goes wrong.

That is a different question from whether it can be done. It can. HubSpot's remote MCP server has been generally available since 13 Apr 2026, it carries write access, and the routes for connecting an OpenAI agent to HubSpot are well documented on both sides. What nobody documents is the boundary: which writes you should permit, what you will be able to reconstruct afterwards, and what you can undo.

This is the engineering half of the question, not the legal half. Your existing data-protection obligations do not change because an agent is doing the typing, and that part belongs to whoever owns it in your business. What follows is what to configure, and what to insist on before anyone builds.

Read access is a disclosure question. Write access propagates

A bad read sits in a chat window. Someone sees data they should not have seen, which is a serious problem with a known shape, and it stops there.

A bad write does not stop. The CRM is not a filing cabinet, it is the input to everything downstream. A changed deal stage moves the forecast, may fire a workflow, may reassign an owner, may start a sequence that emails a customer, and may show up in the commission calculation at the end of the month. By the time anyone notices the field is wrong, four other systems have acted on it as though it were right.

So this is not really about protecting data from being seen. It is about protecting every process that trusts the data.

What actually goes wrong, and it is rarely the model being wrong

Five failures account for most of it, and each has a design answer.

It writes to the wrong record. Two companies with similar names, or a contact who exists three times because sales, marketing and support each created one. A person hesitates. An agent picks. The duplicate it picks is often the older, thinner record, which is frequently the one carrying the routing rules and the subscription preferences. The integration patterns behind this, including retries and reconciliation, are in OpenAI API patterns for CRM work.

It writes a sentence into a field that something parses. Ask a model for a close date and it may return "end of the quarter". Ask for a lifecycle stage and it may return "probably a marketing qualified lead". Both are reasonable English and both break whatever reads that field next.

It overwrites a human's correction, and buries the evidence. HubSpot stores a capped number of revisions per property, up to 45 for contact properties and up to 20 for company, deal, ticket and custom object properties, and that cap counts API changes exactly as it counts changes made in the interface. An agent rewriting the same property on a schedule will chew through those revisions and evict the human-set value that preceded it. The history you would have used to establish what the field said before is gone.

It fires an automation aimed at a customer. HubSpot's enrolment triggers filter on what a record's values are, not on who or what set them, so a value written by an agent enrols the record exactly as a human's edit would. If automation needs to ignore agent-driven changes, that has to be engineered: have the agent set a marker property in the same write and add it as an exclusion filter on the workflow. Nothing does it for you.

It half-finishes. A multi-object update creates the deal, associates the company, then fails on the line items. No visible error, a confident summary in prose, and a deal in your pipeline with no value on it. People discover this one last, because nothing alerted.

None of these is the model behaving badly. In every case it did what it was asked. Nobody had defined what it was allowed to do.

The controls, in the order you would actually apply them

1. Write the boundary down before anyone opens an editor. Which objects, which properties, read or write, and who agreed. One page. Without it, the boundary is whatever the person building it assumed on the day.

2. Read-only until a pilot earns the upgrade, and define the pilot. "We'll try it and see" is not a pilot. A pilot has one named workflow, a fixed volume, a fixed end date, a human reviewing every write, and a pass rate committed to in advance. Most of the early value is reading plus appending a note, and a note is cheap to delete. A deal stage is not.

3. Do not lean on the CRM's own property permissions. This is the trap. HubSpot Enterprise lets a Super Admin restrict view and edit access on a property, so it is tempting to assume a restricted field is protected from an agent connected as a restricted user. It is not. HubSpot states plainly that all users, regardless of access, can set or edit restricted properties via its API, and that the feature is "not recommended" as a security measure. Several of the most consequential properties cannot be restricted at all, including contact email and name, company domain, deal pipeline and stage, and ticket status. Property restriction is tidiness in the interface, not a boundary for anything writing through the API.

4. Put the boundary in code instead. An explicit allow-list of writable properties, checked before the call is made, not described in a prompt and hoped for. Prompts are guidance. Code is a boundary.

5. Enforce the shape of the value, not just the intent. Structured Outputs holds a model's answer to a JSON schema rather than to a request for valid JSON, so the currency field gets a number or the write is rejected. Reject, do not coerce. A coerced value is a wrong value that has stopped looking wrong.

6. Require approval on consequential writes, and define "consequential" narrowly. Money, stage, ownership, and anything a customer will see. OpenAI's Responses API requires approval on MCP tool calls by default, allowed_tools limits which tools the model can even see, and the Agents SDK has human-in-the-loop and guardrails built in. The real risk is not missing approval, it is approval fatigue: route everything to a human and they will soon click approve without reading, which is worse than no approval because it manufactures a signature.

7. Give each agent its own credentials. Not a shared integration user, not a departing employee's account, not the founder's login. This is the control that makes the next two sections possible, and the one most often skipped because reusing an existing connection is quicker on the day.

8. Cap volume yourself. Maximum records per run, maximum writes per record per day, and a stop one person can pull in a single action without a deployment. The platform's rate limits protect the platform, not you.

Where each control can live is worth being honest about:

ControlCan the CRM enforce it?Where it has to live
Which objects the agent reachesYes, through the scopes on the connectionThe platform
Which properties it may writeNo, API writes bypass property restrictionsYour code
Valid values and data typesPartly, through field typesA schema on the model's output
Approval before a consequential writeNoYour agent framework
Volume and pacePartly, through account rate limitsYour code
Why a change was madeNoYour logs

HubSpot will tell you what changed. Nothing will tell you why

Assume someone asks, six months from now, who moved this deal to closed lost and on what basis. Most deployments cannot answer the second half of that, and a fair number cannot answer the first.

What the platform gives you: property history is available on every HubSpot plan and shows the change source and date for each value, and its export can include which user or tool triggered the update. Account activity logging is thinner than people assume. Starter and Professional accounts can only filter it by Login and Security Activity, the CRM categories are Enterprise, the general view covers the last 30 days, and a Super Admin has to export it. HubSpot does record connector attribution: changes made through its ChatGPT connector are attributed in the audit log to both the user and the connector.

What it does not give you is the reasoning. It knows the property changed and roughly what changed it. It does not know what the agent read, which tool calls it made, what it rejected, or how confident it was.

So log that yourself, at design time rather than after the first incident. For every write: the run identifier, the agent and prompt version, the record and property, the before and after values, the tool calls with their inputs and outputs, the source material the decision rested on, and the approver if there was one. Keep it somewhere that outlives both the CRM's retention window and the vendor's, because both are shorter than the questions.

The test is simple. Print one row of that log and hand it to someone who was not there. If they cannot tell what happened and why, you have monitoring, not an audit trail.

You have 14 days to undo it, and only if you set it up so a restore can find it

This is the number most people have never looked up. HubSpot's restore tool covers CRM changes from the last 14 days, across contacts, companies, deals, tickets, calls, products, leads, marketing events, orders, tasks and custom objects, and it lets you filter by the source of the change: manual edits, imports, workflows, and integrations, the last of which was in beta on 08 Aug 2026. A completed restore stays visible in the history for 90 days.

Two consequences follow.

First, an agent running quietly wrong for a month is partly beyond recovery before anyone opens the tool. Detection speed is the difference between a reversible incident and a data-quality project.

Second, that source filter is why each agent needs its own credentials. If it writes under a shared integration or a person's login, you cannot separate its changes from everyone else's, and your options collapse to a blanket undo that reverses legitimate human work alongside the damage. Attribution is not only about blame. It is what makes a rollback surgical.

Deleted records are a different mechanism again: restorable for up to 90 days, capped at 10,000 records at a time, and HubSpot is clear that some associated data does not come back.

Then there is the category no tool touches. The email that went out. The workflow that fired. The report someone exported into a board meeting. The customer who has already read it.

Which is why two design choices matter more than any recovery plan:

Dry-run mode. For a defined period, have the agent write its intended changes to a log rather than to the record, and diff them against what a competent human would have done. It costs a fortnight and it is the cheapest evidence you will buy about whether the thing is ready.

Reversible writes by default. Prefer appending over overwriting. A note, a task or a new agent-owned property is recoverable in a way a replaced value is not. Where a human-owned field has to change, write the proposal to a shadow property and let a person promote it. An agent's first release should not be able to overwrite a field a human owns.

Sign-off needs a name, not a committee

Someone has to own this personally: the person who can revoke the agent's access in a single action, who reads the log monthly rather than after an incident, and who holds a review date in the diary because the platforms underneath this move constantly.

A working group can advise. It cannot be accountable, and "the AI steering group approved it" is not an answer to anything. If nobody's name is on it, it has not been signed off, and it should not be writing to a live CRM yet.

The decision in front of you

None of the failures worth worrying about are exotic. Access broader than the job needed, because narrowing it was fiddly. Prose in a parsed field, because nobody enforced a schema. Weeks of quiet damage past the restore window, and no way to reconstruct what happened, because logging was going to be added later. Every one is a design decision nobody consciously made, which is the good news: engineering problems have engineering answers, and they are far cheaper to solve before you start.

So the question to put to whoever is building it, in-house or otherwise, is not which model they are using. It is: show me the property allow-list, the approval rule, the log format and the rollback plan. If those four exist, the model choice is a detail you can revisit. If they do not, the model choice is irrelevant.

We are a HubSpot Diamond Solutions Partner and an OpenAI Select Partner, and we build AI implementations on whichever platform fits the workload, including OpenAI. Nothing we recommend earns us a margin on your platform spend, which is why we would rather scope an agent narrowly and have it still running in a year.

A step back, and the other routes available, are in the wider picture of OpenAI for UK businesses.

Request a quote, and bring the boundary question, not the model question.

John Kelleher

John Kelleher

Author
John is the founder and the Chief Executive at SpotDev.

Stay Updated with Our Latest Insights

Get expert HubSpot tips and integration strategies delivered to your inbox.