> ## Documentation Index
> Fetch the complete documentation index at: https://docs.upsolve.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Governance

> Control what data your agent can reach and what each user can see: schema-level permissions, row-level security, and how much data reaches the AI.

An analytics agent is only safe to put in front of customers if it can never show one of them another's data. Upsolve enforces that in the platform, on every query the agent runs, not in the agent's instructions. A prompt asks the model to behave; these rules don't depend on it.

Governance works at three levels:

| Level | What it controls | Where you set it |
| - | - | - |
| **Schema** | Which tables and columns the agent can reach, and which database schema each tenant reads from | The workspace's **Data Model** page |
| **Rows** | Which rows each user and organization sees in those tables | The **Data Model** page: **Global Data Security** and each table's **Data Security** tab |
| **AI exposure** | Whether the underlying values are shared with the AI model at all | **Workspace settings → Data access** |

Schema and row rules are part of the workspace version: a rule change reaches your users only when you save a version and promote it. **Restrict data from agent** is set for your whole organization by Upsolve, so it doesn't change with workspace versions.

## Control what the agent can see

The tables and columns you select on the [Data Model](https://docs.upsolve.ai/ai-agent-builder/data-models.md) page are an allowlist. Everything else is denied:

* A query that names a table outside the data model is refused.
* A column you deselected can't be read, even by a query that names it.

So the safest way to keep the agent away from a sensitive table or column (salaries, personal details, internal notes) is to leave it out of the data model entirely.

### Give each tenant its own schema

If your database keeps each customer in a schema of its own, a **Schema Rule** points every query at the signed-in user's schema. Each user's queries run against their own tenant's tables, and only those.

![The Schema Rule form with Schema Property set to user.source, and an Example Output line showing every query prefixed with that schema](https://mintcdn.com/upsolve/D97oBA4ne6a4ffrc/images/ai-agent-builder/schema-rule-form.png?fit=max\&auto=format\&n=D97oBA4ne6a4ffrc\&q=85\&s=296e90e14013712f00495ccc69bfe794)

With the schema property `user.schema`, a query on `orders` reads:

```sql theme={null}
SELECT *
FROM "{{user.schema}}"."orders"
```

Schema rules are created like any other global rule; see [Global security rules](#global-security-rules) below.

## Control which rows each user sees

Row-level security (RLS) filters every table by who is asking. For example:

* A user from Acme Corp only sees Acme Corp's data.
* A sales rep only sees their own deals.
* A regional manager sees their region.

![RLS filtering data by user](https://mintcdn.com/upsolve/fLb4mfHG-6nE-S3X/images/ai-agent-builder/rls-overview.png?fit=max\&auto=format\&n=fLb4mfHG-6nE-S3X\&q=85\&s=923d392d206ee087f1d4bcab47b74c87)

It works in three steps:

1. **Give users and organizations properties**, such as `tenant_id` or `region`.
2. **Write rules** that filter tables using those properties.
3. **Every query is filtered** automatically, in chat, on canvases, in rules and in your embed.

### Give users and organizations properties

Properties set on an **organization** apply to every user in it; properties on a **user** apply to that user alone. Set them in your project's **Organizations** and **Users** tabs, or send them when you [sign your users in](https://docs.upsolve.ai/embedding.md) from your product.

```json theme={null}
{
  "tenant_id": "acme-123",
  "region": "US-West"
}
```

![Setting user properties](https://mintcdn.com/upsolve/uChIQDlSatTJLXIe/images/ai-agent-builder/user-properties.png?fit=max\&auto=format\&n=uChIQDlSatTJLXIe\&q=85\&s=d6276fdc67cf30a84916535efe24ea1d)

Rules refer to them with placeholders:

| Placeholder | Replaced with |
| - | - |
| `{{user.propertyName}}` | The user's property value |
| `{{organization.propertyName}}` | The user's organization's property value |

### Global security rules

Most products filter every table the same way, by a tenant or owner column. **Global security rules** let you write that once and apply it to every table it fits.

1. Open the workspace's **Data Model** page and click the **Global Data Security** tab, beside **Tables**.
2. Click **Add Rule** and choose a type:
   * **Column Rule**: filters every table that has a given column, for example `tenant_id`, by a property. Tables without the column are left alone.
   * **Schema Rule**: points queries at a per-tenant schema (above).
3. Configure it. The rule is enabled straight away.

![The Column Rule form filtering the country column on user.country, with the Optional Rule toggle on, a Tables Affected summary, and the generated WHERE clause](https://mintcdn.com/upsolve/D97oBA4ne6a4ffrc/images/ai-agent-builder/column-rule-form.png?fit=max\&auto=format\&n=D97oBA4ne6a4ffrc\&q=85\&s=086adc8d65349967296e2debc666db74)

A column rule on `user_id` gives each matching table a filter like:

```sql theme={null}
SELECT *
FROM "orders"
WHERE "user_id" = '{{user.id}}'
```

How rules combine:

* Several rules are combined with AND.
* Rules apply in priority order, lowest number first.
* A table with a manual rule (below) is skipped.

Applying the rules opens a preview first: the SQL each table will get, how many tables will be filtered, and how many are skipped because they have a manual rule.

![The Apply Global RLS Rules preview, listing the SQL each table will be given, with a count of the tables to be filtered and those skipped for having a manual override](https://mintcdn.com/upsolve/D97oBA4ne6a4ffrc/images/ai-agent-builder/rules-applied-preview.png?fit=max\&auto=format\&n=D97oBA4ne6a4ffrc\&q=85\&s=376faada239c432c59568d6d3262515b)

### Per-table rules

Select a table on the Data Model page and open its **Data Security** tab to see how the global rules apply to it.

![A table's Data Security tab managed by the global rules, its Applied Rules list empty because this table has no column the rules match, above the read-only generated query](https://mintcdn.com/upsolve/D97oBA4ne6a4ffrc/images/ai-agent-builder/table-data-security-global.png?fit=max\&auto=format\&n=D97oBA4ne6a4ffrc\&q=85\&s=8ee907f24ecb30e3d1504e4d3ca39583)

When one table needs its own logic, click **Edit manually** and confirm. The table stops following the global rules, and you write its filter in SQL:

```sql theme={null}
SELECT *
FROM "sales_data"
WHERE "region" = {{user.region}}
AND "company_id" = {{organization.company_id}}
```

![The same tab in manual override mode: an amber manually-edited banner with Reset to global, an editable query, and the user and organization properties available to it](https://mintcdn.com/upsolve/D97oBA4ne6a4ffrc/images/ai-agent-builder/table-data-security-manual.png?fit=max\&auto=format\&n=D97oBA4ne6a4ffrc\&q=85\&s=b81e193a962f1868a57f65d2752f2bef)

Later changes to the global rules don't reach a manual table. **Reset to global** puts it back under them, replacing your SQL with the generated one.

### Test what a user sees

Before you ship a rule, check it with real data:

1. On the Data Model page, pick a project user with **Test RLS as** at the top.
2. Run the test.
3. Review the query with the user's values filled in, and the rows it returned.

![Test RLS Policy run as a supplier manager whose user.country resolves to Canada and Mexico, showing the query sent to the database and the 18 rows it returned](https://mintcdn.com/upsolve/D97oBA4ne6a4ffrc/images/ai-agent-builder/test-rls-results.png?fit=max\&auto=format\&n=D97oBA4ne6a4ffrc\&q=85\&s=926ebc6595f6694dd4316f5fa246aeb1)

You can also chat as that user in the [Playground](https://docs.upsolve.ai/ai-agent-builder/playground.md), where every answer runs under their rules exactly as in their embedded chat. Turn on [CI](https://docs.upsolve.ai/ai-agent-builder/tests.md#ci-check-tests-every-time-a-version-is-saved) to check the draft's row-level security automatically every time a version is saved.

## Control how much data reaches the AI

**Workspace settings → Data access** shows the **Restrict data from agent** setting. When it's on, the agent works without seeing the underlying values in your data, which is stricter but can make its answers less accurate. It's set for your whole organization by Upsolve; contact Upsolve support to change it.

## Best practices

* **Isolate tenants at the organization level.** Filter by an organization property such as `{{organization.tenant_id}}`, so every user in a customer's organization is covered at once.
* **Layer user properties on top** for finer access within a tenant, such as `"owner_id" = {{user.user_id}}`.
* **Test with several users**: from different organizations, with different properties, and with a property missing.
* **Handle missing properties.** A rule can fall back to a default, for example `COALESCE({{user.department}}, 'all')`, or be marked **Optional** so it's skipped when the property isn't set.

## Troubleshooting

**A user sees no data.** Check that the user has the properties the rule uses, that the names match exactly (they're case-sensitive), and that data exists for those values.

**A user sees too much data.** Check that the table has a rule, that the placeholders are written `{{user.prop}}`, and that the version with the rules is saved **and promoted to production**.

## Next steps

> [card] [Data Model](https://docs.upsolve.ai/ai-agent-builder/data-models.md)
>
> Choose the tables and columns the agent can see.

> [card] [Embed Upsolve in your product](https://docs.upsolve.ai/embedding.md)
>
> Sign your users in with the properties your rules use.

> [card] [Playground](https://docs.upsolve.ai/ai-agent-builder/playground.md)
>
> Chat as any user to check what they can see.

> [card] [Tests](https://docs.upsolve.ai/ai-agent-builder/tests.md)
>
> Check row-level security on every saved version.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.