# Connecting the Agent to the Data Platform

## Databricks

### Dependencies

* Ensure your Immuta customer success representative has enabled the Immuta Agentic Data Access private preview feature.&#x20;
* 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 agent_group.
-- agent_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` (
    agent_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.agent_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.&#x20;

Rather than connecting as a static service account, the agent 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.&#x20;

### 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

You must connect to Snowflake exclusively via programmatic access token (PAT) authentication scoped to the vended role obtained through Immuta's OBO API.

Rather than connecting as a static service account with a long-lived credential, the agent first calls Immuta's OBO API to obtain an ephemeral vended role scoped to the end user's entitlements, and then creates a short-lived PAT restricted to that role using key-pair JWT authentication. This ensures every query executed against Snowflake is scoped to exactly what the end user is permitted to access, with full auditability via the vended role name in query history.

#### **Prerequisites**

* The agent must have its RSA public key registered in Snowflake.&#x20;
* The service account user must have a network policy assigned before the PAT creation.
* The agent must have permission to create the programmatic access token.
* For production deployments, restrict `ALLOWED_IP_LIST` to your specific IP ranges.

**Set the RSA public key**

This is required for key-pair JWT authentication used to create the PAT. 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_user>" SET RSA_PUBLIC_KEY = '<your_rsa_public_key>';
```

To verify it was registered correctly:

```sql
DESC USER "<agent_user>";
```

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

**Assign a network policy**

The service account user must also have a network policy assigned before PAT creation will be permitted by Snowflake. If no existing network policy is available, create a permissive one and attach it. See the [Snowflake documentation](https://docs.snowflake.com/en/sql-reference/sql/create-network-policy) for guidance, but here is an example network policy:

```sql
CREATE NETWORK POLICY immuta_agent_policy
  ALLOWED_IP_LIST = ('0.0.0.0/0')
  COMMENT = 'Required for Immuta agent PAT creation';

ALTER USER "<agent_name>" SET NETWORK_POLICY = immuta_agent_policy;
```

**Grant the agent permission to create the programmatic access token**

You will also need to grant the agent permission to create the programmatic access token. See the [Snowflake documentation](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens) for guidance, but here is an example statement that grants the agent permission to do so:

```sql
-- Grant permission to create token
GRANT MODIFY PROGRAMMATIC AUTHENTICATION METHODS
ON USER "<agent_name>"
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 %}

#### **1 - Create a PAT scoped to the vended role**

Using key-pair JWT authentication, call the Snowflake REST API to create a PAT restricted to the vended role returned by the Immuta OBO API.

```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": "ALTER USER ADD PROGRAMMATIC ACCESS TOKEN <token_name> ROLE_RESTRICTION = '\''<vended_role>'\'' MINS_TO_EXPIRY = <ttl> COMMENT = '\''OBO <user>'\''"
  }'
```

In this example, `ROLE_RESTRICTION = '<vended_role>'` is the ephemeral role name returned from the Immuta OBO API. This ensures the PAT can only be used under that role. The [Immuta OBO API response](/saas/agentic-data-access/agentic-data-access-reference-guide.md#requesting-the-ephemeral-role) includes the role name in `roles.Snowflake.roleName`; use that value here. The PAT should also be configured with the same `MINS_TO_EXPIRY` as the OBO API call's time-to-live (TTL).

The response returns both a `token_name` and a `token_secret`. You must use the `token_secret` in the next step.

#### **2 - Execute queries using the PAT**

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

Note that `<account-locator>` is the short account locator only (e.g., `cna123456`), 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 (e.g., For `cna12345.us-east-1.snowflakecomputing.com`, the locator is `cna12345`).

### 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:

```sql
-- 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: 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:

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

The question should be specific, self-contained, and written in natural language.
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.
