Share to gain more social capita

Written by — Mika Heino, Data Architect
Unlock secure, real-time data insights by integrating external APIs in Snowflake. Learn how to leverage Perplexity API with advanced secrets management, network rules, logging, and external access integrations for seamless agentic workflows.
Written by — Mika Heino, Data Architect
Share to gain more social capita
When exploring agentic workflows, you'll eventually need to access external API endpoints to provide real-time data for your agent. One use case could be to utilize the Perplexity API to retrieve real-time data that is not available in the LLM models provided by Snowflake Cortex. Perplexity AI can be used to answer queries using sources from the web and it’s accessible through API endpoints with credits, which will grant you an API -key, which you want to keep secure.
Within this blog post, I’ll demonstrate how this requirement can be met with Snowflake services.
Accessing an API usually requires storing the API user and its key in a secure location. Traditional development in Python means storing the key in OS environment variables or maintaining a .env file loaded using the “python-dotenv” -library. For local deployments and testing purposes, this pattern works, but for production deployments, Docker Secrets and secret management tools from cloud vendors are usually chosen.
For deployments within Snowflake, you can use Snowflake Secrets. Snowflake Secrets use the same RBAC process as other entities created within Snowflake (e.g. grant usage on secret to role <role>) and they require no additional code to maintain. You create and maintain secrets using SQL as seen below in (example 1) and reference them later by the secret name.
CREATE SECRET api_perplexity |
We don’t want our Snowflake account to be available on the public internet, but we want to access the API endpoint from our Snowflake account. For this, we use network rules, which are the most granular level of objects that you can use to define network identifiers. The above network rules are network policies (for inbound access) and external access integrations (for outbound access) and both of them use network rules to control network traffic in and out of Snowflake service and internal stages.
In our use, we will reference this network rule on our external access integration for granting access into a given API endpoint as seen in the example 2.
|
External access integrations are, as noted in the previous chapter, entities to control outbound access from the Snowflake account. As you can see from the code below (example 3), external access integration builds upon previous components. Within external integration, you define which network rules and secrets are used (you can have a multitude of network rules and secrets) for a given integration. External access integrations are helpful components when you write for example a UDF or procedure that accesses an external location.
What’s not used in example 3. is the possibility to define whether your connection to an external network location uses the public Internet or a private network, such as by using Azure Private Link or AWS PrivateLink.
CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION api_perplexity |
As our code will be written in Python and stored within the Snowflake stored procedure, it means that we want to have a better understanding of what happens when we call our procedure. For this, we can leverage logging capabilities. Logging events happen by importing logging and using it as you would normally do (as seen in example 4.) For a full list of supported languages, check Snowflake documentation.
import logging |
Messages are then stored automatically in the Snowflake event table which you can create without schema as the table inherently possesses a predefined set of columns. After creating the table you define the event table as active, but setting it on an account level (examples 5 and 6). This newly created event table can be queried as a normal table.
CREATE EVENT TABLE <database_name>.<schema_name>.<event_table_name>; |
You can change the log-level settings based on your needs.
-- To set log level at session level |
We are creating this API connection as a Snowflake stored procedure which allows us to call API in a similar manner as we would call any Snowflake Cortex function. Wrapping the API call inside a stored procedure allows us to leverage all the previously mentioned components for a secure and loggable connection. A stored procedure allows the code to be reusable in another project without code duplication.
Before heading into the Snowflake part, obtain the Perplexity API Key.
To access this feature, you need an account on Perplexity website
Enter your billing information to establish a payment method. This is required for generating your API key. Once done, navigate to the API settings page. API settings can be found on the wheel next to your account on the left corner.
In the API settings, find the “Available Credits” section and click on “Buy Credits.” Specify the number of credits you’d like to purchase and follow the on-screen instructions to complete the transaction. Note: If you create an Pro account, you’ll be given 5$ of worth of credits out of box
Go to the “API Keys” section in your account dashboard and click the “Generate API Key” button to create your API key.
Use the string obtained in the previous part and add that as a password. As Perplexity does not require a username, give the username as ‘user.
-- Create Secret |
For this network rule, we define .perplexity.ai as the value list
-- Create a Network rule |
Create a external access integration that uses the rule and secret created above
-- Create EAI |
Putting this all together is rather simple. Snowflake Snowpark Stored Procedure uses Anaconda packages and because of that, we can inform, that "requests"-package is needed during installation.
We have the option to load third-party packages, but for this use case, those are unnecessary. Other important notions are the mention of EXTERNAL_ACCESS_INTEGRATION which defines what access the stored procedure is allowed to use. SECRETS define what secrets to use for the Stored Procedure. With this method, we can later say that _snowflake.get_username_password('cred').password contains our password to Perplexity API.
The last part of the procedure is the EXECUTE AS notion, which is related to Snowflake internals as this stored procedure uses Snowflake RBAC. This means that if we do not execute the procedure as the owner, we need to grant usage to the caller. Creating any Snowflake objects with the code also follows the rights of the execute as. If I execute this procedure as ACCOUNTADMIN and create a table within the code, the table will be owned by ACCOUNTADMIN.
Breakdown of rights
Caller’s Rights |
Owner’s Rights |
Runs with the privileges of the caller. |
Runs with the privileges of the owner. |
Inherit the current warehouse of the caller. |
Inherit the current warehouse of the caller. |
Use the database and schema that the caller is currently using. |
Use the database and schema that the stored procedure is created in, not the database and schema that the caller is currently using. |
CREATE OR REPLACE PROCEDURE AI_AGENT.PUBLIC.PERPLEXITY(PARAMS VARCHAR(16777216)) |
Testing the function happens by calling the procedure with a given user message. The result gives an accurate answer referencing a blog video released on the Recordly site.
This call can now be made anywhere as long as the caller is either the owner of the procedure or has been granted usage for the procedure.
|
You should now have an understanding of how you can create external access from Snowflake. Obviously, this is not the only pattern on how to solve external access integrations, as Snowflake Containers Services introduces a variety of Docker-based solutions. This solution though works inside Snowflake and can be leveraged on code deployed into Snowflake Container Services or Snowflake Notebooks.