Skip to content
← BlogDeveloperAnalysis

What should an AI agent be allowed to read and write in your CRM data?

AI agents need different guardrails for CRM data than for sending. A practical framework for what to let one read, write, bulk-edit, or never touch.

By Gabriel Lara, Developer Relations, Norbelys

Founder-reviewed ·How we research and correct articles

Most of the writing on AI agents and cold email focuses on the moment that feels the most dangerous: the send. The guardrails an AI operator needs before it touches your sending domain covers that question well — rate limits, approval gates, and the evidence an agent should show before a campaign reaches a real inbox. That’s the right frame for send authority. It is not, on its own, the right frame for a question that comes up just as often and gets far less attention: what should an agent be allowed to do to the contact data sitting in your CRM, independent of whether it ever touches the send door at all?

Those are genuinely different risks. A rate limit protects a mailbox’s reputation. It does nothing to stop an agent from quietly renaming half your segments, overwriting a field an integration depends on, or reading private notes it had no reason to see. Data access needs its own framework, and that’s what this post is.

The shape of the data an agent is actually touching

A Norbelys contact — a person — is a normal-looking record: givenName, familyName, email, telephone, custom fields keyed by code (additionalProperty on the wire, per the Schema.org field mapping), and a privateNotes field for the freeform context a rep jots down after a call. Around that record sit two different collection concepts that matter a lot for an access framework: groups, which are static lists someone builds by hand, and segments, which are saved condition sets — “opened campaign A and clicked in B,” say — that can be configured to auto-enroll anyone who newly qualifies into a live program. That distinction is going to matter in a minute.

One detail in how the platform itself stores this data is worth noticing before writing any rule about agent access: privateNotes and custom fields are deliberately excluded from the paginated list projection and only appear on a full single-record read. The people-list endpoint that powers a table of a thousand contacts doesn’t carry notes along for the ride — you have to ask for one record specifically to see them. The platform’s own engineers already decided that field deserved a narrower default than “comes back with everything else.” That’s a reasonable precedent to extend to an agent’s access, not just a database optimization.

Read access: default to list-shaped, justify anything deeper

Letting an agent read contact lists, segment membership, group rosters, and timelines is close to zero-risk on its own — it’s the same information a human on the team could pull up in the dashboard, and it’s what makes an agent useful for triage, summarization, and “which of these 40 replies actually need a human” work in the first place.

Reading privateNotes and custom fields on a specific record is a different tier, not because the mechanism is any different, but because that’s where the sensitive stuff tends to live — a sales rep’s read on a prospect’s budget, an internal flag about a difficult account, a compliance note about why someone was manually excluded. An agent that’s summarizing an account before a call has a real reason to read that note. An agent that’s bulk- scanning every contact’s private notes because it happened to have read access to the field does not, and the difference between those two isn’t visible from the API surface — it’s visible from the task the agent was actually given. Scope the task, and let that scope the calls, rather than handing out blanket field-level read access and trusting the agent to self-restrict.

Write access: field edits are reviewable, membership edits are not

A single field update — correcting a job title, adding a custom field value from an enrichment lookup, tagging a contact — is a small, attributable, easily-reversed action. If an agent gets one wrong, a human looking at the record’s updatedAt and the surrounding activity can see exactly what changed and undo it. This is the same reasoning that makes DELETE a soft archive rather than a hard delete everywhere in the API: reversible-by- default writes are safe to hand out fairly liberally, because a mistake costs a correction, not an incident.

Group and segment membership writes are where the framework needs to get more careful, and the reason is specific to how segments work here, not a generic “bulk operations are scary” instinct:

That’s the concrete reason data-access guardrails and send-authority guardrails have to be evaluated separately rather than treated as one category of “AI agent risk.” An agent can be perfectly rate-limited and gated on every direct send it’s capable of proposing, and still cause an unapproved campaign to reach real people, purely through a CRM write that was never framed as a sending action.

The practical rule: membership writes into anything a segment or program depends on need the same kind of “did a human actually approve this” checkpoint as a launch, even though the API call itself is an ordinary POST on a relationship, not a send. Membership writes into a plain static group with nothing watching it are much closer to the field-edit tier — useful, low-risk, fine to automate.

Bulk writes: the job pattern is a feature, use it as a checkpoint

Large-scale contact writes — an enrichment pass over ten thousand records, a CSV re-import — go through the job pattern rather than a loop of individual calls. That’s convenient for an access framework, because a job is a resource you can inspect before it finishes: you can see total, done, failed, and a report, all before the last record is written. An agent kicking off a bulk job is a fundamentally more reviewable action than an agent silently looping ten thousand PATCH calls one at a time — the same volume of change, but one of the two shapes gives a human a natural moment to watch it land and cancel course if the early results look wrong. Prefer giving an agent job-shaped bulk access over letting it script its own loop, even when the two would technically produce the same end state.

The one hard line: erasure is never agent-autonomous

people:erase is the one operation in the entire API that’s genuinely irreversible — PII is scrubbed from the row, not archived, and it’s the correct response to a real data subject request, not a cleanup action. That combination — irreversible, legally consequential, rarely urgent — is exactly the profile of decision that should never be left to an agent’s judgment about whether “this looks like a valid erasure request.” A human approves the erasure; the agent, at most, drafts the request and cites its evidence for why the contact qualifies. This is the CRM-data equivalent of the send button in the guardrails post: not a check on capability, a check on authority.

Putting the tiers together

Read broadly, write narrowly, treat anything that touches segment or group membership as if it might trigger a send even when it technically doesn’t, prefer job-shaped bulk operations you can watch land, and keep erasure as a human-only action with an audit trail behind it. None of that requires inventing new API surface — every tier maps cleanly onto the resource, relationship, and job patterns the API already uses. What it requires is treating “what can this agent touch in the CRM” as its own deliberate decision, made separately from “what can this agent send” — because in a system where data writes can trigger sends on their own, only asking the sending question leaves half the risk unexamined.