Security

ContextWorks assembles every payload as the calling user. Enrichment sources are the one deliberate exception.

How it works

Every record query runs in user mode, so Salesforce enforces access on the query itself.

CheckEffect
Object permissionsNo read access, no rows
Field-level securityA field the user can’t see never reaches the payload
Record sharingPrivate records never appear, including inside related lists and query results

ContextWorks never fetches a value and then hides it. Two users calling the same tool on the same record get different payloads, with no per-user configuration.

What a stripped field looks like

Nothing. The field is simply absent from the payload, and the agent answers from thinner context.

To see which fields dropped out, open Quality for FLS coverage % — the share of designed fields this caller could see — and Issues, which names stripped fields under fls_strip.

A field can also be absent because you never curated it, or because it sits below the requested level. Only permission strips appear under fls_strip.

Curate for relevance, secure with field-level security

Removing a field from an entity doesn’t protect it. A user with object access still reaches that field through a report, the API, or another entity. Use field-level security for access control, and curation for relevance.

Curating in a sensitive field is safe: a user without access still won’t receive it.

Which catalog a user gets

Discovering a domain and reading records through it are two different questions. Sharing a domain answers the first: a user reads only the domains shared to them. A scoped tool is the exception. It names its domain in Apex, so whoever can run the class reads through it.

Neither one widens data access. Two people holding the same domain still get different records, and a scoped tool still queries as its caller. → Domain access

The permission sets

Permission setGrants
ContextWorks AdminWrite access to the configuration objects, and read on every captured debug log and every write record
ContextWorks Domain ManagerConfiguration rights over entities homed in specific domains. Does nothing unless domain management is on
ContextWorks UserClass access to the eight runtime agent actions, plus read on the configuration objects and the domain object, so ContextWorks can resolve what a caller may use. What Agentforce and MCP callers need

ContextWorks User and ContextWorks Domain Manager grant nothing on your business data: ContextWorks assembles every payload as the caller, from what the caller can already read. ContextWorks Admin is different. Admins read debug logs and write records, which hold record data, so treat admins as trusted with it.

Give every ContextWorks Admin the View All Data system permission as well. The permission set doesn’t include it; grant it through the admin’s profile or a permission set of your own.

Assign ContextWorks User to whoever the call runs as — a Flow or an Apex job included. Salesforce checks Apex class access when an agent action or MCP tool runs, and every configuration read the engine makes runs in user mode, so a caller without the permission set resolves no entity and no domain. → Install and set up

Enrichment sources: the one exception

Enrichment sources run code: Apex, an invocable action, or a flow. The engine handles what they return two ways.

  • The engine re-checks record results. It keeps only the IDs, discards every field value the source returned, and re-queries them as the calling user to render the target entity’s list columns. A record or field the caller can’t see never appears, whatever the source saw. The refetch drops computed per-row values, so return those as scalars instead.

  • The engine trusts scalar values as returned. A constructed number isn’t a field, so the engine can’t re-check it. Whoever writes a provider owns what its scalar values expose: query as the calling user (WITH USER_MODE) so a total can’t leak to a caller who couldn’t have computed it. See the provider SPI reference.

WARNING

Data 360 DMO reads are not governed by CRM sharing — what such a provider returns is what every caller sees. Fine for aggregate engagement data; decide deliberately.

Debug logging

Time-boxed payload logging stores the exact text a caller received, record data included. ContextWorks Admins read every captured payload. A Domain Manager reads only the loads they ran. Salesforce record sharing enforces this, so the Logs page, a report and the API all show the same rows. Logging expires by design: it’s a debugging tool, not an audit trail.

Error handling

If an enrichment source fails, the engine drops that one element, delivers the rest, and records an element_failure issue on the Issues page. The agent gets a payload without that section and never sees the exception text.

What’s next