> For the complete documentation index, see [llms.txt](https://documentation.immuta.com/saas/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.immuta.com/saas/agentic-data-access/manage-agents/connecting-the-agent-to-the-data-platform.md).

# Connecting the Agent to the Data Platform

In order for agents registered in Immuta to run queries or act on behalf of users, you must connect the agent to your data platform. The sections below outline dependencies, scripts, and example requests for connecting agents to [Databricks](#databricks) and [Snowflake](#snowflake).

## Databricks

### Dependencies

* Ensure your Immuta customer success representative has enabled the Immuta Agentic Data Access private preview feature.
* You must be using the [group grants version](/saas/configuration/integrations/databricks/databricks-unity-catalog/how-to-guides/granting-to-groups-for-databricks-unity-catalog.md) of the Immuta Databricks integration. If you're unsure of whether or not you're using that version, contact your customer success representative.
* Ensure your **Databricks** customer success representative has enabled the Databricks Exclusive Access private preview feature.
  * The preview introduces a new type of group: exclusive groups. The group's permissions replace the user's permissions when trying to access data or workspace assets authorized to the group. This is critical to the Immuta Agentic Data Access feature.

If you are planning to use the Agentic Data Access feature on a Databricks [connection](/saas/configuration/integrations/data-and-integrations/registering-a-connection/reference-guides/connections-overview.md) that already existed in Immuta prior to the feature being enabled, you must run this script using the same user account that created the Immuta Databricks connection in question:

```sql
--
-- System table used for data-only impersonation for OBO (on-behalf-of) agents
--
-- Primary keys are informational, not enforceable, in Databricks.
-- Uniqueness is enforced by the application layer via MERGE on vended_group.
-- vended_group is the logical primary key: one agent maps to one impersonated user at a time.
CREATE TABLE IF NOT EXISTS `<immuta system catalog>`.`immuta_system`.`__immuta_obo_agent_impersonation` (
    vended_group STRING NOT NULL PRIMARY KEY,
    impersonated_user STRING NOT NULL,
    created_at TIMESTAMP NOT NULL
);

-- Enable default values so the created_at column can have a default
ALTER TABLE `<immuta system catalog>`.`immuta_system`.`__immuta_obo_agent_impersonation` SET TBLPROPERTIES('delta.feature.allowColumnDefaults' = 'supported');
-- Set the default value for created_at to the current time
ALTER TABLE `<immuta system catalog>`.`immuta_system`.`__immuta_obo_agent_impersonation` ALTER COLUMN created_at SET DEFAULT CURRENT_TIMESTAMP();

--
-- Revoke direct access from account users - only the Immuta service account should
-- read and write this table
--
REVOKE SELECT,MODIFY ON TABLE `<immuta system catalog>`.`immuta_system`.`__immuta_obo_agent_impersonation` FROM `account users`;

--
-- Transfer ownership to the Immuta service account
--
ALTER TABLE `<immuta system catalog>`.`immuta_system`.`__immuta_obo_agent_impersonation` OWNER TO `<immuta system account>`;


CREATE OR REPLACE VIEW `<immuta system catalog>`.`immuta_system`.`__immuta_user` AS
  SELECT p.*
  FROM `<immuta system catalog>`.`immuta_system`.`__immuta_profiles` p
  LEFT JOIN `<immuta system catalog>`.`immuta_system`.`__immuta_obo_agent_impersonation` obo
    ON upper(obo.vended_group) = upper(current_user())
  WHERE upper(p.`immuta__userid`) =
    CASE
      -- OBO Agent Impersonation
      WHEN obo.impersonated_user IS NOT NULL THEN upper(obo.impersonated_user)
      -- Default Identity
      ELSE upper(current_user())
    END;
```

### Creating and mapping the agent account in Databricks

* It is best practice for the agent account in Databricks to be a service principal. Follow Databricks' documentation for creating [service principals](https://docs.databricks.com/aws/en/admin/users-groups/manage-service-principals#-add-service-principals-to-your-account).
* Once your service principal is created, [map it to the agent in Immuta](/saas/agentic-data-access/manage-agents.md#map-the-agent-to-external-data-platforms). The external username must be the **service principal UUID** (the application ID) and not the name. You can retrieve the [service principal's UUID from Databricks](https://docs.databricks.com/api/account/accountserviceprincipals/get).

### Connecting to Databricks as the agent

You must connect to Databricks exclusively via OAuth M2M (machine-to-machine) authentication using a scoped token obtained through Databricks' private preview exclusive group feature.

Rather than connecting as a static service account, the agent harness (not the agent itself) first calls Immuta's on-behalf-of (OBO) API to obtain an ephemeral vended exclusive group scoped to the end user's entitlements, and then exchanges the service principal credentials for a short-lived OAuth token that assumes that exclusive group's identity. This ensures every query executed against Databricks is scoped to exactly what the end user is permitted to access, with full auditability via the vended group name in query history.

See the [Databricks documentation](https://docs.databricks.com/en/dev-tools/auth/oauth-m2m.html) for guidance, but here is an example request:

```shellscript
curl -s -X POST \
  -u "$DATABRICKS_SP_CLIENT_ID:$DATABRICKS_SP_CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials&scope=all-apis&assume_group=<nativeRoleId>" \
  "https://<your-databricks-workspace-host>/oidc/v1/token"
```

In this example, `assume_group=<nativeRoleId>` is the exclusive group ID that was returned from the Immuta OBO API. This ensures the access is scoped to *that group only*. [The response](/saas/agentic-data-access/agentic-data-access-reference-guide.md#requesting-the-ephemeral-role) from the Immuta OBO API will include the name and the ID of the vended group. *You must use the ID* in the OAuth M2M authentication's `assume_group`.

### Ensuring the agent account can run queries

Immuta does not manage access to compute, so in order for the agent to execute queries, you must manually assign a warehouse.

See the [Databricks documentation](https://docs.databricks.com/aws/en/sql/language-manual/security-grant) for guidance, but here is an example statement that grants the agent `USAGE` on a warehouse:

```sql
-- Grant usage to the SQL Warehouse
GRANT USAGE ON WAREHOUSE `<warehouse_name>` TO SERVICE PRINCIPAL `<agent_account>`;      
```

## Snowflake

### Dependencies

* Ensure your Immuta customer success representative has enabled the Immuta Agentic Data Access private preview feature.

### Creating and mapping the agent account in Snowflake

* It is best practice for the agent account in Snowflake to be a SERVICE type user. See the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/admin-user-management) for guidance, but here is an example statement that sets the agent as a SERVICE type user:

```sql
ALTER USER "<agent name>" SET TYPE = SERVICE;
```

* Once your SERVICE account is created, [map it to the agent in Immuta](/saas/agentic-data-access/manage-agents.md#map-the-agent-to-external-data-platforms).

### Connecting to Snowflake as the agent

The agent connects to Snowflake using **key-pair authentication** (RSA private/public key pair). This is Snowflake's recommended authentication method for service accounts and automated processes, as it eliminates password rotation requirements and supports mutual authentication.

At connection time, the agent harness (not the agent itself) explicitly sets the active role to the ephemeral vended role returned by Immuta's OBO API using the `role` connection parameter. This ensures the session operates exclusively under the vended role's entitlements from the moment the connection is established.

See the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/key-pair-auth) for details.

**Why not use programmatic access tokens (PAT)?**

Snowflake enforces a [hard limit](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens#limitations) of **15 active PATs per user;** since the agent connects as itself leveraging the vended role per user, in a multi-user concurrent environment this limit is quickly exhausted, causing connection failures. Key-pair authentication with role pinning avoids this constraint entirely since no tokens are created or accumulated.

#### Prerequisites

* The agent must have its RSA public key registered in Snowflake.

**Set the RSA public key**

This is required for key-pair JWT authentication. See the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/key-pair-auth) for guidance, but here is an example of setting the RSA public key:

```sql
ALTER USER "<agent name>" SET RSA_PUBLIC_KEY = '<your_rsa_public_key>';
```

To verify it was registered correctly:

```sql
DESC USER "<agent name>";
```

Look for the `RSA_PUBLIC_KEY_FP` field. It should show a `SHA256:...` fingerprint matching your key.

**Required Snowflake configuration**

To ensure the agent session is restricted to the vended role and cannot access permissions granted to the service account user directly, a session policy must be applied to block secondary roles:

```sql
CREATE SESSION POLICY <database>.<schema>.BLOCK_SECONDARY_ROLES
    ALLOWED_SECONDARY_ROLES = ();

ALTER USER "<agent name>" SET SESSION POLICY <database>.<schema>.BLOCK_SECONDARY_ROLES;
```

Without this policy, Snowflake may allow the session to activate secondary roles beyond the vended role, potentially exposing data the end user is not entitled to see.

See Snowflake documentation on [session policies](https://docs.snowflake.com/en/sql-reference/sql/create-session-policy) and [secondary roles](https://docs.snowflake.com/en/user-guide/session-policies-using#disallow-secondary-roles-for-all-users-in-the-account) for more details.

#### **Execute queries using key-pair auth pinned to the vended role**

See the [Snowflake documentation](https://docs.snowflake.com/en/developer-guide/snowflake-rest-api/authentication#label-sfrest-api-authenticating-key-pair) for guidance, but here is an example request where key-pair authentication is used to connect:

```bash
curl -s -X POST \
  "https://<account-locator>.snowflakecomputing.com/api/v2/statements" \
  -H "Authorization: Bearer <keypair_jwt>" \
  -H "X-Snowflake-Authorization-Token-Type: KEYPAIR_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "statement": "<your SQL>",
    "database": "\"<database>\"",
    "schema": "\"<schema>\"",
    "warehouse": "\"<warehouse>\"",
    "role": "\"<vended_role>\"",
    "parameters": {
      "QUOTED_IDENTIFIERS_IGNORE_CASE": false
    }
  }'
```

The `role` field must be set to the vended role name returned in `roles.Snowflake.roleName` from the [Immuta OBO response](/saas/agentic-data-access/agentic-data-access-reference-guide.md#requesting-the-ephemeral-role). This ensures the query executes exclusively under the vended role's entitlements.

{% hint style="warning" %}
You **must** double quote the role name since the vended role is always mixed case with special characters. Because of this, `"QUOTED_IDENTIFIERS_IGNORE_CASE": false` is required *if* your Snowflake account has `"QUOTED_IDENTIFIERS_IGNORE_CASE": true` configured.
{% endhint %}

Note that `<account-locator>` is the short account locator only (e.g., `cna957322`), not the full regional hostname and not the organization name. The correct value is available in the `connectionKey` field returned by the Immuta OBO API. For example, for `cna957322.us-east-1.snowflakecomputing.com` the locator is `cna95722`.

### Ensuring the agent account can run queries

Immuta does not manage access to compute, so in order for the agent to execute queries, you must manually assign a warehouse.

See the [Snowflake documentation](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege) for guidance, but here is an example statement that grants the agent `USAGE` on a warehouse to the agent's standing role:

```sql
ALTER SESSION SET QUOTED_IDENTIFIERS_IGNORE_CASE = FALSE; -- Only required if your Snowflake account is set to QUOTED_IDENTIFIERS_IGNORE_CASE = TRUE

-- Grant usage to warehouse
GRANT USAGE ON WAREHOUSE <WAREHOUSE> TO ROLE "<agent_role_created_by_immuta>"; 
```

{% hint style="warning" %}
`<agent_role_created_by_immuta>` is **not** the vended role. Rather, it's the role that is permanently assigned to the agent in Snowflake. The creation of this role occurs once you [map the Immuta agent to the Snowflake account](#creating-and-mapping-the-agent-account-in-snowflake) and it is named `<immuta_integration_prefix>_AGENT_<agent_name>`.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://documentation.immuta.com/saas/agentic-data-access/manage-agents/connecting-the-agent-to-the-data-platform.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
