Skip to main content

Connect Snowflake Cortex Agents

Snowflake Cortex Agents run an agent as a native Cortex agent object inside your own Snowflake account. The agent answers questions over the data its tools expose — structured data through Cortex Analyst (text-to-SQL over semantic views) and unstructured data through Cortex Search — and executes on a warehouse you choose. Willow maps a background agent onto that Cortex agent object so it shows up alongside your other agents, with the same identity, ownership, and deploy flow.

On this platform the agent lives in Snowflake, not on Willow's infrastructure. Willow addresses it over the Cortex REST API using an account identifier and a programmatic access token (PAT) you supply once at the org level.

This is not the Snowflake connector

The Snowflake connector is a data source: an MCP server your users query with OAuth. The Snowflake Cortex Agents platform is a background-agent runtime: your agent is a Cortex agent object. They are configured separately and can be used independently.

How it fits together​

PieceWhere it runsWho owns it
Cortex agent objectYour Snowflake accountYou (surfaced in Willow)
Semantic views / Cortex Search servicesYour Snowflake accountYou
WarehouseYour Snowflake accountYou
Programmatic access tokenStored encrypted in WillowYou issue it in Snowflake

At run time, a caller sends a question to the agent's agent:run endpoint. Cortex plans the request with its orchestration model, calls the attached Cortex Analyst and Cortex Search tools, and runs the underlying queries on the agent's warehouse under the caller's default role.

Prerequisites​

  • A Snowflake account with Cortex Agents available in your region, and Cortex features enabled.
  • At least one semantic view (for Cortex Analyst) and/or a Cortex Search service (for unstructured retrieval) that the agent should answer over.
  • A warehouse the agent can use to run its queries.
  • A Snowflake user whose default role grants access to the warehouse, the agent object's database and schema, and the objects behind each tool. Cortex resolves privileges from the caller's default role — not the role active in the session — so this matters even if your current role has every privilege. A token created with ROLE_RESTRICTION uses that role instead, so grant the same access to it.
  • Privileges to create a programmatic access token for that user.

Step 1: Note your account identifier​

Willow addresses the Cortex REST API at https://<account_identifier>.snowflakecomputing.com. The account identifier has the form orgname-account_name (for example acme-analytics). You can read it from a SQL worksheet:

SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME() AS account_identifier;

Step 2: Create a programmatic access token​

Cortex REST calls authenticate with a Snowflake programmatic access token (PAT). Create one for the user the agent should act as, and restrict it to the role that has the agent's data access:

ALTER USER my_agent_user
ADD PROGRAMMATIC ACCESS TOKEN willow_cortex
ROLE_RESTRICTION = 'MY_AGENT_ROLE'
DAYS_TO_EXPIRY = 90;

Copy the returned token secret immediately — Snowflake shows it only once.

Match the token's role to the agent's data

ROLE_RESTRICTION pins the token (and therefore the agent) to one role. Make sure that role can use the warehouse and reach the semantic views, Cortex Search services, and tables behind the agent's tools. This is the single most common cause of "the agent runs but returns no data."

Step 3: Connect the platform in Willow​

  1. Go to Manage > Machine Users > Background Agents (see the list page), open Settings (gear icon), and find Snowflake Cortex Agents under Agent Types.
  2. Select Set credentials and enter:
    • Account identifier — the orgname-account_name value from Step 1. This is an address, not a secret, and is shown back to prefill the form.
    • Programmatic access token — the token secret from Step 2. It is encrypted at rest and never returned by the API.
  3. Select Connect.

Once connected, Snowflake Cortex Agents appears as a selectable platform when creating an agent.

Step 4: Map the agent to a Cortex agent object​

When you create the agent, its platform configuration describes the Cortex agent object it maps to and the data its tools can reach:

FieldMeaning
Database / SchemaWhere the Cortex agent object lives. With the agent name these form its fully-qualified name, DATABASE.SCHEMA.AGENT_NAME, used in SQL and in the agent:run path.
Agent nameThe object name used in SQL and in agent:run requests.
Display nameThe name client applications show to users, from the agent's PROFILE.
WarehouseThe warehouse the agent's tools run queries on.
Orchestration modelThe model Cortex uses to plan tool calls. auto lets Snowflake pick.
Semantic viewsSemantic views reachable through the agent's Cortex Analyst (text-to-SQL) tools.
Cortex Search servicesCortex Search services reachable for unstructured data.

Step 5: Deploy​

Select Deploy in the detail-page header (Deploy changes once the agent has edits that have not reached Snowflake). Deploying reconciles the Cortex agent object and reads back its resolved configuration — account, fully-qualified name, warehouse, orchestration model, and attached tools — which then appear on the agent's card.

The card reports the result:

StateMeaning
SyncedThe Cortex agent object is in place. The card shows its fully-qualified name, account, warehouse, orchestration model, semantic views, Cortex Search services, and when it last synced, with a How to use this agent action and a link to open it in Snowsight.
Pending syncWaiting for an administrator to deploy. Usage instructions appear once synced.

An agent must be synced before it can be invoked. For the deploy action and the sync-state fields, see Deploy an Agent.

Connect an existing Cortex agent (read-only)​

If your team already built a Cortex agent in Snowflake and keeps using it from Snowsight, connect it instead of deploying a new one. Willow then sees and governs every prompt sent to it without changing how anyone uses it.

  1. In Create agent, choose Snowflake Cortex Agents and turn on Connect existing agent.
  2. Enter the Database, Schema, and Agent name of the existing agent object.
  3. Select Connect on the detail page.

A connected agent is read-only in Willow:

  • Willow only reads the agent object (GET). It never creates, replaces, or drops it, including when you delete the agent in Willow.
  • Its instructions, model, and tools are managed in Snowflake. The Tools and Skills tabs are hidden, and Willow tools and skills can't be added to it.
  • Refresh reads the agent from Snowflake again after someone changes it there.

Connecting needs read access, not the privileges needed to create an agent. The token's role needs USAGE on the agent and on the database and schema that hold it. Without the database and schema grants, Snowflake reports the agent as not found:

GRANT USAGE ON DATABASE MY_DB TO ROLE MY_AGENT_ROLE;
GRANT USAGE ON SCHEMA MY_DB.MY_SCHEMA TO ROLE MY_AGENT_ROLE;
GRANT USAGE ON AGENT MY_DB.MY_SCHEMA.MY_AGENT TO ROLE MY_AGENT_ROLE;

The token's role is its ROLE_RESTRICTION from Step 2, or the user's default role if the token has none. Secondary roles are not used, so an agent you can open in Snowsight through another of your roles can still be invisible to the token.

See and govern prompts​

Willow reads every turn sent to a synced Cortex agent, from Snowsight, the REST API, or Slack, out of Snowflake's AI observability events. Each Cortex thread shows up as a conversation in Conversation Logs under the Snowflake provider, with the Snowflake user who asked. Turns sent from Slack are credited to the Slack user, not to the Snowflake user behind Willow's token. New turns arrive within about an hour, and Willow back-fills the last 30 days the first time.

As turns are recorded, Willow flags sensitive data in them (email addresses, card and Social Security numbers, keys, and tokens), the same way it does for other synced conversations. Prompts sent directly in Snowsight can only be flagged after the fact, because Snowflake has no hook that lets Willow stop them. Turns sent through Slack go through your runtime guards before Cortex sees them; see Use the agent from Slack.

What text is kept follows your organization's log settings: with prompt redaction on or response logging off, Willow records the turn without that text.

Grant the token user's default role access to the events:

GRANT DATABASE ROLE SNOWFLAKE.CORTEX_USER TO ROLE MY_AGENT_ROLE;
GRANT MONITOR ON AGENT MY_DB.MY_SCHEMA.MY_AGENT TO ROLE MY_AGENT_ROLE;
-- Or, for every agent in the schema:
GRANT MONITOR ON FUTURE AGENTS IN SCHEMA MY_DB.MY_SCHEMA TO ROLE MY_AGENT_ROLE;
-- Run as ACCOUNTADMIN. Without it, prompts and answers come back redacted:
GRANT READ UNREDACTED AI OBSERVABILITY EVENTS TABLE ON ACCOUNT TO ROLE MY_AGENT_ROLE;

Reading the events runs a short query on the token user's default warehouse (or the agent's warehouse when one is set), so make sure the user has one.

Use the agent from Slack​

Both deployed and connected Cortex agents work with the Slack app. Connect the agent's Slack app as for any other background agent, then mention it or DM it.

Because Cortex can't call Willow's tools, Willow runs each Slack turn itself:

  1. Willow checks the message against your runtime guards and stops it if a guard blocks.
  2. Willow sends the message to the agent's agent:run endpoint. Replies in the same Slack thread continue the same Cortex thread.
  3. Willow checks the answer against your runtime guards, applies any redaction, and posts it in the thread.

Runs use the platform token, so Slack users get the data that token's role can see. To scope guards to Cortex, attach them to the snowflake-cortex AI agent.

Using the agent​

Send a question to the agent object with the Cortex agent:run endpoint, authenticating with the programmatic access token:

curl -X POST \
"https://<account_identifier>.snowflakecomputing.com/api/v2/databases/<database>/schemas/<schema>/agents/<agent_name>:run" \
-H "Authorization: Bearer $SNOWFLAKE_PAT" \
-H "X-Snowflake-Authorization-Token-Type: PROGRAMMATIC_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"stream": false,
"messages": [{"role": "user",
"content": [{"type": "text",
"text": "What is the average order value by market segment?"}]}]
}'

Pass a thread_id and parent_message_id to continue a conversation, or drop stream to receive server-sent events instead. The exact fields on the card's How to use this agent dialog are prefilled with your agent's account, database, schema, and name.

Cortex uses the caller's default role and warehouse

Cortex resolves permissions from the caller's default role and runs queries on their default warehouse, not the role active in the session. Calls fail if either is missing, even when the current role has every required privilege. See the Cortex Agents run documentation.

Troubleshooting​

The agent runs but returns no data​

The token's role cannot reach the data. Confirm the ROLE_RESTRICTION role from Step 2 can use the agent's warehouse and has SELECT/usage privileges on the semantic views, Cortex Search services, and tables behind its tools.

Calls fail with a role or warehouse error​

Cortex uses the caller's default role and warehouse, not the session's. Set them on the user:

ALTER USER my_agent_user SET DEFAULT_ROLE = MY_AGENT_ROLE;
ALTER USER my_agent_user SET DEFAULT_WAREHOUSE = MY_WAREHOUSE;

Authentication is rejected​

Confirm both PAT headers are sent — Authorization: Bearer <token> and X-Snowflake-Authorization-Token-Type: PROGRAMMATIC_ACCESS_TOKEN — and that the token has not passed its DAYS_TO_EXPIRY. Re-issue the token in Step 2 and update it under Set credentials if it has expired.

The host cannot be resolved​

The account identifier is wrong. It must be orgname-account_name (a hyphen, not a dot). Re-read it with the query in Step 1.

Deploy fails with 502, but agent:run works from a laptop​

Willow Deploy talks to Snowflake from Willow's cloud, not from your network. A working agent:run against a PrivateLink host (*.privatelink.snowflakecomputing.com) only proves the PAT works on a machine that can reach PrivateLink.

  • Set the account identifier to the public orgname-account_name value from Step 1, not the PrivateLink hostname.
  • Confirm the account still allows public access for the Cortex REST API. If public access is disabled, Willow cannot deploy the agent object.
  • Deploy creates or replaces the Cortex agent object (GET/POST/PUT on /agents). That needs privileges beyond USAGE on an existing agent — USAGE is enough to :run, not to deploy.

Logs for this call are in db-service, not the run or connect pods.

Deploy fails with "Failed to create Cortex agent (HTTP 404)"​

The token's role can't create agents in that schema, often because the role only has access through secondary roles, which Cortex ignores. Grant USAGE on the database and schema and CREATE AGENT on the schema to the token's role, or connect the existing agent instead.

Connect fails with "Snowflake could not find Cortex agent"​

The agent exists, but the token's role can't see it. Snowflake answers "does not exist or not authorized" for both cases. Find the role the token uses, then test the read as that role alone:

SHOW USER PROGRAMMATIC ACCESS TOKENS FOR USER my_agent_user; -- role_restriction column

USE ROLE MY_AGENT_ROLE;
USE SECONDARY ROLES NONE;
DESCRIBE AGENT MY_DB.MY_SCHEMA.MY_AGENT;

If DESCRIBE fails, grant the role USAGE on the database, schema, and agent as in Connect an existing Cortex agent, then select Connect again. The error in Willow includes Snowflake's own response after the HTTP status.

Cortex conversations are missing or redacted​

The default role is missing READ UNREDACTED AI OBSERVABILITY EVENTS TABLE, so Snowflake returns only metadata. Have an account administrator run the grant in See and govern prompts.

What to do next​