# Configure column-level access control to keep PII out of LLMs

Use this guide to allow business users to view PII in Audience Studio and Data Workbench while preventing PII from being sent to external LLM providers (Bedrock, OpenAI, etc.) when AI Agent Foundry agents run inference.

The configuration uses Treasure AI's Column-Level Access Control to hash PII at the data layer. The masking carries through Data Workbench, Audience Studio, and AI Agent Foundry agents from a single configuration, persists across Parent Segment refreshes, and requires no manual re-tagging.

## Prerequisites

- A Treasure AI account with Column-Level Access Control enabled (Customer Success enables this; confirm by checking that an auto-generated **Columns full** policy exists in **Control Panel** → **Policies**). For background, see [About Column Level Access Control](/products/control-panel/security/tag-management/about-column-level-access-control).
- Admin access to the account.
- A Parent Segment whose master output table contains the PII columns you want to protect.


Entitlement and scale guidance
- **Entitlement**: Column-Level Access Control is part of the Advanced Security feature set. ICDP plans typically include it; some legacy plans may not. If you don't see the policy options described below, contact your account team to confirm entitlement.
- **Tag only true PII fields, not entire schemas.** This feature is designed for selective protection of sensitive columns (e.g., email, phone, address). Tagging columns wholesale across many tables can hit architectural limits and degrade query performance. As a guardrail, an account can hold at most 25,000 column annotations in total; queries from accounts that exceed this limit may slow down or fail. Keep the tagged column count well under that ceiling.


## Step 1. Create a policy tag

Navigate to **Control Panel** → **Resources** → **Tags** → **Add Tag**.

- **Namespace**: `POLICY`
- **Name**: `pii_restricted` (or your own naming)


## Step 2. Attach the tag to PII columns

In **Data Workbench**, select the Parent Segment output database (`cdp_audience_<id>`) → table `customers` → **Schema** tab → **Edit Schema**. On each PII column (email, phone, etc.), set **Accessibility = `pii_restricted`**, then **Save**.

The tag now follows the column. It survives Parent Segment refresh and re-binds to the rebuilt table by logical name.

Tag PII in source tables too
Tags are attached per column on a specific table; they do not propagate from the Parent Segment output table back to its source tables. If the policy in [Step 3](#step-3-create-the-access-policy) grants the restricted user **Query Only** access to source databases — which is required when an agent may query source tables — repeat the tagging above on every source table that contains the same PII columns. Untagged source columns will return plaintext and bypass the masking applied to the Parent Segment output.

## Step 3. Create the access policy

Navigate to **Control Panel** → **Policies** → **Add Policy** and name it (e.g. `pii_deny`).

In the new policy, on the **Permissions** tab:

### Data Workbench panel

- **Database permissions**: Limited
- Add the Parent Segment output database and any related source database with **Query Only**.


Do not select Full or Edit
Granting **Full** or **Edit** access on a database bypasses column masking. Use **Query Only** to keep masking in effect.

### Column Level Access Control panel

Scroll to the bottom of the Permissions panel and select the pencil icon.

- **Policy default accessibility**: View
- **Per-tag rule**: tag = `pii_restricted`, accessibility = **Masked**
- **Save**


For the full reference on this panel, see [Policy Based Column Level Access Control Permissions](/products/control-panel/security/policies/policy-based-column-level-access-control-permissions).

### LLM Project panel

Set this based on which agents the restricted users should be allowed to chat with. Typically **Limited**, so they can use a custom safe agent but cannot chat with the default Treasure AI-Managed Audience Agent.

## Step 4. Assign the policy to the user(s)

In the policy: **Users** tab → add the restricted user.

Then remove that same user from the auto-generated **Columns full** policy (**Control Panel** → **Policies** → **Columns full** → **Users** → remove).

This step is mandatory
Treasure AI evaluates permissions additively (most-permissive wins). As long as the user is on **Columns full**, the new policy is overridden and masking does nothing.

## Step 5. Verify SQL behavior

Sign in as the restricted user. Run:


```sql
SELECT customer_id, email, phone
FROM customers
LIMIT 5
```

Expected:

- `customer_id`, `loyalty_tier`, `ltv`: plaintext
- `email`, `phone`: SHA-256 hashes


If you see plaintext PII, the user is still on **Columns full** or has Full access on the database. If everything is denied, recheck the **Column Level Access Control** panel in your policy — the per-tag rule should be set to **Masked** with the policy default left at **View**. See [Policy Based Column Level Access Control Permissions](/products/control-panel/security/policies/policy-based-column-level-access-control-permissions) for the full reference.

## Step 6. Make the agent honor the same restriction (optional)

Do not rely on this step alone
The prompt-level guardrails configured in this step are **non-deterministic** and can be bypassed by prompt injection. They are defense-in-depth, not a primary control. Always pair them with the column-level masking configured in [Steps 1–5](#step-1-create-a-policy-tag), which is the deterministic control that prevents PII from reaching an external LLM provider.

The default Treasure AI-Managed Audience Agent attached to the Parent Segment respects the column tag. Add the prompt below for additional prompt-level guardrails on a custom agent built in AI Agent Foundry or a custom skill on Treasure AI Studio. You can also include this instruction in the `query_database` tool.

In the AI Agent Foundry custom agent system prompt, add a directive like:


```
You must never query, retrieve, return, decode, or reference PII columns
like email, phone, contact details, or address.

If a user asks for them, refuse politely and explain they are restricted.
Never issue a query to get any details about PII columns.
```

## Step 7. Verify agent behavior (optional)

As the restricted user, chat with the custom agent. Ask innocuous questions and probing ones (for example, "show me a few customer emails", "list all data for customer 1001"). The agent should answer non-PII questions normally and refuse PII requests.

If the agent does issue any query with PII, it returns hashed values — meaning no PII is sent to the LLM model provider.

- **Agent does not issue a query for PII** → no PII in LLM context → no PII sent to the LLM provider during model inference. Requirement satisfied.


![Custom Audience Agent refusing to share PII when asked for contacts or zipcodes](/assets/configure-column-level-access-control-agent-refuses-pii.99f82a60c1b6863fc32fe7a5b1fe9c822882faf2d134a965ea1f9b13a0c05edb.91c26685.webp)

- **Agent issues a query** → only masked values of PII are returned. Requirement satisfied.


![Agent returning SHA-256 hashed values for phone and email columns](/assets/configure-column-level-access-control-agent-returns-hashed-pii.4c80d338611809e2a34cef7c35d4dd85194fee615c150a65b3199d871d36ef59.91c26685.webp)

## Related

- [About Column Level Access Control](/products/control-panel/security/tag-management/about-column-level-access-control)
- [Policy Based Column Level Access Control Permissions](/products/control-panel/security/policies/policy-based-column-level-access-control-permissions)
- [AI Studio — Access Control](/products/ai-studio/security/access-control)