# embedding_metadata

key: chroma:document
string_value:
Value: Users can now leverage ChatGPT's natural language capability to connect directly to Snowflake’s Data Warehouse..

Example Use Cases:



* Data scientists can connect to tables and run data analyses using ChatGPT's Data Analysis
* Citizen data users can ask basic questions of their transactional data
* Users gain more visibility into their data & potential anomalies

## Application Information

### Application Key Links


Check out these links from the application before you get started:

* Application Website: [https://app.snowflake.com/](https://app.snowflake.com/)
* Application API Documentation: [https://docs.snowflake.com/en/developer-guide/sql-api/intro](https://docs.snowflake.com/en/developer-guide/sql-api/intro)

### Application Prerequisites

Before you get started, make sure you go through the following steps in your application environment:

* Provision a Snowflake Data Warehouse
* Ensure that the user authenticating into Snowflake via ChatGPT has access to the database, schemas, and tables with the necessary role

## ChatGPT Steps


### Custom GPT Instructions

Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
**Context**: You are an expert at writing Snowflake SQL queries. A user is going to ask you a question. 

**Instructions**:
1. No matter the user's question, start by running `runQuery` operation using this query: "SELECT column_name, table_name, data_type, comment FROM `{database}.INFORMATION_SCHEMA.COLUMNS`" 
-- Assume warehouse = "<insert your default warehouse here>", database = "<insert your default database here>", unless the user provides different values 
2. Convert the user's question into a SQL statement that leverages the step above and run the `runQuery` operation on that SQL statement to confirm the query works. Add a limit of 100 rows
3. Now remove the limit of 100 rows and return back the query for the user to see
4. Use the <your role> role when querying Snowflake
5. Run each step in sequence. Explain what you are doing in a few sentences, run the action, and then explain what you learned. This will help the user understand the reason behind your workflow. 

**Additional Notes**: If the user says "Let's get started", explain that the user can provide a project or dataset, along with a question they want answered. If the user has no ideas, suggest that we have a sample flights dataset they can query - ask if they want you to query that
```


### OpenAPI Schema

Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
openapi: 3.1.0
info:
  title: Snowflake Statements API
  version: 1.0.0
  description: API for executing statements in Snowflake with specific warehouse and role settings.
servers:
  - url: 'https://<your server ID>.<your cloud region>.<your cloud provider>.snowflakecomputing.com/api/v2'


key: _node_content
string_value:
{"id_": "5cbdab75-0978-4d07-b52c-6990e6726a60", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb", "title": "GPT Actions - Snowflake direct", "tokens": 2052, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "88c46207-4331-4ae6-b7d2-a2050372f0ae", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb", "title": "GPT Actions - Snowflake direct", "tokens": 2052, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "775ee052d13a93925560fb565cf2c6f1b26b76866b5598edbac5307e876346b1", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "9e18b91d-bc29-4de9-b309-7a251deeb0f1", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb", "title": "GPT Actions - Snowflake direct", "tokens": 2052, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "7df252ae313d05d2d4ca6c690d03fe01e8f8c5defa08dc166e6c39d6c03e7474", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "0fcdd102-93b8-45bc-884b-2f353f31c1f5", "node_type": "1", "metadata": {}, "hash": "ea25c28fb4e193ecc396f37a0d36ee4044cfd8a980423ac1393efa74e60cbc56", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 3940, "end_char_idx": 7576, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
### OpenAPI Schema

Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
openapi: 3.1.0
info:
  title: Snowflake Statements API
  version: 1.0.0
  description: API for executing statements in Snowflake with specific warehouse and role settings.
servers:
  - url: 'https://<your server ID>.<your cloud region>.<your cloud provider>.snowflakecomputing.com/api/v2'


paths:
  /statements:
    post:
      summary: Execute a SQL statement in Snowflake
      description: This endpoint allows users to execute a SQL statement in Snowflake, specifying the warehouse and roles to use.
      operationId: runQuery
      tags:
        - Statements
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse:
                  type: string
                  description: The name of the Snowflake warehouse to use for the statement execution.
                role:
                  type: string
                  description: The Snowflake role to assume for the statement execution.
                statement:
                  type: string
                  description: The SQL statement to execute.
              required:
                - warehouse
                - role
                - statement
      responses:
        '200':
          description: Successful execution of the SQL statement.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    additionalProperties: true
        '400':
          description: Bad request, e.g., invalid SQL statement or missing parameters.
        '401':
          description: Authentication error, invalid API credentials.
        '500':
          description: Internal server error.
```

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

### Pre-Action Steps

Before you set up authentication in ChatGPT, please take the following steps in the application.

* Review the Snowflake OAuth Overview: [https://docs.snowflake.com/en/user-guide/oauth-snowflake-overview](https://docs.snowflake.com/en/user-guide/oauth-snowflake-overview)
* Go to the Snowflake Worksheets
* Create new OAuth credentials through a [Security Integration](https://docs.snowflake.com/en/sql-reference/sql/create-security-integration-oauth-snowflake) - you will need a new one for each OAuth app/custom GPT since Snowflake Redirect URIs are 1-1 mapped to Security Integrations



```python
CREATE SECURITY INTEGRATION CHATGPT_INTEGRATION
  TYPE = OAUTH
  ENABLED = TRUE
  OAUTH_CLIENT = CUSTOM
  OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'
  OAUTH_REDIRECT_URI = 'https://oauth.pstmn.io/v1/callback' --- // this is a temporary value while testing your integration. You will replace this with the value your GPT provides
  OAUTH_ISSUE_REFRESH_TOKENS = TRUE
  OAUTH_REFRESH_TOKEN_VALIDITY = 7776000;
```


* Retrieve your OAuth Client ID, Auth URL, and Token URL



```python
DESCRIBE SECURITY INTEGRATION CHATGPT_INTEGRATION;
```


You’ll find the required information in these 3 columns:


key: _node_content
string_value:
{"id_": "0fcdd102-93b8-45bc-884b-2f353f31c1f5", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb", "title": "GPT Actions - Snowflake direct", "tokens": 2052, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "88c46207-4331-4ae6-b7d2-a2050372f0ae", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb", "title": "GPT Actions - Snowflake direct", "tokens": 2052, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "775ee052d13a93925560fb565cf2c6f1b26b76866b5598edbac5307e876346b1", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "5cbdab75-0978-4d07-b52c-6990e6726a60", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb", "title": "GPT Actions - Snowflake direct", "tokens": 2052, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "8a9064ae405b1e7948814a7f17a651128352f8c7660ffb454a341375486c9fcf", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6978, "end_char_idx": 9663, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
CREATE SECURITY INTEGRATION CHATGPT_INTEGRATION
  TYPE = OAUTH
  ENABLED = TRUE
  OAUTH_CLIENT = CUSTOM
  OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'
  OAUTH_REDIRECT_URI = 'https://oauth.pstmn.io/v1/callback' --- // this is a temporary value while testing your integration. You will replace this with the value your GPT provides
  OAUTH_ISSUE_REFRESH_TOKENS = TRUE
  OAUTH_REFRESH_TOKEN_VALIDITY = 7776000;
```


* Retrieve your OAuth Client ID, Auth URL, and Token URL



```python
DESCRIBE SECURITY INTEGRATION CHATGPT_INTEGRATION;
```


You’ll find the required information in these 3 columns:


![../../../images/snowflake_direct_oauth.png](../../../images/snowflake_direct_oauth.png)


* Retrieve your OAuth Client Secret

You’ll find the Client Secret in OAUTH_CLIENT_SECRET.

You’re now set to test your action in Postman. Once you get a successful API response there, you can proceed with your GPT Action.

### In ChatGPT

In ChatGPT, click on "Authentication" and choose "OAuth". Enter in the information below.

* Client ID: use Client ID from steps above
* Client Secret: use Client Secret from steps above
* Authorization URL: use Authorization Endpoint from steps above
* Token URL: use Token Endpoint from steps above
* Scope: &lt;empty>*
* Token: Default (POST)

*Snowflake scopes pass the role, but you’ll notice the action itself also specifies the role as a parameter in runQuery, so the Scope is unnecessary. You may elect to pass roles in the scope instead of the action parameters if it makes more sense for your GPT.

### Post-Action Steps


Once you've set up authentication in ChatGPT, follow the steps below in the application to finalize the Action.

* Copy the callback URL from the GPT Action
* Update the Redirect URI in your Security Integration to the callback URL provided in ChatGPT.



```python
ALTER SECURITY INTEGRATION CHATGPT_INTEGRATION_DEV SET OAUTH_REDIRECT_URI='https://chat.openai.com/aip/<callback_id>/oauth/callback';
```

### FAQ & Troubleshooting


* _Callback URL Error:_ If you get a callback URL error in ChatGPT, pay close attention to the Post-Action Steps above. You need to add the callback URL directly into your Security Integration for the action to authenticate correctly
* _Schema calls the wrong warehouse or database:_ If ChatGPT calls the wrong warehouse or database, consider updating your instructions to make it more explicit either (a) which warehouse / database should be called or (b) to require the user provide those exact details before it runs the query



_Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look._


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb


key: _node_content
string_value:
{"id_": "9369a343-f9d5-4af9-b68a-2dc4488f67ee", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b59e8cf1-6103-4849-8c27-8fa6c32e3559", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f62fa967f68bc5241a086fbaa9f3d46980603c7b1353007b2671a89a11a46c3d", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "a0d3d013-bbf4-4f67-8a3f-cfcec993e022", "node_type": "1", "metadata": {}, "hash": "898d832dfb7ed3984707f24561544b2d36430c6dbbffd7393e30e759d050eb9c", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 3289, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# GPT Action Library: AWS RedShift

## Introduction

This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information: 
- [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
- [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
- [Example of Building a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)

This solution enables a GPT action to retrieve data from Redshift and perform data analysis.It uses AWS Functions, performing every action from AWS ecosystem and network. The middleware (AWS function) will perform the SQL query, wait for its completion and return the data as a file. The code is provided for information purpose only and should be modified to your needs.

This solution uses the ability to [retrieve files in Actions](https://platform.openai.com/docs/actions/sending-files) and use them as if you had uploaded them directly to a conversation.

This solution highlight a connection to Redshift serverless, the integration with a provisioned Redshift might differ slighltly to retrieve networks and set-up connection, the overall code and (minimal) integration should be similar.

### Value & Example Business Use Cases

**Value**: Leverage ChatGPT's natural language capabilities to connect to Redshift's DWH.

**Example Use Cases**:
- Data scientists can connect to tables and run data analyses using ChatGPT's Data Analysis
- Citizen data users can ask basic questions of their transactional data
- Users gain more visibility into their data & potential anomalies

## Application Information

### Application Prerequisites

Before you get started, make sure that:
- You have access to a Redshift environment
- You have the rights to deploy AWS function in the same VPC (Virtual Private Network)
- Your AWS CLI is authenticated

## Middleware Information

### Install required libraries
- Install AWS CLI, required for AWS SAM ([docs](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions))
- Install AWS SAM CLI ([docs](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html))
- Install Python
- Install yq [docs](https://github.com/mikefarah/yq?tab=readme-ov-file#install)

### Middleware function

To create a function, follow the steps in the [AWS Middleware Action cookbook](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_aws_function).

To deploy specifically an application that connects to Redshift, use the following code instead of the "hello-world" GitHub repository referenced in the Middleware AWS Function cookbook. You can either clone the repository or take the code pasted below and modify it to your needs.

> This code is meant to be directional - while it should work out of the box, it is designed to be customized to your needs (see examples towards the end of this document).

To get the code, you can clone openai-cookbook repository and navigate to the redshift-middleware directory

```
git clone https://github.com/pap-openai/redshift-middleware
cd redshift-middleware
```


key: _node_content
string_value:
{"id_": "a0d3d013-bbf4-4f67-8a3f-cfcec993e022", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b59e8cf1-6103-4849-8c27-8fa6c32e3559", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f62fa967f68bc5241a086fbaa9f3d46980603c7b1353007b2671a89a11a46c3d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "9369a343-f9d5-4af9-b68a-2dc4488f67ee", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "c3895895d508692e6b8199628e271e1df7dc7caed8a7a6c4fa8c106abdebea8e", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "07e0d4a1-761d-4d18-95f3-f14708e698ad", "node_type": "1", "metadata": {}, "hash": "fdc0c27013843c96ce6bb635338e92863cf3d28e38a7fc18427be44d726bfc6b", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 3292, "end_char_idx": 6106, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
import json
import psycopg2
import os
import base64
import tempfile
import csv

# Fetch Redshift credentials from environment variables
host = os.environ['REDSHIFT_HOST']
port = os.environ['REDSHIFT_PORT']
user = os.environ['REDSHIFT_USER']
password = os.environ['REDSHIFT_PASSWORD']
database = os.environ['REDSHIFT_DB']

def execute_statement(sql_statement):
    try:
        # Establish connection
        conn = psycopg2.connect(
            host=host,
            port=port,
            user=user,
            password=password,
            dbname=database
        )
        cur = conn.cursor()
        cur.execute(sql_statement)
        conn.commit()

        # Fetch all results
        if cur.description:
            columns = [desc[0] for desc in cur.description]
            result = cur.fetchall()
        else:
            columns = []
            result = []

        cur.close()
        conn.close()
        return columns, result

    except Exception as e:
        raise Exception(f"Database query failed: {str(e)}")

def lambda_handler(event, context):
    try:
        data = json.loads(event['body'])
        sql_statement = data['sql_statement']

        # Execute the statement and fetch results
        columns, result = execute_statement(sql_statement)
        
        # Create a temporary file to save the result as CSV
        with tempfile.NamedTemporaryFile(delete=False, mode='w', suffix='.csv', newline='') as tmp_file:
            csv_writer = csv.writer(tmp_file)
            if columns:
                csv_writer.writerow(columns)  # Write the header
            csv_writer.writerows(result)  # Write all rows
            tmp_file_path = tmp_file.name

        # Read the file and encode its content to base64
        with open(tmp_file_path, 'rb') as f:
            file_content = f.read()
            encoded_content = base64.b64encode(file_content).decode('utf-8')

        response = {
            'openaiFileResponse': [
                {
                    'name': 'query_result.csv',
                    'mime_type': 'text/csv',
                    'content': encoded_content
                }
            ]
        }

        return {
            'statusCode': 200,
            'headers': {
                'Content-Type': 'application/json'
            },
            'body': json.dumps(response)
        }

    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

```

### Retrieve VPC information

We will need to connnect our function to Redshift, therefore we need to find the network used by Redshift. You can find this on your Redshift interface the AWS console, under Amazon Redshift Serverless > Workgroup configuration > `your_workgroup` > Data access, or through the CLI:


key: _node_content
string_value:
{"id_": "07e0d4a1-761d-4d18-95f3-f14708e698ad", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b59e8cf1-6103-4849-8c27-8fa6c32e3559", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f62fa967f68bc5241a086fbaa9f3d46980603c7b1353007b2671a89a11a46c3d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "a0d3d013-bbf4-4f67-8a3f-cfcec993e022", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "0e9170a0a635a0642a4cbe14c6f366b9b1fd7f3a3a3690f33c9e92421e48eb9c", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "e58268ee-d1ce-4f34-8e08-94d46a44186f", "node_type": "1", "metadata": {}, "hash": "55353d1f2a170965d6e37f7c180cee53b8f4a0a9a5db309b5832e9ac90121c48", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6109, "end_char_idx": 7459, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
aws redshift-serverless get-workgroup --workgroup-name default-workgroup --query 'workgroup.{address: endpoint.address, port: endpoint.port, SecurityGroupIds: securityGroupIds, SubnetIds: subnetIds}'
```

### Set up AWS function

Copy `env.sample.yaml` to `env.yaml` and replace with the values obtained above. You will need a Redshift user with access to your DB/schema.

```
cp env.sample.yaml env.yaml
```

Fill in `env.yaml` with the values retrieved by the previous command as well as your credentials to Redshift.
Alternatively, you can create a file named `env.yaml` manually and fill the following variables:
```
RedshiftHost: default-workgroup.xxxxx.{region}.redshift-serverless.amazonaws.com
RedshiftPort: 5439
RedshiftUser: username
RedshiftPassword: password
RedshiftDb: my-db
SecurityGroupId: sg-xx
SubnetId1: subnet-xx
SubnetId2: subnet-xx
SubnetId3: subnet-xx
SubnetId4: subnet-xx
SubnetId5: subnet-xx
SubnetId6: subnet-xx
```

This file will be used to deploy your function with parameters, as shown below:

```
PARAM_FILE="env.yaml"
PARAMS=$(yq eval -o=json $PARAM_FILE | jq -r 'to_entries | map("\(.key)=\(.value|tostring)") | join(" ")')
sam deploy --template-file template.yaml --stack-name redshift-middleware --capabilities CAPABILITY_IAM --parameter-overrides $PARAMS
```

The template.yaml has the following content:


key: _node_content
string_value:
{"id_": "e58268ee-d1ce-4f34-8e08-94d46a44186f", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b59e8cf1-6103-4849-8c27-8fa6c32e3559", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f62fa967f68bc5241a086fbaa9f3d46980603c7b1353007b2671a89a11a46c3d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "07e0d4a1-761d-4d18-95f3-f14708e698ad", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "23c2173fdb31f1f6f1cb9a3638d13b9faa7bb4d10f78f63fdf36b192262eba76", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "11ce001c-0dd2-49fe-8edf-015df190d1a8", "node_type": "1", "metadata": {}, "hash": "887783962135ba3f2a5ea9e7709688ee6903ada34a8dd762aa49c3c59b372952", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6109, "end_char_idx": 9157, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
aws redshift-serverless get-workgroup --workgroup-name default-workgroup --query 'workgroup.{address: endpoint.address, port: endpoint.port, SecurityGroupIds: securityGroupIds, SubnetIds: subnetIds}'
```

### Set up AWS function

Copy `env.sample.yaml` to `env.yaml` and replace with the values obtained above. You will need a Redshift user with access to your DB/schema.

```
cp env.sample.yaml env.yaml
```

Fill in `env.yaml` with the values retrieved by the previous command as well as your credentials to Redshift.
Alternatively, you can create a file named `env.yaml` manually and fill the following variables:
```
RedshiftHost: default-workgroup.xxxxx.{region}.redshift-serverless.amazonaws.com
RedshiftPort: 5439
RedshiftUser: username
RedshiftPassword: password
RedshiftDb: my-db
SecurityGroupId: sg-xx
SubnetId1: subnet-xx
SubnetId2: subnet-xx
SubnetId3: subnet-xx
SubnetId4: subnet-xx
SubnetId5: subnet-xx
SubnetId6: subnet-xx
```

This file will be used to deploy your function with parameters, as shown below:

```
PARAM_FILE="env.yaml"
PARAMS=$(yq eval -o=json $PARAM_FILE | jq -r 'to_entries | map("\(.key)=\(.value|tostring)") | join(" ")')
sam deploy --template-file template.yaml --stack-name redshift-middleware --capabilities CAPABILITY_IAM --parameter-overrides $PARAMS
```

The template.yaml has the following content:


```python
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  redshift-middleware

  Middleware to fetch RedShift data and return it through HTTP as files

Globals:
  Function:
    Timeout: 3

Parameters:
  RedshiftHost:
    Type: String
  RedshiftPort:
    Type: String
  RedshiftUser:
    Type: String
  RedshiftPassword:
    Type: String
  RedshiftDb:
    Type: String
  SecurityGroupId:
    Type: String
  SubnetId1:
    Type: String
  SubnetId2:
    Type: String
  SubnetId3:
    Type: String
  SubnetId4:
    Type: String
  SubnetId5:
    Type: String
  SubnetId6:
    Type: String
  CognitoUserPoolName:
    Type: String
    Default: MyCognitoUserPool
  CognitoUserPoolClientName:
    Type: String
    Default: MyCognitoUserPoolClient

Resources:
  MyCognitoUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UserPoolName: !Ref CognitoUserPoolName
      Policies:
        PasswordPolicy:
          MinimumLength: 8
      UsernameAttributes:
        - email
      Schema:
        - AttributeDataType: String
          Name: email
          Required: false

  MyCognitoUserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      UserPoolId: !Ref MyCognitoUserPool
      ClientName: !Ref CognitoUserPoolClientName
      GenerateSecret: true

  RedshiftMiddlewareApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Cors: "'*'"
      Auth:
        DefaultAuthorizer: MyCognitoAuthorizer
        Authorizers:
          MyCognitoAuthorizer:
            AuthorizationScopes:
              - openid
              - email
              - profile
            UserPoolArn: !GetAtt MyCognitoUserPool.


key: _node_content
string_value:
{"id_": "11ce001c-0dd2-49fe-8edf-015df190d1a8", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b59e8cf1-6103-4849-8c27-8fa6c32e3559", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f62fa967f68bc5241a086fbaa9f3d46980603c7b1353007b2671a89a11a46c3d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "e58268ee-d1ce-4f34-8e08-94d46a44186f", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f04e91b04597f8d1d68fe615e74153fb45c24510f2e58a0c3ddd02a93fea3d96", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "6ecc472c-0f4e-4f2a-a1ac-30b0c9a195b6", "node_type": "1", "metadata": {}, "hash": "0ce4ae435c18bc569ee8398d9b766102fe08de231db645b7bc9446746bf6e680", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 9157, "end_char_idx": 11253, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
Arn
        
  RedshiftMiddlewareFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: redshift-middleware/
      Handler: app.lambda_handler
      Runtime: python3.11
      Timeout: 45
      Architectures:
        - x86_64
      Events:
        SqlStatement:
          Type: Api
          Properties:
            Path: /sql_statement
            Method: post
            RestApiId: !Ref RedshiftMiddlewareApi
      Environment:
        Variables:
          REDSHIFT_HOST: !Ref RedshiftHost
          REDSHIFT_PORT: !Ref RedshiftPort
          REDSHIFT_USER: !Ref RedshiftUser
          REDSHIFT_PASSWORD: !Ref RedshiftPassword
          REDSHIFT_DB: !Ref RedshiftDb
      VpcConfig:
        SecurityGroupIds:
          - !Ref SecurityGroupId
        SubnetIds:
          - !Ref SubnetId1
          - !Ref SubnetId2
          - !Ref SubnetId3
          - !Ref SubnetId4
          - !Ref SubnetId5
          - !Ref SubnetId6

Outputs:
  RedshiftMiddlewareApi:
    Description: "API Gateway endpoint URL for Prod stage for SQL Statement function"
    Value: !Sub "https://${RedshiftMiddlewareApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/sql_statement/"
  RedshiftMiddlewareFunction:
    Description: "SQL Statement Lambda Function ARN"
    Value: !GetAtt RedshiftMiddlewareFunction.Arn
  RedshiftMiddlewareFunctionIamRole:
    Description: "Implicit IAM Role created for SQL Statement function"
    Value: !GetAtt RedshiftMiddlewareFunctionRole.Arn
  CognitoUserPoolArn:
    Description: "ARN of the Cognito User Pool"
    Value: !GetAtt MyCognitoUserPool.Arn

```

Retrieve the URL information from the previous command output, you can then run a cURL request, which should return data in a file format:


```python
curl -X POST https://<your_url>/Prod/sql_statement/ \
-H "Content-Type: application/json" \
-d '{ "sql_statement": "SELECT * FROM customers LIMIT 10", "workgroup_name": "default-workgroup", "database_name": "pap-db" }'
```

## ChatGPT Steps

### Custom GPT Instructions 

Once you've created a Custom GPT, copy the text below in the Instructions panel.


key: _node_content
string_value:
{"id_": "6ecc472c-0f4e-4f2a-a1ac-30b0c9a195b6", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b59e8cf1-6103-4849-8c27-8fa6c32e3559", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f62fa967f68bc5241a086fbaa9f3d46980603c7b1353007b2671a89a11a46c3d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "11ce001c-0dd2-49fe-8edf-015df190d1a8", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "36061ac237b13eaadc7a824dc3a87005f13a353701e002d21a0e9487310ba4ec", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "fef4760b-47fa-46d9-bc4f-898ab3c0155d", "node_type": "1", "metadata": {}, "hash": "97af33b11de264f9c5a986c42d5fb6c6218f51bb31f4ba1825fc1e0a4460a04f", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 10275, "end_char_idx": 13333, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
execute-api.${AWS::Region}.amazonaws.com/Prod/sql_statement/"
  RedshiftMiddlewareFunction:
    Description: "SQL Statement Lambda Function ARN"
    Value: !GetAtt RedshiftMiddlewareFunction.Arn
  RedshiftMiddlewareFunctionIamRole:
    Description: "Implicit IAM Role created for SQL Statement function"
    Value: !GetAtt RedshiftMiddlewareFunctionRole.Arn
  CognitoUserPoolArn:
    Description: "ARN of the Cognito User Pool"
    Value: !GetAtt MyCognitoUserPool.Arn

```

Retrieve the URL information from the previous command output, you can then run a cURL request, which should return data in a file format:


```python
curl -X POST https://<your_url>/Prod/sql_statement/ \
-H "Content-Type: application/json" \
-d '{ "sql_statement": "SELECT * FROM customers LIMIT 10", "workgroup_name": "default-workgroup", "database_name": "pap-db" }'
```

## ChatGPT Steps

### Custom GPT Instructions 

Once you've created a Custom GPT, copy the text below in the Instructions panel.


```python
**Context**: You are an expert at writing Redshift SQL queries. You will initially retrieve the table schema that you will use thoroughly. Every attributes, table names or data type will be known by you.

**Instructions**:
1. No matter the user's question, start by running `runQuery` operation using this query: "SELECT table_name, column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = 'public' ORDER BY table_name, ordinal_position;"  It will help you understand how to query the data. A CSV will be returned with all the attributes and their table. Make sure to read it fully and understand all available tables & their attributes before querying. You don't have to show this to the user.
2. Convert the user's question into a SQL statement that leverages the step above and run the `runQuery` operation on that SQL statement to confirm the query works. Let the user know which table you will use/query.
3. Execute the query and show him the data. Show only the first few rows.

**Additional Notes**: If the user says "Let's get started", explain they can ask a question they want answered about data that we have access to. If the user has no ideas, suggest that we have transactions data they can query - ask if they want you to query that.
**Important**: Never make up a table name or table attribute. If you don't know, go back to the data you've retrieved to check what is available. If you think no table or attribute is available, then tell the user you can't perform this query for them.
```

### OpenAPI Schema 

Once you've created a Custom GPT, copy the text below in the Actions panel.

This expects a response that matches the file retrieval structure in our doc [here](https://platform.openai.com/docs/actions/sending-files) and passes in a `query` as a parameter to execute.

Make sure to follow the steps in the [AWS Middleware cookbook](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_aws_function) to set up authentication.

> Make sure to switch the function app name based on your function deployment.


key: _node_content
string_value:
{"id_": "fef4760b-47fa-46d9-bc4f-898ab3c0155d", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b59e8cf1-6103-4849-8c27-8fa6c32e3559", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f62fa967f68bc5241a086fbaa9f3d46980603c7b1353007b2671a89a11a46c3d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "6ecc472c-0f4e-4f2a-a1ac-30b0c9a195b6", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_redshift.ipynb", "title": "GPT Action Library: AWS RedShift", "tokens": 3481, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "8b6d4b3381c257e67bd605366be2644c9190b0e0a134fa38a6ae96f1b45d6f7f", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 13336, "end_char_idx": 15784, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
openapi: 3.1.0
info:
  title: SQL Execution API
  description: API to execute SQL statements and return results as a file.
  version: 1.0.0
servers:
  - url: {your_function_url}/Prod
    description: Production server
paths:
  /sql_statement:
    post:
      operationId: executeSqlStatement
      summary: Executes a SQL statement and returns the result as a file.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                sql_statement:
                  type: string
                  description: The SQL statement to execute.
                  example: SELECT * FROM customers LIMIT 10
              required:
                - sql_statement
      responses:
        '200':
          description: The SQL query result as a JSON file.
          content:
            application/json:
              schema:
                type: object
                properties:
                  openaiFileResponse:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: The name of the file.
                          example: query_result.json
                        mime_type:
                          type: string
                          description: The MIME type of the file.
                          example: application/json
                        content:
                          type: string
                          description: The base64 encoded content of the file.
                          format: byte
                          example: eyJrZXkiOiJ2YWx1ZSJ9
        '500':
          description: Error response
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Error message.
                    example: Database query failed error details

```

## Conclusion

You now have deployed a GPT that uses a middleware in AWS, in an authenticated manner, that's able to connect to Redsfhit. Users with access (that are in Cognito) can now query your databases to perform data analysis task:

![../../../images/redshift_gpt.png](../../../images/redshift_gpt.png)


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb


key: _node_content
string_value:
{"id_": "4f738aed-025e-4fa6-8a00-ae3c2d0575d6", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "88cf31ad-bc5b-4182-ac2d-46de4c92fcd0", "node_type": "1", "metadata": {}, "hash": "b6afc9f6eeff315579f086f30055e8e7d2391e2b89f79446e7e193156d033725", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 3570, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# GPT Action Library: Canvas LMS

## Introduction

This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information: 
- [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
- [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
- [Example of Buliding a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)

This particular GPT Action provides an overview of how to connect to [Canvas](https://www.instructure.com/canvas), a widely used LMS tool for course material, grading and general education purposes. 

### Value + Example Business Use Cases

**Value**: Users can now leverage ChatGPT's natural language capability to connect directly to Canvas

**Example Use Cases**:
- Query content from LMS 
- Build quizzes
- Create new modules
- Understand topics from assigned courses

## Application Information

### Application Key Links

Check out these links from the application before you get started:
- Application Website: https://canvas.instructure.com/login/canvas 
- Application API Documentation: https://canvas.instructure.com/doc/api/
 

### Application Prerequisites

Before you get started, make sure you go through the following steps in your application environment:
- Ensure you have the access and permissions in Canvas to create an approved integration with an Access Token for testing
- For OAuth connection see here : https://canvas.instructure.com/doc/api/file.oauth.html


![gptactions_canvaslms_approvedintegrations.png](../../../images/gptactions_canvaslms_approvedintegrations.png)


## ChatGPT Steps

### Custom GPT Instructions 

Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
**Context** : You are a helpful friendly university level course helper designed to search across canvas courses to help students and educators, this GPT is intended to help students and teachers understand course material, take quiz's and tests from information stored in canvas.  


**Instructions**
When asked to perform a task, use the available actions via the canvas.infrastructure.com API


You should be professional and verbose with answers, provide clear pedagogical experience for users. 


Offer assistance with tasks around summarizing course material, understanding module and quiz information. 


Ask for clarification when needed to ensure accuracy and completeness in fulfilling user requests. It should also respect user privacy and handle all data securely.


If a user uploads a file, help the user analyze the file before callin the canvas API.

```

### OpenAPI Schema 

Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
openapi: 3.1.0
info:
  title: Canvas LMS API
  description: >
    This is the API of the Canvas LMS, providing access to various resources such as accounts, courses, users,
    assignments, quizzes, files, and more.
  version: 1.0.0
servers:
  - url: https://canvas.instructure.com
    description: Canvas LMS Production Server
paths:
  /api/v1/accounts:
    get:
      summary: List accounts
      operationId:


key: _node_content
string_value:
{"id_": "88cf31ad-bc5b-4182-ac2d-46de4c92fcd0", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "4f738aed-025e-4fa6-8a00-ae3c2d0575d6", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "10cf94b47576347f64d56c44232b64edf9ce46fed0af52520aed0d082bc0c353", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "3019a95f-6601-4c8c-9c16-6a307106c457", "node_type": "1", "metadata": {}, "hash": "8f7ad2cf854720b6866d86498ff64a56dd6c3e402b58ce71053dafedfeb5d2ee", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 2015, "end_char_idx": 4439, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
**Context** : You are a helpful friendly university level course helper designed to search across canvas courses to help students and educators, this GPT is intended to help students and teachers understand course material, take quiz's and tests from information stored in canvas.  


**Instructions**
When asked to perform a task, use the available actions via the canvas.infrastructure.com API


You should be professional and verbose with answers, provide clear pedagogical experience for users. 


Offer assistance with tasks around summarizing course material, understanding module and quiz information. 


Ask for clarification when needed to ensure accuracy and completeness in fulfilling user requests. It should also respect user privacy and handle all data securely.


If a user uploads a file, help the user analyze the file before callin the canvas API.

```

### OpenAPI Schema 

Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
openapi: 3.1.0
info:
  title: Canvas LMS API
  description: >
    This is the API of the Canvas LMS, providing access to various resources such as accounts, courses, users,
    assignments, quizzes, files, and more.
  version: 1.0.0
servers:
  - url: https://canvas.instructure.com
    description: Canvas LMS Production Server
paths:
  /api/v1/accounts:
    get:
      summary: List accounts
      operationId: listAccounts
      responses:
        "200":
          description: A paginated list of accounts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Account"
  /api/v1/accounts/{account_id}:
    get:
      summary: Get a single account
      operationId: getAccount
      parameters:
        - name: account_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Account details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
  /api/v1/courses:
    get:
      summary: List courses
      operationId: listCourses
      responses:
        "200":
          description: A paginated list


key: _node_content
string_value:
{"id_": "3019a95f-6601-4c8c-9c16-6a307106c457", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "88cf31ad-bc5b-4182-ac2d-46de4c92fcd0", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b43e0b8d996cef17dab1ee449b055ceabb007417731b84763e52c5de5e1b8d6", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "a70cdc86-c711-4099-a10f-c989fd98d293", "node_type": "1", "metadata": {}, "hash": "1699ee8c932e1fe51530e65a952947fb6a694dd0432f874fffc4e8791dbfee18", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 3609, "end_char_idx": 5192, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
"200":
          description: A paginated list of accounts
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Account"
  /api/v1/accounts/{account_id}:
    get:
      summary: Get a single account
      operationId: getAccount
      parameters:
        - name: account_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Account details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Account"
  /api/v1/courses:
    get:
      summary: List courses
      operationId: listCourses
      responses:
        "200":
          description: A paginated list of courses
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Course"
  /api/v1/courses/{course_id}:
    get:
      summary: Get a single course
      operationId: getCourse
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Course details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Course"
  /api/v1/courses/{course_id}/assignments:
    get:
      summary: List assignments
      operationId: listAssignments
      parameters:


key: _node_content
string_value:
{"id_": "a70cdc86-c711-4099-a10f-c989fd98d293", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "3019a95f-6601-4c8c-9c16-6a307106c457", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "436e4270ccecc505e22f6c8841a73c79c7a223381a6c41201f33851454f26fba", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "c0dbc8da-3aa4-41b7-92bc-d52e0e0d4bd2", "node_type": "1", "metadata": {}, "hash": "b3c2541a0ef9224c7da301064ff21ea8ff287ea5a7ea1137202392841ee4fd08", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 4374, "end_char_idx": 5937, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
responses:
        "200":
          description: A paginated list of courses
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Course"
  /api/v1/courses/{course_id}:
    get:
      summary: Get a single course
      operationId: getCourse
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Course details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Course"
  /api/v1/courses/{course_id}/assignments:
    get:
      summary: List assignments
      operationId: listAssignments
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: A paginated list of assignments
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Assignment"
  /api/v1/courses/{course_id}/assignments/{assignment_id}:
    get:
      summary: Get a single assignment
      operationId: getAssignment
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
        - name: assignment_id
          in: path
          required: true
          schema:


key: _node_content
string_value:
{"id_": "c0dbc8da-3aa4-41b7-92bc-d52e0e0d4bd2", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "a70cdc86-c711-4099-a10f-c989fd98d293", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3186f5acb68c4617f1ccd286b5c7f67a3f89f12ba41e36e3cec32c0440ef9fb1", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "42116c30-f2de-448c-af3a-e80043b97072", "node_type": "1", "metadata": {}, "hash": "790eac1f0947e78ac163e910bfcfb0b6fdac4cee2bed9c05def4ec8dd03b0adc", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 5114, "end_char_idx": 6660, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
summary: List assignments
      operationId: listAssignments
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: A paginated list of assignments
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Assignment"
  /api/v1/courses/{course_id}/assignments/{assignment_id}:
    get:
      summary: Get a single assignment
      operationId: getAssignment
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
        - name: assignment_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Assignment details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Assignment"
  /api/v1/courses/{course_id}/quizzes:
    get:
      summary: List quizzes
      operationId: listQuizzes
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: A paginated list of quizzes
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Quiz"


key: _node_content
string_value:
{"id_": "42116c30-f2de-448c-af3a-e80043b97072", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c0dbc8da-3aa4-41b7-92bc-d52e0e0d4bd2", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "b937c411d0f4a7150a81aea303f311522809c060634982711993363aed077089", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "6b43381c-2af6-4e99-8940-7644a60bea70", "node_type": "1", "metadata": {}, "hash": "5f18597081ca8b34e0a30d0e79295c780a2603cc6f593e8f2d3fa23ed65d217b", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 5886, "end_char_idx": 7420, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Assignment details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Assignment"
  /api/v1/courses/{course_id}/quizzes:
    get:
      summary: List quizzes
      operationId: listQuizzes
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: A paginated list of quizzes
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Quiz"
  /api/v1/courses/{course_id}/quizzes/{quiz_id}:
    get:
      summary: Get a single quiz
      operationId: getQuiz
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
        - name: quiz_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Quiz details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Quiz"
  /api/v1/courses/{course_id}/students/{student_id}/grades:
     get:
       summary: List grades for a student
       operationId: listGrades
       parameters:
         - name: course_id
           in: path


key: _node_content
string_value:
{"id_": "6b43381c-2af6-4e99-8940-7644a60bea70", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "42116c30-f2de-448c-af3a-e80043b97072", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3aa2832d584b5c7691aefe074055f1b03b3268812721d57ba8c25f2453353bc6", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "141d3b8c-d3ab-4693-97df-990b39e36e6a", "node_type": "1", "metadata": {}, "hash": "c42e6bf7ec31646ea9b259c219f63ba525fbf4c7b208ed16c9f46010d34b7b01", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6602, "end_char_idx": 8132, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
items:
                  $ref: "#/components/schemas/Quiz"
  /api/v1/courses/{course_id}/quizzes/{quiz_id}:
    get:
      summary: Get a single quiz
      operationId: getQuiz
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
        - name: quiz_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "200":
          description: Quiz details
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Quiz"
  /api/v1/courses/{course_id}/students/{student_id}/grades:
     get:
       summary: List grades for a student
       operationId: listGrades
       parameters:
         - name: course_id
           in: path
           required: true
           schema:
             type: integer
         - name: student_id
           in: path
           required: true
           schema:
             type: integer
       responses:
         '200':
           description: A list of grades for the student
           content:
             application/json:
               schema:
                 type: array
                 items:
                   $ref: '#/components/schemas/Grade'
  /api/v1/courses/{course_id}/students/{student_id}/grades/{grade_id}:
    get:
      summary: Get a single grade
      operationId: getGrade
      parameters:
        - name: course_id
          in: path
          required: true
          schema:


key: _node_content
string_value:
{"id_": "141d3b8c-d3ab-4693-97df-990b39e36e6a", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "6b43381c-2af6-4e99-8940-7644a60bea70", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "447d1750e38d9bbc6c9992842569ac779a2f989a6eb43ea1f31851749f42556d", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "614ff657-0365-4d60-9872-84427ef92a48", "node_type": "1", "metadata": {}, "hash": "2f2dc3497a52a52e7e50ee32a030a4812df06ee8b5c284fa76a73dbe45f18401", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 7362, "end_char_idx": 8841, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
parameters:
         - name: course_id
           in: path
           required: true
           schema:
             type: integer
         - name: student_id
           in: path
           required: true
           schema:
             type: integer
       responses:
         '200':
           description: A list of grades for the student
           content:
             application/json:
               schema:
                 type: array
                 items:
                   $ref: '#/components/schemas/Grade'
  /api/v1/courses/{course_id}/students/{student_id}/grades/{grade_id}:
    get:
      summary: Get a single grade
      operationId: getGrade
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
        - name: student_id
          in: path
          required: true
          schema:
            type: integer
        - name: grade_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Grade details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Grade'
  /api/v1/courses/{course_id}/syllabus:
    get:
      summary: Get course syllabus
      operationId: getSyllabus
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:


key: _node_content
string_value:
{"id_": "614ff657-0365-4d60-9872-84427ef92a48", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "141d3b8c-d3ab-4693-97df-990b39e36e6a", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "27112ca91eca67f2178e0f44dd5c83fa280017323df36368c73b09c18f1b8e8d", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "9f44eb5e-d3eb-4ddd-9773-d71f9c4cc3fb", "node_type": "1", "metadata": {}, "hash": "561056e86e60a6c03b05bba153f73c7d09d4420a9391f0470f17d4aaac50c65e", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 8081, "end_char_idx": 9598, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
in: path
          required: true
          schema:
            type: integer
        - name: student_id
          in: path
          required: true
          schema:
            type: integer
        - name: grade_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Grade details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Grade'
  /api/v1/courses/{course_id}/syllabus:
    get:
      summary: Get course syllabus
      operationId: getSyllabus
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Syllabus details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Syllabus'
  /api/v1/courses/{course_id}/modules:
    get:
      summary: List modules
      operationId: listModules
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: A list of modules in the course
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Module'
  /api/v1/courses/{course_id}/modules/{module_id}:
    get:
      summary:


key: _node_content
string_value:
{"id_": "9f44eb5e-d3eb-4ddd-9773-d71f9c4cc3fb", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "614ff657-0365-4d60-9872-84427ef92a48", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "b358736bac8478c69045d7016d757fecb835fc0827a72fe014b28dcd2e0ba45c", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "ab4cb8b8-9b6c-4dd6-b5b4-ece3c0579bba", "node_type": "1", "metadata": {}, "hash": "f2bb1445c10a451995847b2ccdededf8b2f175ef358a10d3b69ba52d6287118f", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 8791, "end_char_idx": 10328, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
schema:
            type: integer
      responses:
        '200':
          description: Syllabus details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Syllabus'
  /api/v1/courses/{course_id}/modules:
    get:
      summary: List modules
      operationId: listModules
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: A list of modules in the course
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Module'
  /api/v1/courses/{course_id}/modules/{module_id}:
    get:
      summary: Get a single module
      operationId: getModule
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
        - name: module_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Module details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Module'
components:
  schemas:
    Account:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        workflow_state:
          type: string
    Course:
      type: object
      properties:


key: _node_content
string_value:
{"id_": "ab4cb8b8-9b6c-4dd6-b5b4-ece3c0579bba", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "9f44eb5e-d3eb-4ddd-9773-d71f9c4cc3fb", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "c0c8608d21bf8ed70b57517b2cbb27bc8226501c3a4c3497592c8b3ea5e0ebb5", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "c961d00e-4009-4649-9b7e-e3b2f44162ab", "node_type": "1", "metadata": {}, "hash": "b132c387a92272479eab6c7f1c75eb108e93eb746b43fefc7bf16d26788f38b3", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 9526, "end_char_idx": 11031, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
/api/v1/courses/{course_id}/modules/{module_id}:
    get:
      summary: Get a single module
      operationId: getModule
      parameters:
        - name: course_id
          in: path
          required: true
          schema:
            type: integer
        - name: module_id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: Module details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Module'
components:
  schemas:
    Account:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        workflow_state:
          type: string
    Course:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        account_id:
          type: integer
        start_at:
          type: string
          format: date-time
        end_at:
          type: string
          format: date-time
    Assignment:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
        due_at:
          type: string
          format: date-time
        points_possible:
          type: number
    Quiz:
      type: object
      properties:
        id:
          type: integer
        title:
          type: string
        description:
          type: string


key: _node_content
string_value:
{"id_": "c961d00e-4009-4649-9b7e-e3b2f44162ab", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "ab4cb8b8-9b6c-4dd6-b5b4-ece3c0579bba", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "74805180a66c6cdf4c8945d27369cf41515b51b2b784797b6eb6f972ae2b8e56", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "537c40c7-4993-4edc-aa34-00990e4562f1", "node_type": "1", "metadata": {}, "hash": "9649608b95afbb434245406dc0aead34f2a4919f0932d85f31b52e772309efe0", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 10267, "end_char_idx": 11716, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
type: string
    Course:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        account_id:
          type: integer
        start_at:
          type: string
          format: date-time
        end_at:
          type: string
          format: date-time
    Assignment:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        description:
          type: string
        due_at:
          type: string
          format: date-time
        points_possible:
          type: number
    Quiz:
      type: object
      properties:
        id:
          type: integer
        title:
          type: string
        description:
          type: string
        due_at:
          type: string
          format: date-time
        points_possible:
          type: number
    Grade:
      type: object
      properties:
        id:
          type: integer
        student_id:
          type: integer
        course_id:
          type: integer
        assignment_id:
          type: integer
        score:
          type: number
        grade:
          type: string
    Syllabus:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        account_id:
          type: integer
        start_at:
          type: string
          format: date-time
        end_at:
          type: string


key: _node_content
string_value:
{"id_": "537c40c7-4993-4edc-aa34-00990e4562f1", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c961d00e-4009-4649-9b7e-e3b2f44162ab", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "2b3c83b4f803e41437030e2a288e3066ac2b82a31e72ead76753f0349fccdcbc", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f8027f8f-2e01-4190-90a5-bb9a7d1c3761", "node_type": "1", "metadata": {}, "hash": "a77bb54a3415cc72a6dd24888762b5e467f066b99f5327e7671df294d6cd2d03", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 10975, "end_char_idx": 12764, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
type: string
        description:
          type: string
        due_at:
          type: string
          format: date-time
        points_possible:
          type: number
    Grade:
      type: object
      properties:
        id:
          type: integer
        student_id:
          type: integer
        course_id:
          type: integer
        assignment_id:
          type: integer
        score:
          type: number
        grade:
          type: string
    Syllabus:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        account_id:
          type: integer
        start_at:
          type: string
          format: date-time
        end_at:
          type: string
          format: date-time
        syllabus_body:
          type: string
        syllabus_url:
          type: string
    Module:
     type: object
     properties:
       id:
         type: integer
       name:
         type: string
       position:
         type: integer
       unlock_at:
         type: string
         format: date-time
       require_sequential_progress:
         type: boolean
       state:
         type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
security:
  - bearerAuth: []
```

**Note : this schema above does not contain all possible API endpoints, be sure to edit the schema to produce the appropriate actions from canvas [API documentation](https://canvas.instructure.com/doc/api/)**

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


key: _node_content
string_value:
{"id_": "f8027f8f-2e01-4190-90a5-bb9a7d1c3761", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "537c40c7-4993-4edc-aa34-00990e4562f1", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "1414c94279f21a64235fe2ce6fe394c68b5ac2a7e23d0262d24e0f6b660f7823", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "7d07c0c3-e68d-48ae-ba48-1245587541e9", "node_type": "1", "metadata": {}, "hash": "982d739678175bf3b3244fa608fced3f3b7ecd5bb022e9753f1a07380dc0c44a", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 11660, "end_char_idx": 14068, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
format: date-time
        end_at:
          type: string
          format: date-time
        syllabus_body:
          type: string
        syllabus_url:
          type: string
    Module:
     type: object
     properties:
       id:
         type: integer
       name:
         type: string
       position:
         type: integer
       unlock_at:
         type: string
         format: date-time
       require_sequential_progress:
         type: boolean
       state:
         type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
security:
  - bearerAuth: []
```

**Note : this schema above does not contain all possible API endpoints, be sure to edit the schema to produce the appropriate actions from canvas [API documentation](https://canvas.instructure.com/doc/api/)**

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

### Pre-Action Steps

Before you set up authentication in ChatGPT, please take the following steps in the application. Our sample integration below is utilizing a secret key, which is an easier method for testing. In production, it is more common to establish an OAuth connection to ensure permissions are respected from ChatGPT to Canvas, ensuring users the appropriate access. 

1. Canvas accounts : The first step is to ensure the canvas environment has users assigned to the appropriate role (student / teacher) with any access to appropriate courses
2. For testing purposes or service level account access create an approved integration access token as seen below
- Under Account -> Settings -> Approved Integrations

<br> ![gptactions_canvaslms_settings.png](../../../images/gptactions_canvaslms_settings.png)

- Create new Access Token

<br> ![gptactions_canvaslms_integrationslist.png](../../../images/gptactions_canvaslms_integrationslist.png)

- Provide purpose and expiration

<br> ![gptactions_canvaslms_tokencreate.png](../../../images/gptactions_canvaslms_tokencreate.png)

- Copy the new Token to use in the GPT Action (the token will not be accessible once you leave the page - ensure proper token management access is maintained to prevent unauthorzied access from another application.


key: _node_content
string_value:
{"id_": "7d07c0c3-e68d-48ae-ba48-1245587541e9", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "b855db84-51ad-43d4-9f4f-eb9bbd7b340b", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94c0725c1d416af6c12c1420e12861595a263bf4f35c0fce50278483aa102078", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "f8027f8f-2e01-4190-90a5-bb9a7d1c3761", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_canvaslms.ipynb", "title": "GPT Action Library: Canvas LMS", "tokens": 3428, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "dcda8d551b693d67f821c659f4fd07b25076d6bff21e8c7a306bdc266cdc1340", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 12212, "end_char_idx": 16088, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
scheme: bearer
      bearerFormat: JWT
security:
  - bearerAuth: []
```

**Note : this schema above does not contain all possible API endpoints, be sure to edit the schema to produce the appropriate actions from canvas [API documentation](https://canvas.instructure.com/doc/api/)**

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

### Pre-Action Steps

Before you set up authentication in ChatGPT, please take the following steps in the application. Our sample integration below is utilizing a secret key, which is an easier method for testing. In production, it is more common to establish an OAuth connection to ensure permissions are respected from ChatGPT to Canvas, ensuring users the appropriate access. 

1. Canvas accounts : The first step is to ensure the canvas environment has users assigned to the appropriate role (student / teacher) with any access to appropriate courses
2. For testing purposes or service level account access create an approved integration access token as seen below
- Under Account -> Settings -> Approved Integrations

<br> ![gptactions_canvaslms_settings.png](../../../images/gptactions_canvaslms_settings.png)

- Create new Access Token

<br> ![gptactions_canvaslms_integrationslist.png](../../../images/gptactions_canvaslms_integrationslist.png)

- Provide purpose and expiration

<br> ![gptactions_canvaslms_tokencreate.png](../../../images/gptactions_canvaslms_tokencreate.png)

- Copy the new Token to use in the GPT Action (the token will not be accessible once you leave the page - ensure proper token management access is maintained to prevent unauthorzied access from another application.


### In ChatGPT

In ChatGPT, click on "Authentication" and choose **"API Key"**. Enter in the information below. API Key provides general access to the Canvas environment based on the users permissions that created the API key, to follow permission models in Canvas use the OAuth method described below.

- **API Key**: Use the token from above 
- **Auth Type**: Bearer

<br> ![gptactions_canvaslms_auth.png](../../../images/gptactions_canvaslms_auth.png)

**OAuth Connection**

If you want to implement OAuth, follow the guide here : https://canvas.instructure.com/doc/api/file.oauth.html - specific instructions can vary depending on the Canvas implementation.

Parameters for GPT Configuration
- Client ID - obtained from site owner
- Client Secret - obtained from site owner 
- Authorization URL - : https://< canvas-install-url >/login/oauth2/auth?client_id=XXX&response_type=code&redirect_uri=https://example.com/oauth_complete&state=YYY&scope=< value_1 >%20< value_2 >%20< value_n >
- Token URL : https://< canvas-install-url> /login/oauth2/token 

### Post-Action Steps

Once you've set up authentication in ChatGPT, follow the steps below in the application to test the Action.

- You will see a list of available actions from the API schema for Canvas, you can test the endpoints from the GPT builder to ensure Canvas can be reached. Once you verified connection make sure to save the GPT and share it witht the appropriate user base.
- Note: if you are using OAuth, you will need to set up the callback URL from ChatGPT in the Canvas app

### FAQ & Troubleshooting

- *Schema calls the wrong project or dataset:* If ChatGPT calls the wrong project or dataset, consider updating your instructions to make it more explicit either (a) which project / dataset should be called or (b) to require the user provide those exact details before it runs the query

*Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look.*


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb


key: _node_content
string_value:
{"id_": "eab4176c-2b1d-4e99-9d53-e6a95141b933", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "fb405a77-6611-4a8f-b5a3-959aebfc53d4", "node_type": "1", "metadata": {}, "hash": "b1743cde07531228ca3df86446128c21cfe847f913ca8737e8393982bc299e27", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 3504, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# **GPT Action Library: Google Drive**


## **Introduction**

This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information:


* [Introduction to GPT Actions](https://platform.openai.com/docs/actions/introduction)
* [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
* [Example of Building a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)

This particular GPT Action provides an overview of how to connect to **Google Drive**, Google’s File storage system. This action will allow you to list and query against file names, load the file content into your GPT, and ultimately use that data as context in ChatGPT.  This set of actions is extensible by additional methods found via the [Google Drive API](https://developers.google.com/drive/api/guides/about-sdk).  This is great if you want a generalist GPT that can read smaller files, such as: 


* Meetings minutes
* Product design documents
* Short memos
* Frequently-asked questions

For something that wants to read longer memos such as entire books, complex CSVs with many rows, we suggest building a Google Docs or Google Sheets-specific GPT.

### Value + Example business case

Users can now leverage ChatGPT's natural language capability to connect directly to files in Google Drive

Example Use Cases:

- A user needs to look up which files relate to a certain topic
- A user needs an answer to a critical question, buried deep in documents


## **Application Information**


### **Application Key Links**

Check out these links from the application before you get started:


* Application Website: [https://www.google.com/drive/](https://www.google.com/drive/)
* Application API Documentation: [https://developers.google.com/drive/api/guides/about-sdk](https://developers.google.com/drive/api/guides/about-sdk)


### **Application Prerequisites**

Before you get started, make sure you have a Google Cloud account and that the Drive API is enabled:



* Set up a Google Cloud project
* Enable Google Drive API from Google API Library
* If application’s  “Publishing Status” is “Testing”, ensure users are added to your application


## **ChatGPT Steps**


### **Example Custom GPT Instructions**

Once you've created a Custom GPT, to get started, copy the text below in the Instructions panel. You may have to add additional context specific to your use case.  In this way, it is worth testing additional instructions you add to optimize for clarity and accuracy. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.



```python
*** Context *** 

You are an office helper who takes a look at files within Google Drive and reads in information.  In this way, when asked about something, please take a look at all of the relevant information within the drive.  Respect file names, but also take a look at each document and sheet.

*** Instructions ***

Use the 'listFiles' function to get a list of files available within docs.  In this way, determine out of this list which files make the most sense for you to pull back taking into account name and title.  After the output of listFiles is called into context, act like a normal business analyst.  Things you could be asked to be are:

- Summaries: what happens in a given file?


key: _node_content
string_value:
{"id_": "fb405a77-6611-4a8f-b5a3-959aebfc53d4", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "eab4176c-2b1d-4e99-9d53-e6a95141b933", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "0d9ca6e8af91e6131c763b578e9f89e8512a92cc86ceb00da811183cde8fa68c", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "ec475a25-73be-46b9-97ef-8dc00395395d", "node_type": "1", "metadata": {}, "hash": "4854a6b6bbd38addc675a063b35765db7c06b647a353791d9dc2d431f338cd49", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 1750, "end_char_idx": 5161, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
* Application Website: [https://www.google.com/drive/](https://www.google.com/drive/)
* Application API Documentation: [https://developers.google.com/drive/api/guides/about-sdk](https://developers.google.com/drive/api/guides/about-sdk)


### **Application Prerequisites**

Before you get started, make sure you have a Google Cloud account and that the Drive API is enabled:



* Set up a Google Cloud project
* Enable Google Drive API from Google API Library
* If application’s  “Publishing Status” is “Testing”, ensure users are added to your application


## **ChatGPT Steps**


### **Example Custom GPT Instructions**

Once you've created a Custom GPT, to get started, copy the text below in the Instructions panel. You may have to add additional context specific to your use case.  In this way, it is worth testing additional instructions you add to optimize for clarity and accuracy. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.



```python
*** Context *** 

You are an office helper who takes a look at files within Google Drive and reads in information.  In this way, when asked about something, please take a look at all of the relevant information within the drive.  Respect file names, but also take a look at each document and sheet.

*** Instructions ***

Use the 'listFiles' function to get a list of files available within docs.  In this way, determine out of this list which files make the most sense for you to pull back taking into account name and title.  After the output of listFiles is called into context, act like a normal business analyst.  Things you could be asked to be are:

- Summaries: what happens in a given file?  Please give a consistent, concise answer and read through the entire file before giving an answer.
- Professionalism: Behave professionally, providing clear and concise responses.
- Synthesis, Coding, and Data Analysis: ensure coding blocks are explained.
- When handling dates: make sure that dates are searched using date fields and also if you don't find anything, use titles.
- Clarification: Ask for clarification when needed to ensure accuracy and completeness in fulfilling user requests.  Try to make sure you know exactly what is being asked. 
- Privacy and Security: Respect user privacy and handle all data securely.

*** Examples of Documentation ***
Here is the relevant query documentation from Google for the listFiles function:
What you want to query	Example
Files with the name "hello"	name = 'hello'
Files with a name containing the words "hello" and "goodbye"	name contains 'hello' and name contains 'goodbye'
Files with a name that does not contain the word "hello"	not name contains 'hello'
Folders that are Google apps or have the folder MIME type	mimeType = 'application/vnd.google-apps.folder'
Files that are not folders	mimeType != 'application/vnd.google-apps.folder'
Files that contain the text "important" and in the trash	fullText contains 'important' and trashed = true
Files that contain the word "hello"	fullText contains 'hello'
Files that do not have the word "hello"	not fullText contains 'hello'
Files that contain the exact phrase "hello world"	fullText contains '"hello world"'
Files with a query that contains the "\" character (e.g., "\authors")	fullText contains '\\authors'
Files with ID within a collection, e.g.


key: _node_content
string_value:
{"id_": "ec475a25-73be-46b9-97ef-8dc00395395d", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "fb405a77-6611-4a8f-b5a3-959aebfc53d4", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e58d0746618966b5fefc0cedfc1796d837d766480618af4e89061d8d4b0f07de", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "5b034ae1-efa0-4677-b495-ee5a1c7d4f90", "node_type": "1", "metadata": {}, "hash": "064258fd1e74e3c1bbec3c6cefec6f9627eeb7620687e7fc9b6b43a895cf100f", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 3333, "end_char_idx": 6449, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
After the output of listFiles is called into context, act like a normal business analyst.  Things you could be asked to be are:

- Summaries: what happens in a given file?  Please give a consistent, concise answer and read through the entire file before giving an answer.
- Professionalism: Behave professionally, providing clear and concise responses.
- Synthesis, Coding, and Data Analysis: ensure coding blocks are explained.
- When handling dates: make sure that dates are searched using date fields and also if you don't find anything, use titles.
- Clarification: Ask for clarification when needed to ensure accuracy and completeness in fulfilling user requests.  Try to make sure you know exactly what is being asked. 
- Privacy and Security: Respect user privacy and handle all data securely.

*** Examples of Documentation ***
Here is the relevant query documentation from Google for the listFiles function:
What you want to query	Example
Files with the name "hello"	name = 'hello'
Files with a name containing the words "hello" and "goodbye"	name contains 'hello' and name contains 'goodbye'
Files with a name that does not contain the word "hello"	not name contains 'hello'
Folders that are Google apps or have the folder MIME type	mimeType = 'application/vnd.google-apps.folder'
Files that are not folders	mimeType != 'application/vnd.google-apps.folder'
Files that contain the text "important" and in the trash	fullText contains 'important' and trashed = true
Files that contain the word "hello"	fullText contains 'hello'
Files that do not have the word "hello"	not fullText contains 'hello'
Files that contain the exact phrase "hello world"	fullText contains '"hello world"'
Files with a query that contains the "\" character (e.g., "\authors")	fullText contains '\\authors'
Files with ID within a collection, e.g. parents collection	'1234567' in parents
Files in an application data folder in a collection	'appDataFolder' in parents
Files for which user "test@example.org" has write permission	'test@example.org' in writers
Files for which members of the group "group@example.org" have write permission	'group@example.org' in writers
Files modified after a given date	modifiedTime > '2012-06-04T12:00:00' // default time zone is UTC
Files shared with the authorized user with "hello" in the name	sharedWithMe and name contains 'hello'
Files that have not been shared with anyone or domains (only private, or shared with specific users or groups)	visibility = 'limited'
Image or video files modified after a specific date	modifiedTime > '2012-06-04T12:00:00' and (mimeType contains 'image/' or mimeType contains 'video/')

```

### **Example OpenAPI Schema**

Once you've created a Custom GPT, copy the text below in the Actions panel.  This offers an example of what you could include within functions, but . Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/getting-started) to see how this step works in more detail.  As well, try [ActionsGPT](https://chatgpt.com/g/g-TYEliDU6A-actionsgpt), a CustomGPT OpenAI created to help with Actions.  The three examples are:


key: _node_content
string_value:
{"id_": "5b034ae1-efa0-4677-b495-ee5a1c7d4f90", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "ec475a25-73be-46b9-97ef-8dc00395395d", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "c6cec0fc67019293d4329b6cea0b04a57f8cb5c76e97e787eb6f53b1b1173d10", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "160f040d-802e-4c86-ad57-c1204590253f", "node_type": "1", "metadata": {}, "hash": "ccc0d11bd466e53588d2216578a708cd9f5b8ad0b5f149899e087339eb300afb", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 5162, "end_char_idx": 8068, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
parents collection	'1234567' in parents
Files in an application data folder in a collection	'appDataFolder' in parents
Files for which user "test@example.org" has write permission	'test@example.org' in writers
Files for which members of the group "group@example.org" have write permission	'group@example.org' in writers
Files modified after a given date	modifiedTime > '2012-06-04T12:00:00' // default time zone is UTC
Files shared with the authorized user with "hello" in the name	sharedWithMe and name contains 'hello'
Files that have not been shared with anyone or domains (only private, or shared with specific users or groups)	visibility = 'limited'
Image or video files modified after a specific date	modifiedTime > '2012-06-04T12:00:00' and (mimeType contains 'image/' or mimeType contains 'video/')

```

### **Example OpenAPI Schema**

Once you've created a Custom GPT, copy the text below in the Actions panel.  This offers an example of what you could include within functions, but . Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/getting-started) to see how this step works in more detail.  As well, try [ActionsGPT](https://chatgpt.com/g/g-TYEliDU6A-actionsgpt), a CustomGPT OpenAI created to help with Actions.  The three examples are:


* **List Files**: this is the core action that lists the files in your drive.  Within this are a few parameters, such as `q`, `includeItemsFromAllDrives,supportsAllDrives`
* **Get Metadata**: in case list doesn't work, this can offer as a backup based on certain results - for example, if users attempt to make a search via “meeting from last week”, etc 
* **Export**: exports in a byte content.  For more reading, please consult [https://developers.google.com/drive/api/reference/rest/v3/files/export](https://developers.google.com/drive/api/reference/rest/v3/files/export)

Generally, if ‘get’ is used, the model will attempt to download the file, which may be undesirable. Thus, Export is recommended instead.




```python

{
  "openapi": "3.1.0",
  "info": {
    "title": "Google Drive API",
    "description": "API for interacting with Google Drive",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://www.googleapis.com/drive/v3"
    }
  ],
  "paths": {
    "/files": {
      "get": {
        "operationId": "ListFiles",
        "summary": "List files",
        "description": "Retrieve a list of files in the user's Google Drive.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Query string for searching files.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeItemsFromAllDrives",
            "in": "query",
            "description": "Whether both My Drive and shared drive items should be included in results.


key: _node_content
string_value:
{"id_": "160f040d-802e-4c86-ad57-c1204590253f", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "5b034ae1-efa0-4677-b495-ee5a1c7d4f90", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "a117de977b758b70f8c33379eaaef57b9c1dc9667bdccad0f5c32f9b880b0e72", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "de974e36-d18f-4e89-9def-6ff8c1a99216", "node_type": "1", "metadata": {}, "hash": "ae15a92928bcadc4f7ffe41af29a8591f3422e88b56c3e31cdb65c3cd009738a", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6426, "end_char_idx": 9858, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
The three examples are:


* **List Files**: this is the core action that lists the files in your drive.  Within this are a few parameters, such as `q`, `includeItemsFromAllDrives,supportsAllDrives`
* **Get Metadata**: in case list doesn't work, this can offer as a backup based on certain results - for example, if users attempt to make a search via “meeting from last week”, etc 
* **Export**: exports in a byte content.  For more reading, please consult [https://developers.google.com/drive/api/reference/rest/v3/files/export](https://developers.google.com/drive/api/reference/rest/v3/files/export)

Generally, if ‘get’ is used, the model will attempt to download the file, which may be undesirable. Thus, Export is recommended instead.




```python

{
  "openapi": "3.1.0",
  "info": {
    "title": "Google Drive API",
    "description": "API for interacting with Google Drive",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://www.googleapis.com/drive/v3"
    }
  ],
  "paths": {
    "/files": {
      "get": {
        "operationId": "ListFiles",
        "summary": "List files",
        "description": "Retrieve a list of files in the user's Google Drive.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "Query string for searching files.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeItemsFromAllDrives",
            "in": "query",
            "description": "Whether both My Drive and shared drive items should be included in results.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "supportsAllDrives",
            "in": "query",
            "description": "Whether the requesting application supports both My Drives and shared drives.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Maximum number of files to return.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 10
            }
          },
          {
            "name": "pageToken",
            "in": "query",
            "description": "Token for continuing a previous list request.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Comma-separated list of fields to include in the response.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A list of files.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "kind": {
                      "type": "string",
                      "example": "drive#fileList"
                    },
                    "nextPageToken": {
                      "type": "string",
                      "description": "Token to retrieve the next page of results."


key: _node_content
string_value:
{"id_": "de974e36-d18f-4e89-9def-6ff8c1a99216", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "160f040d-802e-4c86-ad57-c1204590253f", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "a48a8b93b7718b96bcd70e27d965db3bd74d52b80e317baaca2f656a56b64424", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "c2746d77-15e1-4677-9690-8b5871ad167e", "node_type": "1", "metadata": {}, "hash": "16f49f2ec67bd5fefd0e342a728eed99be7e72c7458311081d8645c134f98d4c", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 8068, "end_char_idx": 11392, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "supportsAllDrives",
            "in": "query",
            "description": "Whether the requesting application supports both My Drives and shared drives.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Maximum number of files to return.",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 10
            }
          },
          {
            "name": "pageToken",
            "in": "query",
            "description": "Token for continuing a previous list request.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Comma-separated list of fields to include in the response.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A list of files.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "kind": {
                      "type": "string",
                      "example": "drive#fileList"
                    },
                    "nextPageToken": {
                      "type": "string",
                      "description": "Token to retrieve the next page of results."
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/files/{fileId}": {
      "get": {
        "operationId": "getMetadata",
        "summary": "Get file metadata",
        "description": "Retrieve metadata for a specific file.",
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "description": "ID of the file to retrieve.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Comma-separated list of fields to include in the response.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Metadata of the file.


key: _node_content
string_value:
{"id_": "c2746d77-15e1-4677-9690-8b5871ad167e", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "de974e36-d18f-4e89-9def-6ff8c1a99216", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "dc320d9b5d511ac4c1c34dbfdad7500aefd3a71f12b738248b8fce09c8037caf", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "964a937e-720e-41bf-abaf-1acb7fba672f", "node_type": "1", "metadata": {}, "hash": "e51a256222a5688818a7b626e58e3785decc9affb848ed1e970b2626830cef59", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 9392, "end_char_idx": 13178, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "kind": {
                      "type": "string",
                      "example": "drive#fileList"
                    },
                    "nextPageToken": {
                      "type": "string",
                      "description": "Token to retrieve the next page of results."
                    },
                    "files": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/files/{fileId}": {
      "get": {
        "operationId": "getMetadata",
        "summary": "Get file metadata",
        "description": "Retrieve metadata for a specific file.",
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "description": "ID of the file to retrieve.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fields",
            "in": "query",
            "description": "Comma-separated list of fields to include in the response.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Metadata of the file.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "mimeType": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "createdTime": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/files/{fileId}/export": {
      "get": {
        "operationId": "export",
        "summary": "Export a file",
        "description": "Export a Google Doc to the requested MIME type.",
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "description": "ID of the file to export.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mimeType",
            "in": "query",
            "description": "The MIME type of the format to export to.",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/pdf",
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                "text/plain"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The exported file.


key: _node_content
string_value:
{"id_": "964a937e-720e-41bf-abaf-1acb7fba672f", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c2746d77-15e1-4677-9690-8b5871ad167e", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "9799203d54dfdb24f12bfc6b52c982623176fe90e6a0988566216c93bfb9d25a", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "5c957989-0f62-4775-9fc7-415a8612dfc6", "node_type": "1", "metadata": {}, "hash": "96311f5a307109484e21b27d39528032a939c2b2ed7797036f785490d48b9153", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 11175, "end_char_idx": 14945, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Metadata of the file.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "mimeType": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "createdTime": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/files/{fileId}/export": {
      "get": {
        "operationId": "export",
        "summary": "Export a file",
        "description": "Export a Google Doc to the requested MIME type.",
        "parameters": [
          {
            "name": "fileId",
            "in": "path",
            "description": "ID of the file to export.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mimeType",
            "in": "query",
            "description": "The MIME type of the format to export to.",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "application/pdf",
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                "text/plain"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The exported file.",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid MIME type or file ID."
          },
          "404": {
            "description": "File not found."
          }
        }
      }
    }
  }
}
```

## **Authentication Instructions**

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


### **Pre-Action Steps**

Before you set up authentication in ChatGPT, please take the following steps in the application.



* Go to the Google Cloud Console
* Navigate to Enabled API & Services and enable Google Drive API 


![alt_text](../../../images/gptactions_gd_api_services_pin.png "api_and_services")

![alt_text](../../../images/gptactions_gd_nav_to_enabled_api.png "api_lib")


* Within the search bar, search Google Drive API:

![alt_text](../../../images/gptactions_gd_search_google_drive_api.png "gpt_actions")


* Create new OAuth credentials (or use an existing one).  Note that if you haven’t set up an OAuth credentials screen, you will need to do that.


key: _node_content
string_value:
{"id_": "5c957989-0f62-4775-9fc7-415a8612dfc6", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "964a937e-720e-41bf-abaf-1acb7fba672f", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "1856076344f9611277b72d36dfd80a2255bd2c5e3aa0907a98820b67992eeef8", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "b87b48d5-f87f-4444-b8db-3fe3a22e5912", "node_type": "1", "metadata": {}, "hash": "01278a3075e0a001bc4859e984d6cf426d50d3b87dbbca0085a1b626a2169fd4", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 13178, "end_char_idx": 16641, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/vnd.openxmlformats-officedocument.wordprocessingml.document": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Invalid MIME type or file ID."
          },
          "404": {
            "description": "File not found."
          }
        }
      }
    }
  }
}
```

## **Authentication Instructions**

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


### **Pre-Action Steps**

Before you set up authentication in ChatGPT, please take the following steps in the application.



* Go to the Google Cloud Console
* Navigate to Enabled API & Services and enable Google Drive API 


![alt_text](../../../images/gptactions_gd_api_services_pin.png "api_and_services")

![alt_text](../../../images/gptactions_gd_nav_to_enabled_api.png "api_lib")


* Within the search bar, search Google Drive API:

![alt_text](../../../images/gptactions_gd_search_google_drive_api.png "gpt_actions")


* Create new OAuth credentials (or use an existing one).  Note that if you haven’t set up an OAuth credentials screen, you will need to do that.


![alt_text](../../../images/gptactions_gd_oauth_consent_screen.png "oauth_consent")




* Within this process, you will need to grant access to the correct permissions, establish the primary tester as a testing email if Testing is enabled, and set up the OAuth rate limit.
* Next, go to credentials and click “+ Create Credentials” and click “Create Credentials”.  Below is an example of what this screen looks like when it’s already set up.


![alt_text](../../../images/gptactions_gd_go_to_create_credentials.png "creds")




* Locate your OAuth Client ID & Client Secret and store both values securely (see screenshot below)



![alt_text](../../../images/gptactions_gd_oauthcid_and_csecret.png "id and secret")



### **In ChatGPT**

In ChatGPT, click on "Authentication" and choose **"OAuth"**. Enter in the information below.

* **Client ID**: use Client ID from steps above
* **Client Secret**: use Client Secret from steps above
* **Authorization URL**: [https://accounts.google.com/o/oauth2/auth](https://accounts.google.com/o/oauth2/auth)
* **Token URL**: [https://oauth2.googleapis.com/token](https://oauth2.googleapis.com/token)
* **Scope**: [https://www.googleapis.com/auth/drive](https://www.googleapis.com/auth/drive.readonly)
    * **Note**: for a list of more detailed scopes enabled, please refer to [Google’s OAuth 2.0 guide.](https://developers.google.com/identity/protocols/oauth2/scopes)
* **Token**: Default (POST)
* **Privacy Policy**: [https://policies.google.com/privacy?hl=en-US](https://policies.google.com/privacy?hl=en-US)


### **Post-Action Steps**

Once you've set up authentication in ChatGPT, follow the steps below in the application to finalize the Action.


key: _node_content
string_value:
{"id_": "b87b48d5-f87f-4444-b8db-3fe3a22e5912", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "55083893-05db-483d-a770-e73ba6436bde", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3b3da2445c3053f1309894f6d29a740434dd15d0925ded0cfce06c919140d5e6", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "5c957989-0f62-4775-9fc7-415a8612dfc6", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_google_drive.ipynb", "title": "**GPT Action Library: Google Drive**", "tokens": 3718, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f85e47f184ec05ddd0c3ee9e70eb65aa73595852c531c7a73d74b170683fe1cb", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 15036, "end_char_idx": 17471, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
* Within this process, you will need to grant access to the correct permissions, establish the primary tester as a testing email if Testing is enabled, and set up the OAuth rate limit.
* Next, go to credentials and click “+ Create Credentials” and click “Create Credentials”.  Below is an example of what this screen looks like when it’s already set up.


![alt_text](../../../images/gptactions_gd_go_to_create_credentials.png "creds")




* Locate your OAuth Client ID & Client Secret and store both values securely (see screenshot below)



![alt_text](../../../images/gptactions_gd_oauthcid_and_csecret.png "id and secret")



### **In ChatGPT**

In ChatGPT, click on "Authentication" and choose **"OAuth"**. Enter in the information below.

* **Client ID**: use Client ID from steps above
* **Client Secret**: use Client Secret from steps above
* **Authorization URL**: [https://accounts.google.com/o/oauth2/auth](https://accounts.google.com/o/oauth2/auth)
* **Token URL**: [https://oauth2.googleapis.com/token](https://oauth2.googleapis.com/token)
* **Scope**: [https://www.googleapis.com/auth/drive](https://www.googleapis.com/auth/drive.readonly)
    * **Note**: for a list of more detailed scopes enabled, please refer to [Google’s OAuth 2.0 guide.](https://developers.google.com/identity/protocols/oauth2/scopes)
* **Token**: Default (POST)
* **Privacy Policy**: [https://policies.google.com/privacy?hl=en-US](https://policies.google.com/privacy?hl=en-US)


### **Post-Action Steps**

Once you've set up authentication in ChatGPT, follow the steps below in the application to finalize the Action.



* Copy the callback URL from the GPT Action


![alt_text](../../../images/gptactions_gd_callbackurl_from_gpt_action.png "callback")




* In the “Authorized redirect URIs”, add your callback URL


![alt_text](../../../images/gptactions_gd_authorized_redirect_uris.png "image_tooltip")



### **FAQ & Troubleshooting**



* _Callback URL Error:_ If you get a callback URL error in ChatGPT, pay close attention to the screenshot above. You need to add the callback URL directly into GCP for the action to authenticate correctly.

_Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our GitHub, and we’ll take a look._




<!-- watermark --><div style="background-color:#FFFFFF"><p style="color:#FFFFFF; font-size: 1px">gd2md-html: xyzzy Mon Aug 12 2024</p></div>


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb


key: _node_content
string_value:
{"id_": "ad694fbf-97ac-4c3f-b2b5-eeeed24148a1", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ccfa0d68-6753-4c2d-a573-f8a08517b88f", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "2588a086a336b8e21d84546d77fa7ffaa1325df68a6615cdf1543bba92660629", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "d44e9a06-a37a-42df-bfd3-34de11cbc017", "node_type": "1", "metadata": {}, "hash": "bd37646c5a6fa97ae55f93e88eac0fb4c65b5554542d96b3ca8631ce4d5f5fb5", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2736, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# GPT Action Library: Confluence

## Introduction

This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information: 
- [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
- [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
- [Example of Building a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)

This particular GPT Action provides an overview of how to connect to **Confluence**, Atlassian's collaboration and documentation platform. This Action takes a user’s question, scans the relevant Confluence spaces and pages to gather the necessary information, then formulates a response to answer the user’s question. This cookbook does not address updating content in Confluence directly from ChatGPT, but it is technically feasible to accomplish with additional Actions and scopes.

### Value + Example Business Use Cases

**Value**

Users can now leverage ChatGPT's natural language capability to connect directly to Confluence, enabling seamless interaction with their organization's knowledge base.

**Example Use Cases**
- **Knowledge Workers**: Easily retrieve information from Confluence pages and spaces to answer questions or gather details for reports and presentations.
- **Project Managers**: Quickly access project documentation and updates stored in Confluence without manually searching through pages.
- **Customer Support Teams**: Provide accurate and timely responses to customer inquiries by pulling relevant information from the Confluence knowledge base.
- **All Users**: Gain more visibility into company-wide documentation, policies, and procedures, enhancing collaboration and knowledge sharing.

## Application Information

### Application Key Links

Check out these links from the application before you get started:
- Application Website: https://developer.atlassian.com/console/myapps/ 
- Application API Documentation: https://developer.atlassian.com/cloud/confluence/rest/v2/intro/#about

### Application Prerequisites

Before you get started, make sure you go through the following steps in your application environment:
- Ensure you have permissions to create an App in the Atlassian Developer Portal
- Determine what interactions you would like your GPT to take (search, read, edit, etc.)

## ChatGPT Steps

### Custom GPT Instructions 

Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


key: _node_content
string_value:
{"id_": "d44e9a06-a37a-42df-bfd3-34de11cbc017", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ccfa0d68-6753-4c2d-a573-f8a08517b88f", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "2588a086a336b8e21d84546d77fa7ffaa1325df68a6615cdf1543bba92660629", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "ad694fbf-97ac-4c3f-b2b5-eeeed24148a1", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "a812dc385e288be04bc698a8e2bc228aff4e5ff4c6075bf438b64c6ecf3e3a78", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "9c78f1d3-706b-4deb-b9c0-b1f6c07469b3", "node_type": "1", "metadata": {}, "hash": "de4f5397664aee77ead8eb938ffe826dfddfa9b90628decac6ebc399030d0093", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 2739, "end_char_idx": 6421, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
You are a "Confluence Savant", equipped with the ability to search our company's Product Wiki in Confluence to answer product-related questions.

You must ALWAYS perform the "getAccessibleResources" Action first to get the "cloudid" value you will need in subsequent Actions.

Your job is to provide accurate and detailed responses by retrieving information from the Product Wiki. Your responses should be clear, concise, and directly address the question asked. You have the capability to execute an action named "performConfluenceSearch" that allows you to search for content within our Confluence Product Wiki using specific terms or phrases related to the user's question.

    - When you receive a query about product information, use the "performConfluenceSearch" action to retrieve relevant content from the Product Wiki. Formulate your search query based on the user's question, using specific keywords or phrases to find the most pertinent information.
    - Once you receive the search results, review the content to ensure it matches the user's query. If necessary, refine your search query to retrieve more accurate results.
    - Provide a response that synthesizes the information from the Product Wiki, clearly answering the user's question. Your response should be easy to understand and directly related to the query.
    - If the query is complex or requires clarification, ask follow-up questions to the user to refine your understanding and improve the accuracy of your search.
    - If the information needed to answer the question is not available in the Product Wiki, inform the user and guide them to where they might find the answer, such as contacting a specific department or person in the company.

    Here is an example of how you might respond to a query:

    User: "What are the latest features of our XYZ product?"
    You: "The latest features of the XYZ product, as detailed in our Product Wiki, include [feature 1], [feature 2], and [feature 3]. These features were added in the recent update to enhance [specific functionalities]. For more detailed information, you can refer to the Product Wiki page [link to the specific Confluence page]."

Remember, your goal is to provide helpful, accurate, and relevant information to the user's query by effectively leveraging the Confluence Product Wiki.

```

### OpenAPI Schema 

Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
openapi: 3.1.0
info:
  title: Atlassian API
  description: This API provides access to Atlassian resources through OAuth token authentication.
  version: 1.0.0
servers:
  - url: https://api.atlassian.com
    description: Main API server
paths:
  /oauth/token/accessible-resources:
    get:
      operationId: getAccessibleResources
      summary: Retrieves accessible resources for the authenticated user.
      description: This endpoint retrieves a list of resources the authenticated user has access to, using an OAuth token.
      security:
        - bearerAuth: []
      responses:
        '200':
          description: A JSON array of accessible resources.
          content:
            application/json:
              schema: 
                $ref: '#/components/schemas/ResourceArray'
  /ex/confluence/{cloudid}/wiki/rest/api/search:
    get:
      operationId: performConfluenceSearch
      summary: Performs a search in Confluence based on a query.
      description: This endpoint allows searching within Confluence using the CQL (Confluence Query Language).


key: _node_content
string_value:
{"id_": "9c78f1d3-706b-4deb-b9c0-b1f6c07469b3", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ccfa0d68-6753-4c2d-a573-f8a08517b88f", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "2588a086a336b8e21d84546d77fa7ffaa1325df68a6615cdf1543bba92660629", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "d44e9a06-a37a-42df-bfd3-34de11cbc017", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "4bcbe151558e03411c44b235e7fa05b8bdccd811a009b894b66e7fc29bb923bc", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "59bd8e58-b058-4d48-82d8-73ed061f6512", "node_type": "1", "metadata": {}, "hash": "5e975f34efcf77ccb3b97cc5ac29a3703183ead515986b465ed45e0c4447f2fc", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 5341, "end_char_idx": 9044, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
openapi: 3.1.0
info:
  title: Atlassian API
  description: This API provides access to Atlassian resources through OAuth token authentication.
  version: 1.0.0
servers:
  - url: https://api.atlassian.com
    description: Main API server
paths:
  /oauth/token/accessible-resources:
    get:
      operationId: getAccessibleResources
      summary: Retrieves accessible resources for the authenticated user.
      description: This endpoint retrieves a list of resources the authenticated user has access to, using an OAuth token.
      security:
        - bearerAuth: []
      responses:
        '200':
          description: A JSON array of accessible resources.
          content:
            application/json:
              schema: 
                $ref: '#/components/schemas/ResourceArray'
  /ex/confluence/{cloudid}/wiki/rest/api/search:
    get:
      operationId: performConfluenceSearch
      summary: Performs a search in Confluence based on a query.
      description: This endpoint allows searching within Confluence using the CQL (Confluence Query Language).
      parameters:
        - in: query
          name: cql
          required: true
          description: The Confluence Query Language expression to evaluate.
          schema:
            type: string
        - in: path
          name: cloudid
          required: true
          schema:
            type: string
          description: The cloudid retrieved from the getAccessibleResources Action
        - in: query
          name: cqlcontext
          description: The context to limit the search, specified as JSON.
          schema:
            type: string
        - in: query
          name: expand
          description: A comma-separated list of properties to expand on the search result.
          schema:
            type: string
      responses:
        '200':
          description: A list of search results matching the query.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResults'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    ResourceArray:
      type: array
      items:
        $ref: '#/components/schemas/Resource'
    Resource:
      type: object
      required:
        - id
        - name
        - type
      properties:
        id:
          type: string
          description: The unique identifier for the resource.
        name:
          type: string
          description: The name of the resource.
        type:
          type: string
          description: The type of the resource.
    SearchResults:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/SearchResult'
    SearchResult:
      type: object
      properties:
        id:
          type: string
          description: The unique identifier of the content.
        title:
          type: string
          description: The title of the content.
        type:
          type: string
          description: The type of the content (e.g., page, blog post).
        space:
          type: object
          properties:
            id:
              type: string
              description: The space ID where the content is located.
            name:
              type: string
              description: The name of the space.
```

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


key: _node_content
string_value:
{"id_": "59bd8e58-b058-4d48-82d8-73ed061f6512", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ccfa0d68-6753-4c2d-a573-f8a08517b88f", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "2588a086a336b8e21d84546d77fa7ffaa1325df68a6615cdf1543bba92660629", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "9c78f1d3-706b-4deb-b9c0-b1f6c07469b3", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f591609919211db6eb3ab4083f58f4bdf276ff95513c3170f4aff9fcf2d36ae1", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "b802228a-b2f0-4d41-a850-b85747d17280", "node_type": "1", "metadata": {}, "hash": "cf579e21906dfcc88c903f74fdc99e9f1d29b5c0ef4f33788febf57d112759d5", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 7130, "end_char_idx": 10115, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
schema:
            type: string
      responses:
        '200':
          description: A list of search results matching the query.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResults'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    ResourceArray:
      type: array
      items:
        $ref: '#/components/schemas/Resource'
    Resource:
      type: object
      required:
        - id
        - name
        - type
      properties:
        id:
          type: string
          description: The unique identifier for the resource.
        name:
          type: string
          description: The name of the resource.
        type:
          type: string
          description: The type of the resource.
    SearchResults:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/SearchResult'
    SearchResult:
      type: object
      properties:
        id:
          type: string
          description: The unique identifier of the content.
        title:
          type: string
          description: The title of the content.
        type:
          type: string
          description: The type of the content (e.g., page, blog post).
        space:
          type: object
          properties:
            id:
              type: string
              description: The space ID where the content is located.
            name:
              type: string
              description: The name of the space.
```

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

### Pre-Action Steps

Before you set up authentication in ChatGPT, make sure you go through the following steps within the Atlassian Developer portal to create your Confluence app:

1. Select the Create drop-down
2. Choose OAuth 2.0 integration
3. Give a name, agree to terms, and click Create
4. Select "Distribution" on the left-hand menu and click “Edit”
5. Change radio button to "Sharing"
6. Fill out required fields and Save Changes
7. Select "Permissions" on the left-hand menu
8. Add in the scopes you would like to include (e.g., User identity API and Confluence API so that the app can know what a user has access to and fetch from Confluence)
9. Select "Authorization" on the left-hand menu
10. Click "Add" under Action in the row for OAuth 2.0
11. Enter the callback URL from your GPT (note: you may need to add a placeholder for now and revisit this once you have created the Action and OAuth in your GPT so that you have the final callback URL)
12. Select "Settings" under the left-hand menu
13. Copy your Client ID and Secret for us in OAuth setup in GPT


key: _node_content
string_value:
{"id_": "b802228a-b2f0-4d41-a850-b85747d17280", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ccfa0d68-6753-4c2d-a573-f8a08517b88f", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "2588a086a336b8e21d84546d77fa7ffaa1325df68a6615cdf1543bba92660629", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "59bd8e58-b058-4d48-82d8-73ed061f6512", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_confluence.ipynb", "title": "GPT Action Library: Confluence", "tokens": 2411, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "0951cc6300dbcba564c35590be192bb4b5a1c63900e9008329c3c328c6cb52d9", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 8510, "end_char_idx": 11680, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
space:
          type: object
          properties:
            id:
              type: string
              description: The space ID where the content is located.
            name:
              type: string
              description: The name of the space.
```

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

### Pre-Action Steps

Before you set up authentication in ChatGPT, make sure you go through the following steps within the Atlassian Developer portal to create your Confluence app:

1. Select the Create drop-down
2. Choose OAuth 2.0 integration
3. Give a name, agree to terms, and click Create
4. Select "Distribution" on the left-hand menu and click “Edit”
5. Change radio button to "Sharing"
6. Fill out required fields and Save Changes
7. Select "Permissions" on the left-hand menu
8. Add in the scopes you would like to include (e.g., User identity API and Confluence API so that the app can know what a user has access to and fetch from Confluence)
9. Select "Authorization" on the left-hand menu
10. Click "Add" under Action in the row for OAuth 2.0
11. Enter the callback URL from your GPT (note: you may need to add a placeholder for now and revisit this once you have created the Action and OAuth in your GPT so that you have the final callback URL)
12. Select "Settings" under the left-hand menu
13. Copy your Client ID and Secret for us in OAuth setup in GPT


![confluence_gpt.png](../../../images/confluence_gpt.png)

### In ChatGPT

In ChatGPT, click on "Authentication" and choose **"OAuth"**. Enter in the information below. 

- **Client ID**: use Client ID from steps above 
- **Client Secret**: use Client Secret from steps above
- **Authorization URL**: https://auth.atlassian.com/authorize
- **Token URL**: https://auth.atlassian.com/oauth/token 
- **Scope**: read:confluence-content.all search:confluence
- **Token**: Default (POST)

### Post-Action Steps

Once you've set up authentication in ChatGPT, follow the steps below in the application to finalize the Action. 

- Copy the callback URL from the GPT Action
- In the “Authorized redirect URIs” (see screenshot above), add your callback URL 


### FAQ & Troubleshooting

- *Callback URL Error:* If you get a callback URL error in ChatGPT, pay close attention to the screenshot above. You need to add the callback URL directly into your Confluence app for the action to authenticate correctly
- *Schema calls the wrong project or dataset:* If ChatGPT calls the wrong project or dataset, consider updating your instructions to make it more explicit either (a) which project / dataset should be called or (b) to require the user provide those exact details before it runs the query
- *Looping Actions:* You may not have given the necessary scopes/permissions to your app to accomplish its intended purpose

*Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look.*


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_zapier.ipynb


key: _node_content
string_value:
{"id_": "8d1d490f-edc1-49c7-9e40-8a7ffa9d33ea", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_zapier.ipynb", "title": "GPT Action Library: Zapier", "tokens": 577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "2b208d3e-9236-4396-8a9f-ded63768f204", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_zapier.ipynb", "title": "GPT Action Library: Zapier", "tokens": 577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "6833f6d2aa59602869e7c43920c005e78fa68af20a7d2d47708aab6d7ca9d6c7", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2521, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# GPT Action Library: Zapier

## Introduction

This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information: 
- [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
- [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
- [Example of Buliding a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)

This GPT Action provides an overview of how to connect a GPT to **Zapier**.  Because the majority of configuration occurs on Zapier, we recommend reviewing this ***[helpful guide from Zapier on connecting GPTs to custom Zapier Actions](https://actions.zapier.com/docs/platform/gpt)***.

### Value + Example Business Use Cases

**Value**: Users can now connect custom GPTs within ChatGPT to Zapier and get instant integration to 6,0000+ apps and 20,000+ actions across the tech stack.   

**Example Use Cases**: 
- An organization has already setup Zapier integrations, and would like to avoid additional integration work when connecting their tech ecosystem with ChatGPT
- Build a Calendar Assistant GPT which looks up calendar events, and provides additional context based on attendees' LinkedIn profiles
- A CRM GPT to help connect Hubspot to ChatGPT allowing sales teams to update or review contacts and notes on the go


## Application Information

### Application Key Links

Check out these links from the application before you get started:
- Application Website: https://zapier.com
- AI Actions URL: https://actions.zapier.com/gpt/actions/
- Automatic OpenAPI Configuration: https://actions.zapier.com/gpt/api/v1/dynamic/openapi.json?tools=meta

### Application Prerequisites

Before you get started, make sure you go through the following step in your Zapier:
- Configure the desired AI Actions via the [AI Action Manager](https://actions.zapier.com/gpt/actions/)

![zapier_ai_actions.png](../../../images/zapier_ai_actions.png)

![zapier_action_config.png](../../../images/zapier_action_config.png)

### In ChatGPT

In ChatGPT, from the custom GPT creator screen, click on "Actions" and choose **"Import from URL"**. Enter in Zapier URL for provisioning GPTs: https://actions.zapier.com/gpt/api/v1/dynamic/openapi.json?tools=meta

*Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look.*


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb


key: _node_content
string_value:
{"id_": "e82b2f1a-2f38-4ea0-ab73-4a7dbe385dbc", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "3f0beb73-a1ac-4439-8113-8d9e20bfced9", "node_type": "1", "metadata": {}, "hash": "a3ebdd4685e08b45c7cd41ea4c3966bbd039d05a801f5313a07047d6e6d011e7", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 3638, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# GPT Action Library: Box

## Introduction

This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information: 
- [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
- [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
- [Example of Buliding a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)

This guide provides details on how to connect chatGPT with a Box.com account, the GPT requires two actions to pull data from Box. The GPT will interact with the Box API directly but requires middleware (ie Azure function) to properly format the response from Box to download and read the file contents. The azure function action is transparent to the end user, meaning the user will not need to explicity call the action. 

- Action 1 : Box API Action - Leverages the Box API to query data from Box 
- Action 2 : Azure function - Formats response from Box enabling chatGPT to download the file directly from Box

### Value + Example Business Use Cases

Existing Box customers can leverage these guidelines to query details about files, contents of files and any metadata related. This enables a OpenAI powered analysis of any content stored in Box such as visualizing data sets and creating summaries across multiple folders and files. This GPT can access folders, files and business process data such as metadata in Box. Additionally Box admins can use this GPT action for visibility into audit trails and health checks.

## Application Information

### Application Key Links

Check out these links from Box and Azure before you get started:

**Box Action**
- Application Website: https://app.box.com 
- Application API Documentation: https://developer.box.com/reference/

</br>

**Azure Function**
- Application Website: https://learn.microsoft.com/en-us/azure/azure-functions/
- Application API Documentation: https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference/
 

### Application Prerequisites

Before you get started, make sure you go through the following steps in your Box environment:
- This requires a Box developer account to get started : https://developer.box.com/
- Follow the Box Developer site to create a custom app with OAuth 2.0 authentication type  : https://developer.box.com/guides/getting-started/first-application/  
- Navigate to **Configuration** tab for the following values
    - OAuth 2.0 Credentials (**Client ID** / **Client Secret**) You will need both of these values for the chatGPT configuration
    - OAuth 2.0 **Redirect URIs** : You will fill this value in from chatGPT action configuration below
    - Application scopes (**Read all files and folders in Box**, **Manage Enterprise properties**) 

You will want to keep this window open, the Redirct URIs needs to be filled in from the gpt configuration.



![gpt_actions_box_boxconfig1.png.png](../../../images/gpt_actions_box_boxconfig1.png)

</br>


### Middleware information : required for Action 2

Make sure you go through the following steps in your Azure environment:
- Azure Portal with access to create Azure Function Apps and Azure Entra App Registrations
- There is a detailed section in this guide related to deploying and designing the function required to wrap the response from Box in order to view the contents of the file. Without the function the GPT will only be able to query data about the file and not the contents. Be sure to read this section after creating the first action.


key: _node_content
string_value:
{"id_": "3f0beb73-a1ac-4439-8113-8d9e20bfced9", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "e82b2f1a-2f38-4ea0-ab73-4a7dbe385dbc", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ec0636cf22750abd2c412dd95ebde41975764df3561de8393f4a657ecf8b8d93", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "02c88097-20ca-4f6d-8ae7-6487f9cc5447", "node_type": "1", "metadata": {}, "hash": "fbae7c8c7e3f6e82055fe245799205f79efa3d95e751aa18ff03059994d9aa8a", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 2995, "end_char_idx": 6368, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
![gpt_actions_box_boxconfig1.png.png](../../../images/gpt_actions_box_boxconfig1.png)

</br>


### Middleware information : required for Action 2

Make sure you go through the following steps in your Azure environment:
- Azure Portal with access to create Azure Function Apps and Azure Entra App Registrations
- There is a detailed section in this guide related to deploying and designing the function required to wrap the response from Box in order to view the contents of the file. Without the function the GPT will only be able to query data about the file and not the contents. Be sure to read this section after creating the first action.


## ChatGPT Steps

### Custom GPT Instructions 

Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
**context** 

This GPT will connect to your Box.com account to search files and folders, providing accurate and helpful responses based on the user's queries. It will assist with finding, organizing, and retrieving information stored in Box.com. Ensure secure and private handling of any accessed data. Avoid performing any actions that could modify or delete files unless explicitly instructed. Prioritize clarity and efficiency in responses. Use simple language for ease of understanding. Ask for clarification if a request is ambiguous or if additional details are needed to perform a search. Maintain a professional and friendly tone, ensuring users feel comfortable and supported.


Please use this website for instructions using the box API : https://developer.box.com/reference/ each endpoint can be found from this reference documentation

Users can search with the Box search endpoint or Box metadata search endpoint

**instructions**
When retrieving file information from Box provide as much details as possible and format into a table when more than one file is returned, include the modified date, created date and any other headers you might find valuable

Provide insights to files and suggest patterns for users, gives example queries and suggestions when appropriate

When a user wants to compare files retrieve the file for the user with out asking
```

### Action 1 : Box API Action

Once you've created a Custom GPT, you will need to create 2 actions. Copy the text below in the 1st Actions panel, this will be for the Box action. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
{
  "openapi": "3.1.0",
  "info": {
    "title": "Box.com API",
    "description": "API for Box.com services",
    "version": "v1.0.0"
  },
  "servers": [
    {
      "url": "https://api.box.com/2.0"
    }
  ],
  "paths": {
    "/folders/{folder_id}": {
      "get": {
        "summary": "Get Folder Items",
        "operationId": "getFolderItems",
        "parameters": [
          {
            "name": "folder_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the folder"
          }
        ],
        "responses": {
          "200": {
            "description": "A list of items in the folder",


key: _node_content
string_value:
{"id_": "02c88097-20ca-4f6d-8ae7-6487f9cc5447", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "3f0beb73-a1ac-4439-8113-8d9e20bfced9", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "011d96336653b75143d17f11a5d3c8d666e7bbc21a01b36408df409a486420f7", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "4ce33c93-df2b-4ca3-b0bf-b820e1c99869", "node_type": "1", "metadata": {}, "hash": "db0790474626c716d51ffacee086454822dcc2ca9d0ffb5e1d4ff38a90921a95", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 5640, "end_char_idx": 8805, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
{
  "openapi": "3.1.0",
  "info": {
    "title": "Box.com API",
    "description": "API for Box.com services",
    "version": "v1.0.0"
  },
  "servers": [
    {
      "url": "https://api.box.com/2.0"
    }
  ],
  "paths": {
    "/folders/{folder_id}": {
      "get": {
        "summary": "Get Folder Items",
        "operationId": "getFolderItems",
        "parameters": [
          {
            "name": "folder_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the folder"
          }
        ],
        "responses": {
          "200": {
            "description": "A list of items in the folder",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderItems"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:folders"
            ]
          }
        ]
      }
    },
    "/files/{file_id}": {
      "get": {
        "summary": "Get File Information",
        "operationId": "getFileInfo",
        "parameters": [
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the file"
          }
        ],
        "responses": {
          "200": {
            "description": "File information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileInfo"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:files"
            ]
          }
        ]
      }
    },
    "/folders": {
      "get": {
        "summary": "List All Folders",
        "operationId": "listAllFolders",
        "responses": {
          "200": {
            "description": "A list of all folders",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoldersList"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:folders"
            ]
          }
        ]
      }
    },
    "/events": {
      "get": {
        "summary": "Get User Events",
        "operationId": "getUserEvents",
        "parameters": [
          {
            "name": "stream_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The type of stream"
          }
        ],
        "responses": {
          "200": {
            "description": "User events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserEvents"
                }
              }
            }
          }
        },


key: _node_content
string_value:
{"id_": "4ce33c93-df2b-4ca3-b0bf-b820e1c99869", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "02c88097-20ca-4f6d-8ae7-6487f9cc5447", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "da9e94717cd9150719f2605a4f5438f7facb28fcd4bf2bd05d2bce9a19995402", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "04577281-8b6f-44e5-9c6c-46f9d88043dd", "node_type": "1", "metadata": {}, "hash": "d5918dde00de7ac659f6b8be0460793cee0e51cffa12c24dc7ae41acab105878", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6955, "end_char_idx": 10438, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
"required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the file"
          }
        ],
        "responses": {
          "200": {
            "description": "File information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileInfo"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:files"
            ]
          }
        ]
      }
    },
    "/folders": {
      "get": {
        "summary": "List All Folders",
        "operationId": "listAllFolders",
        "responses": {
          "200": {
            "description": "A list of all folders",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoldersList"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:folders"
            ]
          }
        ]
      }
    },
    "/events": {
      "get": {
        "summary": "Get User Events",
        "operationId": "getUserEvents",
        "parameters": [
          {
            "name": "stream_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The type of stream"
          }
        ],
        "responses": {
          "200": {
            "description": "User events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserEvents"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:events"
            ]
          }
        ]
      }
    },
    "/admin_events": {
      "get": {
        "summary": "Get Admin Events",
        "operationId": "getAdminEvents",
        "responses": {
          "200": {
            "description": "Admin events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminEvents"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:events"
            ]
          }
        ]
      }
    },
    "/search": {
      "get": {
        "summary": "Search",
        "operationId": "search",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Search query"
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResults"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "search:items"
            ]
          }
        ]
      }
    },
    "/metadata_templates": {
      "get": {
        "summary": "Get Metadata Templates",
        "operationId": "getMetadataTemplates",


key: _node_content
string_value:
{"id_": "04577281-8b6f-44e5-9c6c-46f9d88043dd", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "4ce33c93-df2b-4ca3-b0bf-b820e1c99869", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "372dc2ede4e24a94cf7a16106e4416f6e5cdffb66569c362aca6cb07a6f1dac0", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "27fe90d3-bc24-425a-bf4a-eb30d16ad1c3", "node_type": "1", "metadata": {}, "hash": "95355e07d9fec585f21ab98204fdece961dde6abe310d6c147b62e4485c391d1", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 8598, "end_char_idx": 12071, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
"content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserEvents"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:events"
            ]
          }
        ]
      }
    },
    "/admin_events": {
      "get": {
        "summary": "Get Admin Events",
        "operationId": "getAdminEvents",
        "responses": {
          "200": {
            "description": "Admin events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminEvents"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:events"
            ]
          }
        ]
      }
    },
    "/search": {
      "get": {
        "summary": "Search",
        "operationId": "search",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Search query"
          }
        ],
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResults"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "search:items"
            ]
          }
        ]
      }
    },
    "/metadata_templates": {
      "get": {
        "summary": "Get Metadata Templates",
        "operationId": "getMetadataTemplates",
        "responses": {
          "200": {
            "description": "Metadata templates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataTemplates"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata_templates"
            ]
          }
        ]
      }
    },
    "/metadata_templates/enterprise": {
      "get": {
        "summary": "Get Enterprise Metadata Templates",
        "operationId": "getEnterpriseMetadataTemplates",
        "responses": {
          "200": {
            "description": "Enterprise metadata templates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataTemplates"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata_templates"
            ]
          }
        ]
      }
    },
    "/files/{file_id}/metadata": {
      "get": {
        "summary": "Get All Metadata for a File",
        "operationId": "getAllMetadataForFile",
        "parameters": [
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the file"
          }
        ],
        "responses": {
          "200": {
            "description": "All metadata instances for the file",


key: _node_content
string_value:
{"id_": "27fe90d3-bc24-425a-bf4a-eb30d16ad1c3", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "04577281-8b6f-44e5-9c6c-46f9d88043dd", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "0decbc0239cf8be2fb6e1b84871cd380f8ee0583861aba91bb948382a5feb636", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "ce735448-c85f-478b-b1c3-64d088e8df8d", "node_type": "1", "metadata": {}, "hash": "5d8ad6b3d9ad33a421c49f7885134ca894f983da1700fbd573d4b6013409898a", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": null, "end_char_idx": null, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
"/metadata_templates": {
      "get": {
        "summary": "Get Metadata Templates",
        "operationId": "getMetadataTemplates",
        "responses": {
          "200": {
            "description": "Metadata templates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataTemplates"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata_templates"
            ]
          }
        ]
      }
    },
    "/metadata_templates/enterprise": {
      "get": {
        "summary": "Get Enterprise Metadata Templates",
        "operationId": "getEnterpriseMetadataTemplates",
        "responses": {
          "200": {
            "description": "Enterprise metadata templates",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataTemplates"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata_templates"
            ]
          }
        ]
      }
    },
    "/files/{file_id}/metadata": {
      "get": {
        "summary": "Get All Metadata for a File",
        "operationId": "getAllMetadataForFile",
        "parameters": [
          {
            "name": "file_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the file"
          }
        ],
        "responses": {
          "200": {
            "description": "All metadata instances for the file",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataInstances"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "FolderItems": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "integer",
            "description": "The total number of items in the folder"
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "The type of the item (e.g. file, folder)"
                },
                "id": {
                  "type": "string",
                  "description": "The ID of the item"
                },
                "name": {
                  "type": "string",
                  "description": "The name of the item"
                }
              }
            }
          }
        }
      },
      "FileInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the file"
          },
          "name": {
            "type": "string",
            "description": "The name of the file"
          },
          "size": {
            "type": "integer",
            "description": "The size of the file in bytes"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",


key: _node_content
string_value:
{"id_": "ce735448-c85f-478b-b1c3-64d088e8df8d", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "27fe90d3-bc24-425a-bf4a-eb30d16ad1c3", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "bb749f4a5c7d08b365cb27e00771a8217a97ff001a5a88b8e67528601c8c9b9e", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "123d95e7-3dde-4249-839d-e89ee56dc9ce", "node_type": "1", "metadata": {}, "hash": "ac229b3674eeea2eb0171c3bf78338e19e5f9a208677bd52b3c48af756673835", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": null, "end_char_idx": null, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
"content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetadataInstances"
                }
              }
            }
          }
        },
        "security": [
          {
            "OAuth2": [
              "read:metadata"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "FolderItems": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "integer",
            "description": "The total number of items in the folder"
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "The type of the item (e.g. file, folder)"
                },
                "id": {
                  "type": "string",
                  "description": "The ID of the item"
                },
                "name": {
                  "type": "string",
                  "description": "The name of the item"
                }
              }
            }
          }
        }
      },
      "FileInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the file"
          },
          "name": {
            "type": "string",
            "description": "The name of the file"
          },
          "size": {
            "type": "integer",
            "description": "The size of the file in bytes"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "The creation time of the file"
          },
          "modified_at": {
            "type": "string",
            "format": "date-time",
            "description": "The last modification time of the file"
          }
        }
      },
      "FoldersList": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "description": "The ID of the folder"
            },
            "name": {
              "type": "string",
              "description": "The name of the folder"
            }
          }
        }
      },
      "UserEvents": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "event_id": {
                  "type": "string",
                  "description": "The ID of the event"
                },
                "event_type": {
                  "type": "string",
                  "description": "The type of the event"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "The time the event occurred"
                }
              }
            }
          }
        }
      },
      "AdminEvents": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "event_id": {
                  "type": "string",
                  "description": "The ID of the event"
                },


key: _node_content
string_value:
{"id_": "123d95e7-3dde-4249-839d-e89ee56dc9ce", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "ce735448-c85f-478b-b1c3-64d088e8df8d", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "b3d3427cdaeaad93e97fddb268d9368aba4483ddcdc49543411d4523fe38899c", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "3fc7d304-6b7b-461e-b1a2-2a510c855bb9", "node_type": "1", "metadata": {}, "hash": "4ca0faa5f49f592a854f470d22a7c02a81fdce6671ced0fc7750d57f6b3a2eaa", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": null, "end_char_idx": null, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
"format": "date-time",
            "description": "The creation time of the file"
          },
          "modified_at": {
            "type": "string",
            "format": "date-time",
            "description": "The last modification time of the file"
          }
        }
      },
      "FoldersList": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string",
              "description": "The ID of the folder"
            },
            "name": {
              "type": "string",
              "description": "The name of the folder"
            }
          }
        }
      },
      "UserEvents": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "event_id": {
                  "type": "string",
                  "description": "The ID of the event"
                },
                "event_type": {
                  "type": "string",
                  "description": "The type of the event"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "The time the event occurred"
                }
              }
            }
          }
        }
      },
      "AdminEvents": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "event_id": {
                  "type": "string",
                  "description": "The ID of the event"
                },
                "event_type": {
                  "type": "string",
                  "description": "The type of the event"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "The time the event occurred"
                }
              }
            }
          }
        }
      },
      "SearchResults": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "integer",
            "description": "The total number of search results"
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "The type of the item (e.g. file, folder)"
                },
                "id": {
                  "type": "string",
                  "description": "The ID of the item"
                },
                "name": {
                  "type": "string",
                  "description": "The name of the item"
                }
              }
            }
          }
        }
      },
      "MetadataTemplates": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "templateKey": {
              "type": "string",
              "description": "The key of the metadata template"
            },
            "displayName": {
              "type": "string",
              "description": "The display name of the metadata template"
            },
            "scope": {
              "type": "string",
              "description": "The scope of the metadata template"
            }
          }
        }
      },


key: _node_content
string_value:
{"id_": "3fc7d304-6b7b-461e-b1a2-2a510c855bb9", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "123d95e7-3dde-4249-839d-e89ee56dc9ce", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "c5e6c3ce29c77efb28411fd61bf3b39af61d3d94d559aad7d7fa21d4bc669d72", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "e2f32af6-4388-4a5a-b697-c22d395560fa", "node_type": "1", "metadata": {}, "hash": "299f90d1ba2fb5bda98108c5ca216bc510266bb2b0ee28d2b0fffab51dcbf437", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": null, "end_char_idx": null, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
"description": "The ID of the event"
                },
                "event_type": {
                  "type": "string",
                  "description": "The type of the event"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "The time the event occurred"
                }
              }
            }
          }
        }
      },
      "SearchResults": {
        "type": "object",
        "properties": {
          "total_count": {
            "type": "integer",
            "description": "The total number of search results"
          },
          "entries": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "The type of the item (e.g. file, folder)"
                },
                "id": {
                  "type": "string",
                  "description": "The ID of the item"
                },
                "name": {
                  "type": "string",
                  "description": "The name of the item"
                }
              }
            }
          }
        }
      },
      "MetadataTemplates": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "templateKey": {
              "type": "string",
              "description": "The key of the metadata template"
            },
            "displayName": {
              "type": "string",
              "description": "The display name of the metadata template"
            },
            "scope": {
              "type": "string",
              "description": "The scope of the metadata template"
            }
          }
        }
      },
      "MetadataInstances": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "templateKey": {
              "type": "string",
              "description": "The key of the metadata template"
            },
            "type": {
              "type": "string",
              "description": "The type of the metadata instance"
            },
            "attributes": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              },
              "description": "Attributes of the metadata instance"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "OAuth2": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://account.box.com/api/oauth2/authorize",
            "tokenUrl": "https://api.box.com/oauth2/token",
            "scopes": {
              "read:folders": "Read folders",
              "read:files": "Read files",
              "search:items": "Search items",
              "read:metadata": "Read metadata",
              "read:metadata_templates": "Read metadata templates",
              "read:events": "Read events"
            }
          }
        }
      }
    }
  }
}
```

**Note : this schema above does not contain all possible API endpoints, be sure to edit the schema to produce the appropriate actions from [Box Developer documentation](https://developer.box.com)**

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions?


key: _node_content
string_value:
{"id_": "e2f32af6-4388-4a5a-b697-c22d395560fa", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "3fc7d304-6b7b-461e-b1a2-2a510c855bb9", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "af7955f8327f081fe519af80da65bd36a551eafbe3fb125c2bb5fd476ef65a55", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f67cf60e-3500-4a93-bd7a-b03599188573", "node_type": "1", "metadata": {}, "hash": "4de2f402bec7bc38ae5768ebc7ba981a725e7daf3df0b28ecac24226081a941e", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 17229, "end_char_idx": 20345, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
"scope": {
              "type": "string",
              "description": "The scope of the metadata template"
            }
          }
        }
      },
      "MetadataInstances": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "templateKey": {
              "type": "string",
              "description": "The key of the metadata template"
            },
            "type": {
              "type": "string",
              "description": "The type of the metadata instance"
            },
            "attributes": {
              "type": "object",
              "additionalProperties": {
                "type": "string"
              },
              "description": "Attributes of the metadata instance"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "OAuth2": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://account.box.com/api/oauth2/authorize",
            "tokenUrl": "https://api.box.com/oauth2/token",
            "scopes": {
              "read:folders": "Read folders",
              "read:files": "Read files",
              "search:items": "Search items",
              "read:metadata": "Read metadata",
              "read:metadata_templates": "Read metadata templates",
              "read:events": "Read events"
            }
          }
        }
      }
    }
  }
}
```

**Note : this schema above does not contain all possible API endpoints, be sure to edit the schema to produce the appropriate actions from [Box Developer documentation](https://developer.box.com)**

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

### In ChatGPT

In ChatGPT, click on "Authentication" and choose OAuth 


<br> ![gptactions_box_gptauth.png](../../../images/gpt_actions_box_gptauth.png)

**OAuth Connection**

- Client ID - value from Box custom app you created earlier
- Client Secret - value from Box custom app you created earlier 
- Authorization URL - : https://account.box.com/api/oauth2/authorize?response_type=code&client_id=[client ID from above]&redirect_uri=[use a placeholder like chat.openai.com/aip//oauth/callback for now, you’ll update this later when you create the Action in ChatGPT]
- Token URL : https:api.box.com/oauth2/token
</br>
</br>
You need to save the configuration and navigate back to the gpt Configuration tab to copy the Callback URL, edit the configuration for the Box action Authorization URL and format the URL as https://account.box.com/api/oauth2/authorize?response_type=code&client_id=[client_ID]&redirect_uri=[callBack URL]

### Post-Action Steps

Update the Box.com custom application
</br>
- Copy the CallBack URL from the gpt and add a OAuth 2.0 Redirect URIs in Box.com
</br>
</br>
![gpt_actions_box_boxconfig1.png.png](../../../images/gpt_actions_box_boxconfig1.png)

</br>


key: _node_content
string_value:
{"id_": "f67cf60e-3500-4a93-bd7a-b03599188573", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "e2f32af6-4388-4a5a-b697-c22d395560fa", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "743980366435e1cde1f734afae999faf721e058cdf2305519d70b9cb1d7b4371", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "1ec6c6e1-4cfd-4d4c-a46e-0cc3ca4825de", "node_type": "1", "metadata": {}, "hash": "49e7131cea51067c087ea9af23ea131c0d6bd3ca15ca3405b81d63553147f203", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 18763, "end_char_idx": 21100, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
be sure to edit the schema to produce the appropriate actions from [Box Developer documentation](https://developer.box.com)**

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

### In ChatGPT

In ChatGPT, click on "Authentication" and choose OAuth 


<br> ![gptactions_box_gptauth.png](../../../images/gpt_actions_box_gptauth.png)

**OAuth Connection**

- Client ID - value from Box custom app you created earlier
- Client Secret - value from Box custom app you created earlier 
- Authorization URL - : https://account.box.com/api/oauth2/authorize?response_type=code&client_id=[client ID from above]&redirect_uri=[use a placeholder like chat.openai.com/aip//oauth/callback for now, you’ll update this later when you create the Action in ChatGPT]
- Token URL : https:api.box.com/oauth2/token
</br>
</br>
You need to save the configuration and navigate back to the gpt Configuration tab to copy the Callback URL, edit the configuration for the Box action Authorization URL and format the URL as https://account.box.com/api/oauth2/authorize?response_type=code&client_id=[client_ID]&redirect_uri=[callBack URL]

### Post-Action Steps

Update the Box.com custom application
</br>
- Copy the CallBack URL from the gpt and add a OAuth 2.0 Redirect URIs in Box.com
</br>
</br>
![gpt_actions_box_boxconfig1.png.png](../../../images/gpt_actions_box_boxconfig1.png)

</br>


### Action 2 : Azure Function

Now that we have the GPT created and authenticating against Box.com, we can create the azure function to handle the response formatting enabling the GPT to download the files from Box. 

Follow this [Azure Cookbook Guide](https://cookbook.openai.com/examples/azure/functions) for further details deploying an Azure function. Below you will find sample code to add to the function. 

This code is meant to be directional - while it should work out of the box, it is designed to be customized to your need.</br>

</br>

**Data flow**

![gpt_actions_box_azureflow.png](../../../images/gpt_actions_box_azuredataflow.png)

</br></br>



Now that you have the azure function created, add the sample code below:

function_app.py


key: _node_content
string_value:
{"id_": "1ec6c6e1-4cfd-4d4c-a46e-0cc3ca4825de", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "f67cf60e-3500-4a93-bd7a-b03599188573", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "c989cb227f5387727cd8d92fd373b31f9482c5157991e601f87b03efdb40b61e", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "b72c8ef7-5acf-42f7-9d47-488e6860b87c", "node_type": "1", "metadata": {}, "hash": "7a528b96c9139b8d1f823fa5cf9fbeb2d3ab722c8b71dff057b7b8c8ccf1dc92", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 20348, "end_char_idx": 23801, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
### Action 2 : Azure Function

Now that we have the GPT created and authenticating against Box.com, we can create the azure function to handle the response formatting enabling the GPT to download the files from Box. 

Follow this [Azure Cookbook Guide](https://cookbook.openai.com/examples/azure/functions) for further details deploying an Azure function. Below you will find sample code to add to the function. 

This code is meant to be directional - while it should work out of the box, it is designed to be customized to your need.</br>

</br>

**Data flow**

![gpt_actions_box_azureflow.png](../../../images/gpt_actions_box_azuredataflow.png)

</br></br>



Now that you have the azure function created, add the sample code below:

function_app.py


```python
import azure.functions as func
from boxsdk import Client, JWTAuth

import requests
import base64
import json
import jwt
import logging

app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

@app.route(route="box_retrieval")
def box_retrieval(req: func.HttpRequest) -> func.HttpResponse:
    logger.info('Starting box_retrieval function')
    file_ids = req.params.get('file_ids')
    auth_header = req.headers.get('Authorization')

    if not file_ids or not auth_header:
        logger.error('Missing file_ids or Authorization header')
        return func.HttpResponse(
            "Missing file_id or Authorization header.",
            status_code=400
        )
    
    file_ids = file_ids.split(",")  # Assuming file_ids are passed as a comma-separated string
    if len(file_ids) == 0 or len(file_ids) > 10:
        logger.error('file_ids list is empty or contains more than 10 IDs')
        return func.HttpResponse(
            "file_ids list is empty or contains more than 10 IDs.",
            status_code=400
        )

    try:
        # Decode JWT to extract the email
        token = auth_header.split(" ")[1]
        decoded_token = jwt.decode(token, options={"verify_signature": False})
        upn = decoded_token['upn']
        user_email = get_user_mapping(upn)
        logger.info(f'User email extracted: {user_email}')

        config = JWTAuth.from_settings_file('jwt_config.json')
        sdk = Client(config)
        logger.info('Authenticated with Box API')

        # Use the user email to get the user ID
        users = sdk.users(filter_term=user_email)
        user = next(users)
        user_id = user.id
        logger.info(f'User ID obtained: {user_id}')

        openai_file_responses = []
        for file_id in file_ids:
            # Perform as_user call to get the file representation
            my_file = sdk.as_user(user).file(file_id).get()
            file_url = my_file.get_download_url()
            openai_file_responses.append(file_url)
        
        response_body = json.dumps({'openaiFileResponse': openai_file_responses})

        return func.HttpResponse(
            response_body,
            status_code=200,
            mimetype="application/json"
        )

    except Exception as e:
        return func.HttpResponse(
            f"An error occurred: {str(e)}",
            status_code=500
        )
    
def get_user_mapping(upn):
    # In our case, the user's authentication email into Azure AD is the same as their email in Box
    # If that is not the case, map the email in Box to the email in Azure AD
    return upn
```

jwt_config.json.sample


key: _node_content
string_value:
{"id_": "b72c8ef7-5acf-42f7-9d47-488e6860b87c", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "ac929a31-75d1-4968-acdf-858b8d36f7e6", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "d03a11bf65184d684bcf5a9096334f39b7cece7cc5d8081d0fb5dc0facbbc08d", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "1ec6c6e1-4cfd-4d4c-a46e-0cc3ca4825de", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_box.ipynb", "title": "GPT Action Library: Box", "tokens": 5278, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "16475c15c910ed4790e89c8ddac9a58aed9a12f3afa0e8dab3bbdd46e2906a20", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 23804, "end_char_idx": 24951, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
{
    "boxAppSettings": {
      "clientID": "12345",
      "clientSecret": "abcde",
      "appAuth": {
        "publicKeyID": "123",
        "privateKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\nvwxyz==\n-----END ENCRYPTED PRIVATE KEY-----\n",
        "passphrase": "lmnop"
      }
    },
    "enterpriseID": "09876"
  }
```

requirements.txt


```python
boxsdk[jwt]
azure-functions
requests
pyjwt
```

Make sure to follow the rest of the Azure guide for post authentication steps and chatGPT configuration : [Azure Cookbook Guide](https://cookbook.openai.com/examples/azure/functions)

### FAQ & Troubleshooting

- *Schema calls the wrong project or dataset:* If ChatGPT calls the wrong project or dataset, consider updating your instructions to make it more explicit either (a) which project / dataset should be called or (b) to require the user provide those exact details before it runs the query
- Box can return a large set of data in the event stream which can cause errors, 

*Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look.*


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb


key: _node_content
string_value:
{"id_": "d7c4e0e1-a0c0-4e42-a66d-a4b6e4fb161d", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "4eb028cd-d41a-4786-a7c5-a0d268dc9aab", "node_type": "1", "metadata": {}, "hash": "b3e8a188f8eddec0d3a61dfdc53b5de00d96bfa5dc278a74d6b09aeeb023f5ac", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 3085, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# GPT Actions - Snowflake middleware
## Introduction


This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information:

* [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
* [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
* [Example of Buliding a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)


This guide provides details on how to connect ChatGPT with a Snowflake Data Warehouse for the purposes of returning a SQL query to ChatGPT for use with [Data Analysis](https://help.openai.com/en/articles/8437071-data-analysis-with-chatgpt). The GPT requires an action that interfaces with middleware (ie Azure function) so that the action can properly format the response from Snowflake for use in the Python notebook environment. Data must be [returned as a file](https://platform.openai.com/docs/actions/sending-files/returning-files), so the middleware function should transform the SQL response into a CSV/Excel file, under 10MB in size.

This document will outline the Middleware function GPT action. For setting up the middleware function itself, see [GPT Actions library (Middleware) - Azure Functions](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_azure_function). You can combine this Snowflake middleware action with an action to Snowflake Directly to enable a GPT that can form and test SQL queries prior to executing them.

### Value + Example Business Use Cases


Existing Snowflake customers can leverage these guidelines to query data from their data warehouse and load that data into the Data Analysis Python environment for further insights. This enables ChatGPT powered analysis such as visualizing data sets, identifying patterns/anomalies, or identifying gaps for data cleansing purposes. This GPT can be used to drive business decisions from relatively small datasets, or to explore subsets of data through AI to generate hypotheses as you explore the holistic dataset in your BI tool, saving time and money, while identifying previously unseen patterns.

## Application Information

### Application Key Links


Check out these links from Snowflake and Azure before you get started:

**Snowflake Action**

* Application Website: [https://app.snowflake.com/](https://app.snowflake.com/)
* Application Python Connector Documentation: [https://docs.snowflake.com/en/developer-guide/python-connector/python-connector-connect](https://docs.snowflake.com/en/developer-guide/python-connector/python-connector-connect)

**Azure Function**

* Application Website: [https://learn.microsoft.com/en-us/azure/azure-functions/](https://learn.microsoft.com/en-us/azure/azure-functions/)
* Application API Documentation: [https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference/](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference/)


### Application Prerequisites


key: _node_content
string_value:
{"id_": "4eb028cd-d41a-4786-a7c5-a0d268dc9aab", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "d7c4e0e1-a0c0-4e42-a66d-a4b6e4fb161d", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "faae36901de09ebfea00e1481a7a55fb7c5a7c82e93cdec2fcc509b90d6534a0", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "af6ae3a5-15a5-46d2-9c5f-62d3131e9351", "node_type": "1", "metadata": {}, "hash": "32abb55004f06f6d25101b5e0f5761dff498d1c311f48a77cd37dcc4387c4436", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 1648, "end_char_idx": 5182, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
Existing Snowflake customers can leverage these guidelines to query data from their data warehouse and load that data into the Data Analysis Python environment for further insights. This enables ChatGPT powered analysis such as visualizing data sets, identifying patterns/anomalies, or identifying gaps for data cleansing purposes. This GPT can be used to drive business decisions from relatively small datasets, or to explore subsets of data through AI to generate hypotheses as you explore the holistic dataset in your BI tool, saving time and money, while identifying previously unseen patterns.

## Application Information

### Application Key Links


Check out these links from Snowflake and Azure before you get started:

**Snowflake Action**

* Application Website: [https://app.snowflake.com/](https://app.snowflake.com/)
* Application Python Connector Documentation: [https://docs.snowflake.com/en/developer-guide/python-connector/python-connector-connect](https://docs.snowflake.com/en/developer-guide/python-connector/python-connector-connect)

**Azure Function**

* Application Website: [https://learn.microsoft.com/en-us/azure/azure-functions/](https://learn.microsoft.com/en-us/azure/azure-functions/)
* Application API Documentation: [https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference/](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference/)


### Application Prerequisites


Before you get started, make sure you go through the following steps in your application environment:

* Provision a Snowflake Data Warehouse
* Ensure that the user authenticating into Snowflake via ChatGPT has access to the database, schemas, and tables with the necessary role

In addition, before creating your application in Azure Function App, you’ll need a way to handle user authentication. You’ll need to set up an OAuth App Registration in Azure Entra ID that can be linked with a Snowflake External OAuth security integration. Snowflake’s External OAuth security integrations allow external systems to issue access tokens that Snowflake can use for determining level of access. In this case, that external token provider is Azure Entra ID. Since ChatGPT will connect to Azure rather than Snowflake, the GPT user’s OAuth token will be provisioned by Azure associated with their user in Entra ID. Thus you’ll need a way to map users in Snowflake to their corresponding user in Azure. 

All of the necessary steps for both the Azure side and the Snowflake side are laid out below.

## Configure the OAuth resource in Azure Entra ID


We’ll set up a new App Registration, configure the necessary Snowflake Scopes in Azure that will be used, and retrieve all of the OAuth configuration parameters that will be needed in both Snowflake and ChatGPT. This section will all be in Azure so that in the next section, you’ll have the necessary info to link to this App Registration when configuring on the Snowflake side.

1. Navigate to the [Microsoft Azure Portal](https://portal.azure.com/) and authenticate.
2. Navigate to Azure Entra ID (formerly Active Directory).
3. Click on **App Registrations** under **Manage**.
4. Click on **New Registration**.
5. Enter `Snowflake GPT OAuth Client`, or similar value as the **Name**.
6. Verify the **Supported account types** is set to **Single Tenant**.
7. Ignore Redirect URI for now. You will come back for this once you are configuring your GPT
8. Click **Register**.
9. Note down the **Directory (tenant) ID** (`TENANT_ID`) under **Essentials**.


key: _node_content
string_value:
{"id_": "af6ae3a5-15a5-46d2-9c5f-62d3131e9351", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "4eb028cd-d41a-4786-a7c5-a0d268dc9aab", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "415b08d08f54145cd71ac4c2c76528b753864f340ea576f4e72bc0fb93f76eab", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f294c6d2-5ccc-4326-abb9-1b2fc15370b7", "node_type": "1", "metadata": {}, "hash": "683decc6d07bfda1c8a07925b11b8fda755b538e2a3e69229a3764b5bf6fab5e", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 4229, "end_char_idx": 6974, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
We’ll set up a new App Registration, configure the necessary Snowflake Scopes in Azure that will be used, and retrieve all of the OAuth configuration parameters that will be needed in both Snowflake and ChatGPT. This section will all be in Azure so that in the next section, you’ll have the necessary info to link to this App Registration when configuring on the Snowflake side.

1. Navigate to the [Microsoft Azure Portal](https://portal.azure.com/) and authenticate.
2. Navigate to Azure Entra ID (formerly Active Directory).
3. Click on **App Registrations** under **Manage**.
4. Click on **New Registration**.
5. Enter `Snowflake GPT OAuth Client`, or similar value as the **Name**.
6. Verify the **Supported account types** is set to **Single Tenant**.
7. Ignore Redirect URI for now. You will come back for this once you are configuring your GPT
8. Click **Register**.
9. Note down the **Directory (tenant) ID** (`TENANT_ID`) under **Essentials**. You will use this to generate your `AZURE_AD_ISSUER` and `AZURE_AD_JWS_KEY_ENDPOINT.`
    * The `AZURE_AD_ISSUER` is `https://sts.windows.net/TENANT_ID/`
    *  The `AZURE_AD_JWS_KEY_ENDPOINT` is `https://login.microsoftonline.com/TENANT_ID/discovery/v2.0/keys`
10. Click on **Endpoints** in the **Overview** interface.
11. On the right-hand side, note the **OAuth 2.0 authorization endpoint (v2)** as the `AZURE_AD_OAUTH_AUTHORIZATION_ENDPOINT`  and **OAuth 2.0 token endpoint (v2)** as the `AZURE_AD_OAUTH_TOKEN_ENDPOINT`.
    * The endpoints should be similar to `https://login.microsoftonline.com/90288a9b-97df-4c6d-b025-95713f21cef9/oauth2/v2.0/authorization` and `https://login.microsoftonline.com/90288a9b-97df-4c6d-b025-95713f21cef9/oauth2/v2.0/token`.
12. Click on **Expose an API **under **Manage**.
13. Click on the **Set** link next to **Application ID URI** to set the `Application ID URI`.
    * The `Application ID URI` must be unique within your organization’s directory, such as `https://your.company.com/4d2a8c2b-a5f4-4b86-93ca-294185f45f2e`. This value will be referred to as the `<SNOWFLAKE_APPLICATION_ID_URI>` in the subsequent configuration steps.
14. To add a Snowflake Role as an OAuth scope for OAuth flows where the programmatic client acts on behalf of a user, click on **Add a scope** to add a scope representing the Snowflake role.
    * Enter the scope by having the name of the Snowflake role with the `session:scope:` prefix. For example, for the Snowflake Analyst role, enter `session:scope:analyst`.
    * Select who can consent.
    * Enter a **display name** for the scope (e.g.: Account Admin).
    * Enter a **description** for the scope (e.g.: Can administer the Snowflake account).
    * Click **Add Scope**.
    * Save the scope as `AZURE_AD_SCOPE`.


key: _node_content
string_value:
{"id_": "f294c6d2-5ccc-4326-abb9-1b2fc15370b7", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "af6ae3a5-15a5-46d2-9c5f-62d3131e9351", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "0b7de66be9d9fe919e63bf18135e8c0e301b9be9ecaaa9563069ce6473610dfa", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "603ccd97-c475-49a5-aa9e-517dff59ead2", "node_type": "1", "metadata": {}, "hash": "6ced49d223edfee113df72f35c19edfe9a2b17df098e6a6cf3bab8009934d39b", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 5712, "end_char_idx": 8458, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
* The endpoints should be similar to `https://login.microsoftonline.com/90288a9b-97df-4c6d-b025-95713f21cef9/oauth2/v2.0/authorization` and `https://login.microsoftonline.com/90288a9b-97df-4c6d-b025-95713f21cef9/oauth2/v2.0/token`.
12. Click on **Expose an API **under **Manage**.
13. Click on the **Set** link next to **Application ID URI** to set the `Application ID URI`.
    * The `Application ID URI` must be unique within your organization’s directory, such as `https://your.company.com/4d2a8c2b-a5f4-4b86-93ca-294185f45f2e`. This value will be referred to as the `<SNOWFLAKE_APPLICATION_ID_URI>` in the subsequent configuration steps.
14. To add a Snowflake Role as an OAuth scope for OAuth flows where the programmatic client acts on behalf of a user, click on **Add a scope** to add a scope representing the Snowflake role.
    * Enter the scope by having the name of the Snowflake role with the `session:scope:` prefix. For example, for the Snowflake Analyst role, enter `session:scope:analyst`.
    * Select who can consent.
    * Enter a **display name** for the scope (e.g.: Account Admin).
    * Enter a **description** for the scope (e.g.: Can administer the Snowflake account).
    * Click **Add Scope**.
    * Save the scope as `AZURE_AD_SCOPE`. It should be a concatenation of your `Application ID URI` and your `Scope name`
15. In the **Overview** section, copy the `ClientID` from the **Application (client) ID** field. This will be known as the `OAUTH_CLIENT_ID` in the following steps.
16. Click on **Certificates & secrets** and then **New client secret**.
17. Add a description of the secret.
18. Select **730 days (24 months)**. For testing purposes, select secrets that don’t expire soon.
19. Click **Add**. Copy the secret. This will be known as the `OAUTH_CLIENT_SECRET` in the following steps.
20. For programmatic clients that will request an Access Token on behalf of a user, configure Delegated permissions for Applications as follows.
    * Click on **API Permissions**.
    * Click on **Add Permission**.
    * Click on **My APIs**.
    * Click on the **Snowflake OAuth Resource** that you created in [Configure the OAuth resource in Azure AD](https://docs.snowflake.com/en/user-guide/oauth-azure#configure-the-oauth-resource-in-azure-ad).
    * Click on the **Delegated Permissions** box.
    * Check on the Permission related to the Scopes defined in the Application that you wish to grant to this client.
    * Click **Add Permissions**.
    * Click on the **Grant Admin Consent** button to grant the permissions to the client. Note that for testing purposes, permissions are configured this way. However, in a production environment, granting permissions in this manner is not advisable.
    * Click **Yes**.


key: _node_content
string_value:
{"id_": "603ccd97-c475-49a5-aa9e-517dff59ead2", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "f294c6d2-5ccc-4326-abb9-1b2fc15370b7", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "20f8092363d4d61c19c00d701faf47e1f44499388ebeb75734565c825f376034", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "0740576b-175f-4c6f-a9cc-30154cf4e62e", "node_type": "1", "metadata": {}, "hash": "ba4a1f0791b11d46c5d1d5a42aae0e6c7fa1eef0985f61cf0d49ee9333b512f1", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6798, "end_char_idx": 9203, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
: Account Admin).
    * Enter a **description** for the scope (e.g.: Can administer the Snowflake account).
    * Click **Add Scope**.
    * Save the scope as `AZURE_AD_SCOPE`. It should be a concatenation of your `Application ID URI` and your `Scope name`
15. In the **Overview** section, copy the `ClientID` from the **Application (client) ID** field. This will be known as the `OAUTH_CLIENT_ID` in the following steps.
16. Click on **Certificates & secrets** and then **New client secret**.
17. Add a description of the secret.
18. Select **730 days (24 months)**. For testing purposes, select secrets that don’t expire soon.
19. Click **Add**. Copy the secret. This will be known as the `OAUTH_CLIENT_SECRET` in the following steps.
20. For programmatic clients that will request an Access Token on behalf of a user, configure Delegated permissions for Applications as follows.
    * Click on **API Permissions**.
    * Click on **Add Permission**.
    * Click on **My APIs**.
    * Click on the **Snowflake OAuth Resource** that you created in [Configure the OAuth resource in Azure AD](https://docs.snowflake.com/en/user-guide/oauth-azure#configure-the-oauth-resource-in-azure-ad).
    * Click on the **Delegated Permissions** box.
    * Check on the Permission related to the Scopes defined in the Application that you wish to grant to this client.
    * Click **Add Permissions**.
    * Click on the **Grant Admin Consent** button to grant the permissions to the client. Note that for testing purposes, permissions are configured this way. However, in a production environment, granting permissions in this manner is not advisable.
    * Click **Yes**.


## Create a security integration in Snowflake

Once the App Registration is complete in Azure Entra ID, the next step is to link that App Registration to Snowflake via an External OAuth Security Integration. The `external_oauth_audience_list` parameter of the security integration must match the **Application ID URI** that you specified while configuring Azure Entra ID. 

The **Issuer** and the **JWS Keys endpoint** will also come from values collected in the previous steps. The **User Mapping Attribute** can either be set to `EMAIL_ADDRESS` or `LOGIN_NAME`, and this is how user’s Microsoft login credentials will be mapped to their user in Snowflake to ensure permissions in Snowflake are honored by the access token issued to ChatGPT.


key: _node_content
string_value:
{"id_": "0740576b-175f-4c6f-a9cc-30154cf4e62e", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "603ccd97-c475-49a5-aa9e-517dff59ead2", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "94fce7394a27815467e4321a27d1f54f7178e96a1db8a0a6b63b4343156f5eb1", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "3e0d4e21-f535-4557-a39b-ab3eaa751580", "node_type": "1", "metadata": {}, "hash": "160816291367e70930ccb6d4f063599cd8b984d0880c5e14d140348086a9c0fa", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 7427, "end_char_idx": 11853, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
19. Click **Add**. Copy the secret. This will be known as the `OAUTH_CLIENT_SECRET` in the following steps.
20. For programmatic clients that will request an Access Token on behalf of a user, configure Delegated permissions for Applications as follows.
    * Click on **API Permissions**.
    * Click on **Add Permission**.
    * Click on **My APIs**.
    * Click on the **Snowflake OAuth Resource** that you created in [Configure the OAuth resource in Azure AD](https://docs.snowflake.com/en/user-guide/oauth-azure#configure-the-oauth-resource-in-azure-ad).
    * Click on the **Delegated Permissions** box.
    * Check on the Permission related to the Scopes defined in the Application that you wish to grant to this client.
    * Click **Add Permissions**.
    * Click on the **Grant Admin Consent** button to grant the permissions to the client. Note that for testing purposes, permissions are configured this way. However, in a production environment, granting permissions in this manner is not advisable.
    * Click **Yes**.


## Create a security integration in Snowflake

Once the App Registration is complete in Azure Entra ID, the next step is to link that App Registration to Snowflake via an External OAuth Security Integration. The `external_oauth_audience_list` parameter of the security integration must match the **Application ID URI** that you specified while configuring Azure Entra ID. 

The **Issuer** and the **JWS Keys endpoint** will also come from values collected in the previous steps. The **User Mapping Attribute** can either be set to `EMAIL_ADDRESS` or `LOGIN_NAME`, and this is how user’s Microsoft login credentials will be mapped to their user in Snowflake to ensure permissions in Snowflake are honored by the access token issued to ChatGPT. 


```python
CREATE OR REPLACE SECURITY INTEGRATION AZURE_OAUTH_INTEGRATION
  TYPE = EXTERNAL_OAUTH
  ENABLED = TRUE
  EXTERNAL_OAUTH_TYPE = 'AZURE'
  EXTERNAL_OAUTH_ISSUER = '<AZURE_AD_ISSUER>'
  EXTERNAL_OAUTH_JWS_KEYS_URL = '<AZURE_AD_JWS_KEY_ENDPOINT>'
  EXTERNAL_OAUTH_AUDIENCE_LIST = ('<SNOWFLAKE_APPLICATION_ID_URI>')
  EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM = 'upn'
  EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE = 'EMAIL_ADDRESS';
```

### Middleware information:

Make sure you go through the following steps in your Azure environment:

* Azure Portal or VS Code with access to create Azure Function Apps and Azure Entra App Registrations
* There is [a detailed section in this guide](#azure-function-app) related to deploying and designing the function required to wrap the response from Snowflake in order to return the query results as a CSV to ChatGPT. The Azure Function App allows your GPT to ingest larger datasets as ChatGPT can ingest more data from files responses rather than from application/json payloads. Additionally, those datasets will only be available for Data Analysis (aka Code Interpreter) with a response formatted as a CSV file.

### Azure Function App

Now that we have the GPT created and handled Azure/Snowflake authentication, we can create the Azure Function App itself to execute the SQL query and handle the response formatting enabling the GPT to download the result as a CSV for use with Data Analysis.

Follow this [Azure Cookbook Guide](https://cookbook.openai.com/examples/azure/functions) for further details deploying an Azure Function App. Below you will find sample code to add to the function.

This code is meant to be directional - while it should work out of the box, you should customize it based on the needs specific to your GPT and your IT setup.

### Application Code

You’ll need to setup the following flows in your Azure Function App:

* Extracting the token from the HTTP request and using it to connect to Snowflake
* Executing the SQL query and writing the results to a CSV
* Temporarily storing that CSV in Blob Storage*
* Generating a pre-signed URL to access that CSV securely*
* Responding with an openaiFileResponse

*These steps may not be required if you use the [file stream](https://platform.openai.com/docs/actions/getting-started/inline-option) option instead of the [url](https://platform.openai.com/docs/actions/getting-started/url-option) option for returning files to your GPT. More on this below.

Ensure you have the necessary libraries installed and imported into your script. In addition to Python standard libraries, this sample script leveraged the following:


key: _node_content
string_value:
{"id_": "3e0d4e21-f535-4557-a39b-ab3eaa751580", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "0740576b-175f-4c6f-a9cc-30154cf4e62e", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f50e2c0c707c52b912d2e54f5a9583c1f6cb4acfcf5eea52bf2f11a068ec1af1", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "ec627e04-e0ec-48be-b44f-00bb6661ff92", "node_type": "1", "metadata": {}, "hash": "db2cd53f39f9b2d703a48f52c21c00ce7d75ce0ac7f5d2e1c323d62735b45b55", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 11856, "end_char_idx": 14707, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
import azure.functions as func
from azure.storage.blob import BlobServiceClient, generate_blob_sas, BlobSasPermissions, ContentSettings
import snowflake.connector
import jwt    # pyjwt for token decoding
```

#### Connecting to Snowflake

To connect to Snowflake, you’ll need to extract the access token assigned from Azure Entra ID from the Authorization header and use that token when connecting to the Snowflake server. 

In this this example, Snowflake usernames are email addresses which simplifies the mapping of the Entra ID user extracted from the HTTP access token to the Snowflake user ID needed to connect. If this is not the case for your organization, you can map email addresses to Snowflake user IDs in your Python application.

My application was built to interface with a single Snowflake Account (i.e. ab12345.eastus2.azure) and Warehouse. If you need to access multiple accounts or warehouses, you may consider passing these parameters in your GPT action parameters so you can extract them from the HTTP request.


```python
# Extract the token from the Authorization header
auth_header = req.headers.get('Authorization')
token_type, token = auth_header.split()

try:
    # Extract email address from token to use for Snowflake user mapping
    # If Snowflake usernames are not emails, then identify the username accordingly
    decoded_token = jwt.decode(token, options={"verify_signature": False})
    email = decoded_token.get('upn') 
    
    conn = snowflake.connector.connect(
        user=email, # Snowflake username, i.e., user's email in my example
        account=SNOWFLAKE_ACCOUNT, # Snowflake account, i.e., ab12345.eastus2.azure
        authenticator="oauth",
        token=token,
        warehouse=SNOWFLAKE_WAREHOUSE # Replace with Snowflake warehouse
    )
    logging.info("Successfully connected to Snowflake.")
except Exception as e:
    logging.error(f"Failed to connect to Snowflake: {e}")
```

#### Execute query and save CSV

Once you connect to Snowflake you’ll need to execute the query and store the results into a CSV. While the role in Snowflake should prevent any chance of harmful queries, you may want to sanitize your query in your application (not included below) just as you would any other programmatic SQL query execution. 


```python
# Extract SQL query from request parameters or body
sql_query = req.params.get('sql_query')

try:
    # Use the specified warehouse
    cursor = conn.cursor()

    # Execute the query
    cursor.execute(sql_query)
    results = cursor.fetchall()
    column_names = [desc[0] for desc in cursor.description]
    logger.info(f"Query executed successfully: {sql_query}")

    # Convert results to CSV
    csv_file_path = write_results_to_csv(results, column_names)
except Exception as e:
    logger.error(f"Error executing query or processing data: {e}")


key: _node_content
string_value:
{"id_": "ec627e04-e0ec-48be-b44f-00bb6661ff92", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "3e0d4e21-f535-4557-a39b-ab3eaa751580", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "a02aba08243cf11dd1886ffd65cb0b66126a9fa50cf78415b495b5a27285c59d", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "dd3fcd90-2142-4f11-ac40-86efbf5cc624", "node_type": "1", "metadata": {}, "hash": "7ceb5b3788e60af1a7c855b8c884fe03bdbc362e2b87c6c9ad71d3e7fcca58b4", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 14147, "end_char_idx": 16341, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
# Extract SQL query from request parameters or body
sql_query = req.params.get('sql_query')

try:
    # Use the specified warehouse
    cursor = conn.cursor()

    # Execute the query
    cursor.execute(sql_query)
    results = cursor.fetchall()
    column_names = [desc[0] for desc in cursor.description]
    logger.info(f"Query executed successfully: {sql_query}")

    # Convert results to CSV
    csv_file_path = write_results_to_csv(results, column_names)
except Exception as e:
    logger.error(f"Error executing query or processing data: {e}")


def write_results_to_csv(results, column_names):
    try:
        # Create a temporary file
        temp_file = tempfile.NamedTemporaryFile(delete=False, mode='w', newline='')
        csv_writer = csv.writer(temp_file)
        csv_writer.writerow(column_names)  # Write the column headers
        csv_writer.writerows(results)      # Write the data rows
        temp_file.close()  # Close the file to flush the contents
        return temp_file.name  # Return file path
    except Exception as e:
        logger.error(f"Error writing results to CSV: {e}")
```

#### Storing the file in Blob Storage

There are 2 methods for returning files to ChatGPT for processing. You can either [stream](https://platform.openai.com/docs/actions/getting-started/inline-option) the base64 encoded data along with the mimeType and file name in the openaiFileResponse list response, or you can return a [list of URLs](https://platform.openai.com/docs/actions/getting-started/url-option). In this solution we’ll focus on the latter.

To do this, you’ll need to upload the CSV to Azure Blob Storage and return a pre-signed URL for accessing that file securely in ChatGPT. It is important to note that in order to download a URL in ChatGPT, you’ll need to ensure that URL includes a content_type and content_disposition, as in the below example. If you’d like to inspect whether a URL has the necessary headers, you can use ``curl -I <url>`` from any terminal.

You’ll need to get a connection String for your Azure storage bucket, as per instructions [here](https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string).


key: _node_content
string_value:
{"id_": "dd3fcd90-2142-4f11-ac40-86efbf5cc624", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "ec627e04-e0ec-48be-b44f-00bb6661ff92", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "30b3adb482f6abdb189496ecc2d0557ce19ba5d92e5bfa639255640168de2345", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "6c9f84ac-7165-49e0-9364-f09b5891cfe5", "node_type": "1", "metadata": {}, "hash": "8a7a916f14bc8b62d5cc7ad2017314f40fe72f2f78bfb7888b960bbeae191848", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 14710, "end_char_idx": 18402, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
def write_results_to_csv(results, column_names):
    try:
        # Create a temporary file
        temp_file = tempfile.NamedTemporaryFile(delete=False, mode='w', newline='')
        csv_writer = csv.writer(temp_file)
        csv_writer.writerow(column_names)  # Write the column headers
        csv_writer.writerows(results)      # Write the data rows
        temp_file.close()  # Close the file to flush the contents
        return temp_file.name  # Return file path
    except Exception as e:
        logger.error(f"Error writing results to CSV: {e}")
```

#### Storing the file in Blob Storage

There are 2 methods for returning files to ChatGPT for processing. You can either [stream](https://platform.openai.com/docs/actions/getting-started/inline-option) the base64 encoded data along with the mimeType and file name in the openaiFileResponse list response, or you can return a [list of URLs](https://platform.openai.com/docs/actions/getting-started/url-option). In this solution we’ll focus on the latter.

To do this, you’ll need to upload the CSV to Azure Blob Storage and return a pre-signed URL for accessing that file securely in ChatGPT. It is important to note that in order to download a URL in ChatGPT, you’ll need to ensure that URL includes a content_type and content_disposition, as in the below example. If you’d like to inspect whether a URL has the necessary headers, you can use ``curl -I <url>`` from any terminal.

You’ll need to get a connection String for your Azure storage bucket, as per instructions [here](https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string). 


```python
def upload_csv_to_azure(file_path, container_name, blob_name, connect_str):
    try:
        # Create the BlobServiceClient object which will be used to create a container client
        blob_service_client = BlobServiceClient.from_connection_string(connect_str)
        
        # Create a blob client using the local file name as the name for the blob
        blob_client = blob_service_client.get_blob_client(container=container_name, blob=blob_name)

        # Upload the file with specified content settings
        with open(file_path, "rb") as data:
            blob_client.upload_blob(data, overwrite=True, content_settings=ContentSettings(
                content_type='text/csv',
                content_disposition=f'attachment; filename="{blob_name}"'
            ))
        logger.info(f"Successfully uploaded {file_path} to {container_name}/{blob_name}")

        # Generate a SAS token for the blob
        sas_token = generate_blob_sas(
            account_name=blob_service_client.account_name,
            container_name=container_name,
            blob_name=blob_name,
            account_key=blob_service_client.credential.account_key,
            permission=BlobSasPermissions(read=True),
            expiry=datetime.datetime.utcnow() + datetime.timedelta(hours=1)  # Token valid for 1 hour
        )

        # Generate a presigned URL using the SAS token
        url = f"https://{blob_service_client.account_name}.blob.core.windows.net/{container_name}/{blob_name}?{sas_token}"
        logger.info(f"Generated presigned URL: {url}")

        return url
    except Exception as e:
        logger.error(f"Error uploading file to Azure Blob Storage: {e}")
        raise
```

#### Format openaiFileResponse

Lastly, you’ll need to format the response appropriately to instruct ChatGPT to process that response as a file or series of files. The openaiFileResponse is a list which can include up to 10 URLs (or base64 encodings if using the [inline option](https://platform.openai.com/docs/actions/getting-started/inline-option)).


key: _node_content
string_value:
{"id_": "6c9f84ac-7165-49e0-9364-f09b5891cfe5", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "dd3fcd90-2142-4f11-ac40-86efbf5cc624", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "75ddf880fb3bdf6489f3614ce2ca078c03f03c50e5e3a9687ddd8b425c20e355", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "6771a787-cb8a-4792-801d-48e1802ccdbe", "node_type": "1", "metadata": {}, "hash": "c9f5cc16f34fad6a7d06b6667e11c95ac09d31c7027e48750d87bc3b9b292740", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 18405, "end_char_idx": 20509, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
# Format the response so ChatGPT treats it as a file
response = {
    'openaiFileResponse': [csv_url]
}
cursor.close()
conn.close()
return func.HttpResponse(
    json.dumps(response), 
    status_code=200
)
```


There are a lot of moving pieces to this application, so testing your Azure Function App can be important. ChatGPT can be a difficult testing grounds given that requests and responses can sometimes be more opaque than needed for debugging. Initial testing of your application through cURL or Postman to invoke the HTTP request from a more controlled environment will allow you to debug and triage issues more easily. Once you determine that responses are being returned as expected in those tools, you are ready to build your GPT.

## ChatGPT Steps

### Custom GPT Instructions

Once you've created a Custom GPT, use the text below in the Instructions panel for inspiration. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

##### Example Instructions

It is important that ChatGPT understands your table schema to properly form SQL queries. There are different methods for doing so, and this Instruction set represents the most direct way. We are working to publish additional instructions for different versions of Snowflake GPTs you may want to build to allow for working with multiple different tables, schemas and databases, or to even learn dynamically for schemas that tend to change over time.

Below are some basic instructions when working with a single schema and table. This GPT has been optimized for a single use case (analyzing flight data from January 2013 out of NYC) which allows for the most simple instructions to provide the most reliable GPT performance.

You are an expert at writing SQL queries to fetch data from Snowflake. You help users convert their prompts into SQL queries. Any question around flight data will be converted into a Snowflake SQL query that hits the table `FLIGHTS.PUBLIC.JAN_2013_NYC`. Pass any query into the "sql_query" parameter


key: _node_content
string_value:
{"id_": "6771a787-cb8a-4792-801d-48e1802ccdbe", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "6c9f84ac-7165-49e0-9364-f09b5891cfe5", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "5567e4f817571c9a60630762ec589659bb8cc366a90c7010c62cd94e426f34a9", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "c78d8e30-3965-46db-bfec-c44ffe1d0166", "node_type": "1", "metadata": {}, "hash": "ea27476ccbd950edce14861b2c1e44513f6b6a6d833f1c72cd305141f7f0cf92", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 18628, "end_char_idx": 22289, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
There are a lot of moving pieces to this application, so testing your Azure Function App can be important. ChatGPT can be a difficult testing grounds given that requests and responses can sometimes be more opaque than needed for debugging. Initial testing of your application through cURL or Postman to invoke the HTTP request from a more controlled environment will allow you to debug and triage issues more easily. Once you determine that responses are being returned as expected in those tools, you are ready to build your GPT.

## ChatGPT Steps

### Custom GPT Instructions

Once you've created a Custom GPT, use the text below in the Instructions panel for inspiration. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

##### Example Instructions

It is important that ChatGPT understands your table schema to properly form SQL queries. There are different methods for doing so, and this Instruction set represents the most direct way. We are working to publish additional instructions for different versions of Snowflake GPTs you may want to build to allow for working with multiple different tables, schemas and databases, or to even learn dynamically for schemas that tend to change over time.

Below are some basic instructions when working with a single schema and table. This GPT has been optimized for a single use case (analyzing flight data from January 2013 out of NYC) which allows for the most simple instructions to provide the most reliable GPT performance.

You are an expert at writing SQL queries to fetch data from Snowflake. You help users convert their prompts into SQL queries. Any question around flight data will be converted into a Snowflake SQL query that hits the table `FLIGHTS.PUBLIC.JAN_2013_NYC`. Pass any query into the "sql_query" parameter


The schema of the table includes
```
ID	NUMBER	A unique identifier for each flight
YEAR	NUMBER	The year of the flight
MONTH	NUMBER	The month of the flight
DAY		NUMBER	The day of the month on which the flight departed
DEP_TIME	NUMBER	The actual departure time of the flight
SCHED_DEP_TIME	NUMBER	The scheduled departure time of the flight
DEP_DELAY	NUMBER	The departure delay in minutes (negative values indicate early departures)
ARR_TIME	NUMBER	The actual arrival time of the flight
SCHED_ARR_TIME	NUMBER	The scheduled arrival time of the flight
ARR_DELAY	NUMBER	The arrival delay in minutes (negative values indicate early arrivals)
CARRIER_CODE	TEXT	The carrier code of the airline
FLIGHT	NUMBER	The flight number
TAILNUM	TEXT	The aircraft tail number
ORIGIN_AIRPORT_CODE	TEXT	The origin airport code
DEST_AIRPORT_CODE	TEXT	The destination airport code
AIR_TIME	NUMBER	The total airtime of the flight in minutes
DISTANCE	NUMBER	The distance traveled by the flight in miles
HOUR	NUMBER	The hour part of the scheduled departure time
MINUTE	NUMBER	The minute part of the scheduled departure time
TIME_HOUR	NUMBER	The time at which the flight departed (rounded to the nearest hour)
CARRIER_NAME	TEXT	The full name of the airline carrier
ORIGIN_AIRPORT_NAME	TEXT	The full name of the origin airport
ORIGIN_REGION	TEXT	The region code of the origin airport
ORIGIN_MUNICIPALITY	TEXT	The city where the origin airport is located
ORIGIN_COORDINATES	TEXT	The geographical coordinates of the origin airport
DEST_AIRPORT_NAME	TEXT	The full name of the destination airport
DEST_REGION	TEXT	The region code of the destination airport
DEST_MUNICIPALITY	TEXT	The city where the destination airport is located
DEST_COORDINATES	TEXT	The geographical coordinates of the destination airport
```


key: _node_content
string_value:
{"id_": "c78d8e30-3965-46db-bfec-c44ffe1d0166", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "6771a787-cb8a-4792-801d-48e1802ccdbe", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "0570e1e6ad773044360241e2c72ca492d9c5f9c0404497a2bd0462043ac8faa1", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "8324e94e-c165-425a-8170-a31d76cc653b", "node_type": "1", "metadata": {}, "hash": "f63f6f7630c887d06ae59fabef1b20ddbf4699f06dd3a442b99a1a47b37efb15", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 22292, "end_char_idx": 25598, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
When a user asks for data around flights, perform the following:


1. Use the `executeSQL` action to send a POST request to the Azure function endpoint
2. Receive the file that is returned as part of the Action response. Display it as a spreadsheet
3. Perform analysis on the file and provide the necessary information that the user has asked for


The user will wish to ask questions about the data in code interpreter, so use that for any data analysis insights from the dataset you pulled.

### OpenAPI Schema

Once you've created a Custom GPT, copy the text below in the Actions panel, replacing the placeholder values with your specific function details and updating your parameters based on any additional inputs you built into your Azure Function App. 

Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
openapi: 3.1.0
info:
  title: Snowflake GPT API
  description: API to execute SQL queries on Snowflake and get the results as a CSV file URL.
  version: 1.0.0
servers:
  - url: https://<server-name>.azurewebsites.net
    description: Azure Function App server running Snowflake integration application
paths:
  /api/<function_name>?code=<code>:
    post:
      operationId: executeSQL
      summary: Executes a SQL query on Snowflake and returns the result file URL as a CSV.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                sql_query:
                  type: string
                  description: The SQL query to be executed on Snowflake.
              required:
                - sql_query
      responses:
        '200':
          description: Successfully executed the query.
          content:
            application/json:
              schema:
                type: object
                properties:
                  openaiFileResponse:
                    type: array
                    items:
                      type: string
                      format: uri
                    description: Array of URLs pointing to the result files.
        '401':
          description: Unauthorized. Missing or invalid authentication token.
        '400':
          description: Bad Request. The request was invalid or cannot be otherwise served.
        '500':
          description: Internal Server Error. An error occurred on the server.
components:
  schemas: {} 
```

### FAQ & Troubleshooting

* Files returned to ChatGPT are limited in size to 10MB. Your request may fail if the file returned is larger than that. Ensure to include LIMITs on your SQL commands if you find you are running into these limitations.
* _Why is the Azure Function App requred in the first place?_ ChatGPT’s Data Analysis feature (aka Code Interpreter) depends on a secure Python environment that is separate from the model’s context window. Data passed to Data Analysis must be done so by uploading a file today. GPT actions returning data must then return that data as a CSV or other data file type. In order to return a file via GPT action, the response must be wrapped in an `openaiFileResponse` object. This requires custom code to properly format the response.


key: _node_content
string_value:
{"id_": "8324e94e-c165-425a-8170-a31d76cc653b", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "af2d2469-8f83-44e0-8bbf-a032755257cf", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e51bb0df04ca68cc266c89829e99d51cb7e4dbda8766927640621bb1521570b9", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c78d8e30-3965-46db-bfec-c44ffe1d0166", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_middleware.ipynb", "title": "GPT Actions - Snowflake middleware", "tokens": 5944, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "bf85947818fb44162632c67b2fdc242522a4567294cea3a2c84c2ec8920a2918", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 23700, "end_char_idx": 27346, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                sql_query:
                  type: string
                  description: The SQL query to be executed on Snowflake.
              required:
                - sql_query
      responses:
        '200':
          description: Successfully executed the query.
          content:
            application/json:
              schema:
                type: object
                properties:
                  openaiFileResponse:
                    type: array
                    items:
                      type: string
                      format: uri
                    description: Array of URLs pointing to the result files.
        '401':
          description: Unauthorized. Missing or invalid authentication token.
        '400':
          description: Bad Request. The request was invalid or cannot be otherwise served.
        '500':
          description: Internal Server Error. An error occurred on the server.
components:
  schemas: {} 
```

### FAQ & Troubleshooting

* Files returned to ChatGPT are limited in size to 10MB. Your request may fail if the file returned is larger than that. Ensure to include LIMITs on your SQL commands if you find you are running into these limitations.
* _Why is the Azure Function App requred in the first place?_ ChatGPT’s Data Analysis feature (aka Code Interpreter) depends on a secure Python environment that is separate from the model’s context window. Data passed to Data Analysis must be done so by uploading a file today. GPT actions returning data must then return that data as a CSV or other data file type. In order to return a file via GPT action, the response must be wrapped in an `openaiFileResponse` object. This requires custom code to properly format the response.
* _My company uses a different cloud provider than Azure._ For connecting other middleware functions to ChatGPT via GPT action, please refer to other [AWS](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_aws_function) or [GCP](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_google_cloud_function) middleware cookbooks. You can use the concepts discussed in this cookbook to advise on considerations when building your middleware app, but connecting that middleware to Snowflake may be different for different cloud providers. For example, Snowflake built an External OAuth integration specifically for linking with Azure Entra ID. 
* _How do I limit the datasets that my GPT has access to?_ It can be imporant to limit the scope of access ChatGPT has within Snowflake. There are a few ways to do this:
    * Snowflake roles can limit who has access to which tables, and will be respected by the GPT user’s access token provisioned by Azure Entra ID
    * In your middleware function you can add sanity checks to verify the tables accessed are approved by for that application
    * You may want to generate an entirely new Database/Warehouse specific to integrating with ChatGPT that is scrubbed of anything sensitive, such as PII.
* _Schema calls the wrong warehouse or dataset:_ If ChatGPT calls the wrong warehouse or database, consider updating your instructions to make it more explicit either (a) which warehouse / database should be called or (b) to require the user provide those exact details before it runs the query


_Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look._


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb


key: _node_content
string_value:
{"id_": "a62cdc94-00d1-47dd-a992-6ec570ec122f", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "d5c0d381-a67c-4a67-ac0a-d8d5fe690779", "node_type": "1", "metadata": {}, "hash": "9608d55c1f2b80d30ebe7365dc5c7671ef9154d3ef96c80bef4755b36e919a24", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 3151, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)

## Introduction

This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information: 
- [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
- [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
- [Example of Building a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)

This solution enables a GPT action to answer a user’s question with the context of files the user can access in SharePoint or Office365, using Microsoft’s Graph API [search capabilities](https://learn.microsoft.com/en-us/graph/api/resources/search-api-overview?view=graph-rest-1.0) and the ability to [retrieve files](https://learn.microsoft.com/en-us/graph/api/driveitem-get?view=graph-rest-1.0\&tabs=http). It uses Azure Functions to process the Graph API response and convert it to a human readable format or structure it in a way ChatGPT understands. This code is meant to be directional, and you should modify it to your requirements.

This solution uses the ability to[ retrieve files in Actions](https://platform.openai.com/docs/actions/sending-files) and use them as if you had uploaded them directly to a conversation. The Azure Function returns a base64 string that ChatGPT converts into a file. This solution can handle both structured and unstructured data, but does have size volume limitations (see docs [here](https://platform.openai.com/docs/actions/sending-files))

### Value + Example Business Use Cases

**Value**: Users can now leverage ChatGPT's natural language capability to connect directly to files in Sharpeoint

**Example Use Cases**: 
- A user needs to look up which files relate to a certain topic
- A user needs an answer to a critical question, buried deep in documents

## Architecture / Example

![](../../../images/solution_1.gif)


This solution uses a Node.js Azure Function to, based on the logged in user:

1. Search for a relevant file that the user has access to, based on the user’s initial question. 

2. For each file that is found, convert it to a base64 string.

3. Format the data in the structure ChatGPT is expecting [here](https://platform.openai.com/docs/actions/sending-files/inline-option).

4. Return that to ChatGPT. The GPT then can use those files as if you had uploaded it to the conversation.

![](../../../images/solution_1_architecture.png)

## Application Information

### Application Key Links

Check out these links from the application before you get started:
- Application Website: https://www.microsoft.com/en-us/microsoft-365/sharepoint/collaboration
- Application API Documentation: https://learn.microsoft.com/en-us/previous-versions/office/developer/sharepoint-rest-reference/

### Application Prerequisites

Before you get started, make sure you go through the following steps in your application environment:
- Access to a Sharepoint environment 
- Postman (and knowledge of APIs and OAuth)


key: _node_content
string_value:
{"id_": "d5c0d381-a67c-4a67-ac0a-d8d5fe690779", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "a62cdc94-00d1-47dd-a992-6ec570ec122f", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "11b6c96af5a58077e72af8ea1e860949b5c1f0cd9e3361319b4ad277fece3e3c", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "df609fa9-8745-404c-9a3d-f6e79f20a6a0", "node_type": "1", "metadata": {}, "hash": "34da1156f1121dfd44962762f258e9bbd4c662859a2c3abe2f2e88a259e51727", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 2056, "end_char_idx": 5474, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
This solution uses a Node.js Azure Function to, based on the logged in user:

1. Search for a relevant file that the user has access to, based on the user’s initial question. 

2. For each file that is found, convert it to a base64 string.

3. Format the data in the structure ChatGPT is expecting [here](https://platform.openai.com/docs/actions/sending-files/inline-option).

4. Return that to ChatGPT. The GPT then can use those files as if you had uploaded it to the conversation.

![](../../../images/solution_1_architecture.png)

## Application Information

### Application Key Links

Check out these links from the application before you get started:
- Application Website: https://www.microsoft.com/en-us/microsoft-365/sharepoint/collaboration
- Application API Documentation: https://learn.microsoft.com/en-us/previous-versions/office/developer/sharepoint-rest-reference/

### Application Prerequisites

Before you get started, make sure you go through the following steps in your application environment:
- Access to a Sharepoint environment 
- Postman (and knowledge of APIs and OAuth)


## Middleware Information

If you follow the [search concept files guide](https://learn.microsoft.com/en-us/graph/search-concept-files), the [Microsoft Graph Search API](https://learn.microsoft.com/en-us/graph/search-concept-files) returns references to files that fit the criteria, but not the file contents themselves. Therefore, middleware is required, rather than hitting the MSFT endpoints directly.

We need to restructure the response from that API so that it matches the expected structure in `openaiFileResponse` outlined [here](https://platform.openai.com/docs/actions/getting-started/inline-option).

### Additional Steps

#### Set up Azure Function

1. Set up an Azure Function using the steps in the [Azure Function cookbook](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_azure_function)

#### Add in Function Code

Now that you have an authenticated Azure Function, we can update the function to search SharePoint / O365

2. Go to your test function and paste in the code from [this file](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_one_file_retrieval.js). Save the function.

> **This code is meant to be directional** - while it should work out of the box, it is designed to be customized to your needs (see examples towards the end of this document).

3. Set up the following env variables by going to the **Configuration** tab on the left under **Settings.** Note that this may be listed directly in **Environment Variables** depending on your Azure UI.

    1. `TENANT_ID`: copied from previous section

    2. `CLIENT_ID`: copied from previous section

4. Go to the **Console** tab under the **Development Tools**

    1. Install the following packages in console

       1. `npm install @microsoft/microsoft-graph-client`

       2. `npm install axios`

5. Once this is complete, try calling the function (POST call) from Postman again, putting the below into body (using a query and search term you think will generate responses).

     ```json
    {
        "searchTerm": "<choose a search term>"
    }
    ```

6. If you get a response, you are ready to set this up with a Custom GPT! See the ChatGPT Section of the Azure Function page for more details on setting this up


## More Detailed Walkthrough


key: _node_content
string_value:
{"id_": "df609fa9-8745-404c-9a3d-f6e79f20a6a0", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "d5c0d381-a67c-4a67-ac0a-d8d5fe690779", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f6044fe73cbf6bc4160282038fa3b1189e858d1e80a6c52f07756d1c1450eead", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "c7495575-337a-4e4d-aaaf-b13a99388f7c", "node_type": "1", "metadata": {}, "hash": "98227c9a5ba660ee865051b4ae2f8386c509d94287b093f95cdacb8180c472e0", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 5446, "end_char_idx": 7934, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
## More Detailed Walkthrough


The below walks through setup instructions and walkthrough unique to this solution. You can find the entire code [here](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_one_file_retrieval.js).

### Code Walkthrough

The below walks through the different parts of the function. Before you begin, ensure you have the required packages installed and environment variables set up (see the Installation Steps section).


#### Implementing the Authentication 

Below we have a few helper functions that we’ll use in the function.


##### Initializing the Microsoft Graph Client

Create a function to initialize the Graph client with an access token. This will be used to search through Office 365 and SharePoint.

```javascript
const { Client } = require('@microsoft/microsoft-graph-client');

function initGraphClient(accessToken) {
    return Client.init({
        authProvider: (done) => {
            done(null, accessToken);
        }
    });
}
```

##### Obtaining an On-Behalf-Of (OBO) Token

This function uses an existing bearer token to request an OBO token from Microsoft's identity platform. This enables passing through the credentials to ensure the search only returns files the logged-in user can access.

```javascript
const axios = require('axios');
const qs = require('querystring');

async function getOboToken(userAccessToken) {
    const { TENANT_ID, CLIENT_ID, MICROSOFT_PROVIDER_AUTHENTICATION_SECRET } = process.env;
    const params = {
        client_id: CLIENT_ID,
        client_secret: MICROSOFT_PROVIDER_AUTHENTICATION_SECRET,
        grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        assertion: userAccessToken,
        requested_token_use: 'on_behalf_of',
        scope: 'https://graph.microsoft.com/.default'
    };

    const url = `https\://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`;
    try {
        const response = await axios.post(url, qs.stringify(params), {
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });
        return response.data.access\_token;
    } catch (error) {
        console.error('Error obtaining OBO token:', error.response?.data || error.message);
        throw error;
    }
}
```

#### Retrieving Content from O365 / SharePoint Items

This function fetches the content of drive items, converts it to a base64 string, and restructures to match the `openaiFileResponse` format.


key: _node_content
string_value:
{"id_": "c7495575-337a-4e4d-aaaf-b13a99388f7c", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "df609fa9-8745-404c-9a3d-f6e79f20a6a0", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "f82efdec559fb9467d9c44926942d0f462aaf67983ecddc7b012e428c89797fb", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "31768d71-edab-44e0-85eb-a2fe51e8f0e2", "node_type": "1", "metadata": {}, "hash": "4938b5c03c6fa5a7a2c2b52ae6043e6e7fc2daf7327352fc674fde37ce3deabc", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6240, "end_char_idx": 9420, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```javascript
const { Client } = require('@microsoft/microsoft-graph-client');

function initGraphClient(accessToken) {
    return Client.init({
        authProvider: (done) => {
            done(null, accessToken);
        }
    });
}
```

##### Obtaining an On-Behalf-Of (OBO) Token

This function uses an existing bearer token to request an OBO token from Microsoft's identity platform. This enables passing through the credentials to ensure the search only returns files the logged-in user can access.

```javascript
const axios = require('axios');
const qs = require('querystring');

async function getOboToken(userAccessToken) {
    const { TENANT_ID, CLIENT_ID, MICROSOFT_PROVIDER_AUTHENTICATION_SECRET } = process.env;
    const params = {
        client_id: CLIENT_ID,
        client_secret: MICROSOFT_PROVIDER_AUTHENTICATION_SECRET,
        grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        assertion: userAccessToken,
        requested_token_use: 'on_behalf_of',
        scope: 'https://graph.microsoft.com/.default'
    };

    const url = `https\://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`;
    try {
        const response = await axios.post(url, qs.stringify(params), {
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        });
        return response.data.access\_token;
    } catch (error) {
        console.error('Error obtaining OBO token:', error.response?.data || error.message);
        throw error;
    }
}
```

#### Retrieving Content from O365 / SharePoint Items

This function fetches the content of drive items, converts it to a base64 string, and restructures to match the `openaiFileResponse` format.
```javascript
const getDriveItemContent = async (client, driveId, itemId, name) => {
   try
       const filePath = `/drives/${driveId}/items/${itemId}`;
       const downloadPath = filePath + `/content`
       // this is where we get the contents and convert to base64
       const fileStream = await client.api(downloadPath).getStream();
       let chunks = [];
           for await (let chunk of fileStream) {
               chunks.push(chunk);
           }
       const base64String = Buffer.concat(chunks).toString('base64');
       // this is where we get the other metadata to include in response
       const file = await client.api(filePath).get();
       const mime_type = file.file.mimeType;
       const name = file.name;
       return {"name":name, "mime_type":mime_type, "content":base64String}
   } catch (error) {
       console.error('Error fetching drive content:', error);
       throw new Error(`Failed to fetch content for ${name}: ${error.message}`);
   }
```

#### Creating the Azure Function to Handle Requests

Now that we have all these helper functions, the Azure Function will orchestrate the flow, by authenticating the user, performing the search, and iterating through the search results to extract the text and retrieve the relevant parts of the text to the GPT.

**Handling HTTP Requests:** The function starts by extracting the query and searchTerm from the HTTP request. It checks if the Authorization header is present and extracts the bearer token.


key: _node_content
string_value:
{"id_": "31768d71-edab-44e0-85eb-a2fe51e8f0e2", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c7495575-337a-4e4d-aaaf-b13a99388f7c", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "a465afd983581991f057bb5bbcf8e257f9891486ccbc58bb8061432724f14130", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "181d2338-73a1-43e4-a200-4216e57ad4c0", "node_type": "1", "metadata": {}, "hash": "7db814d396dcc8e6ee55df676c6bb3bd6db91b0492137bfde266e988f624d8bb", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 7935, "end_char_idx": 10597, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```javascript
const getDriveItemContent = async (client, driveId, itemId, name) => {
   try
       const filePath = `/drives/${driveId}/items/${itemId}`;
       const downloadPath = filePath + `/content`
       // this is where we get the contents and convert to base64
       const fileStream = await client.api(downloadPath).getStream();
       let chunks = [];
           for await (let chunk of fileStream) {
               chunks.push(chunk);
           }
       const base64String = Buffer.concat(chunks).toString('base64');
       // this is where we get the other metadata to include in response
       const file = await client.api(filePath).get();
       const mime_type = file.file.mimeType;
       const name = file.name;
       return {"name":name, "mime_type":mime_type, "content":base64String}
   } catch (error) {
       console.error('Error fetching drive content:', error);
       throw new Error(`Failed to fetch content for ${name}: ${error.message}`);
   }
```

#### Creating the Azure Function to Handle Requests

Now that we have all these helper functions, the Azure Function will orchestrate the flow, by authenticating the user, performing the search, and iterating through the search results to extract the text and retrieve the relevant parts of the text to the GPT.

**Handling HTTP Requests:** The function starts by extracting the query and searchTerm from the HTTP request. It checks if the Authorization header is present and extracts the bearer token.

**Authentication:** Using the bearer token, it obtains an OBO token from Microsoft's identity platform using getOboToken defined above.

**Initializing the Graph Client:** With the OBO token, it initializes the Microsoft Graph client using initGraphClient defined above.

**Document Search:** It constructs a search query and sends it to the Microsoft Graph API to find documents based on the searchTerm.

**Document Processing**: For each document returned by the search:

- It retrieves the document content using getDriveItemContent.

- It converts the document to base64 string and restructures it to match the `openaiFileResponse` structure.

**Response**: The function sends them back in the HTTP response.
```javascript
module.exports = async function (context, req) {
   // const query = req.query.query || (req.body && req.body.query);
   const searchTerm = req.query.searchTerm || (req.body && req.body.searchTerm);
   if (!req.headers.authorization) {
       context.res = {
           status: 400,
           body: 'Authorization header is missing'
       };
       return;
   }
   /// The below takes the token passed to the function, to use to get an OBO token.


key: _node_content
string_value:
{"id_": "181d2338-73a1-43e4-a200-4216e57ad4c0", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "31768d71-edab-44e0-85eb-a2fe51e8f0e2", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "1146db340ffb799d6ea5139bbc43707e228ac9d080ba851b216bad10f6e7344c", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "8629812f-e020-4a28-a63e-b99a2236daed", "node_type": "1", "metadata": {}, "hash": "33d7e4d8119d1ad5d98e5b33283c58f314f50b8bab21a98a4d791cb812724687", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 9231, "end_char_idx": 11568, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: _node_content
string_value:
{"id_": "8629812f-e020-4a28-a63e-b99a2236daed", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "181d2338-73a1-43e4-a200-4216e57ad4c0", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "27a4b0314a22444216322032223f48b34d1240b851918078bf300702442bd8ee", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "8301a6d5-efb4-4a2b-8a1a-4e6fa7953f18", "node_type": "1", "metadata": {}, "hash": "d6bc1de29bb1b4e65039297ca5c50478d93fad34849cb001480d93da08a7db9f", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 9694, "end_char_idx": 14970, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
**Document Search:** It constructs a search query and sends it to the Microsoft Graph API to find documents based on the searchTerm.

**Document Processing**: For each document returned by the search:

- It retrieves the document content using getDriveItemContent.

- It converts the document to base64 string and restructures it to match the `openaiFileResponse` structure.

**Response**: The function sends them back in the HTTP response.
```javascript
module.exports = async function (context, req) {
   // const query = req.query.query || (req.body && req.body.query);
   const searchTerm = req.query.searchTerm || (req.body && req.body.searchTerm);
   if (!req.headers.authorization) {
       context.res = {
           status: 400,
           body: 'Authorization header is missing'
       };
       return;
   }
   /// The below takes the token passed to the function, to use to get an OBO token.
   const bearerToken = req.headers.authorization.split(' ')[1];
   let accessToken;
   try {
       accessToken = await getOboToken(bearerToken);
   } catch (error) {
       context.res = {
           status: 500,
           body: `Failed to obtain OBO token: ${error.message}`
       };
       return;
   }
   // Initialize the Graph Client using the initGraphClient function defined above
   let client = initGraphClient(accessToken);
   // this is the search body to be used in the Microsft Graph Search API: https://learn.microsoft.com/en-us/graph/search-concept-files
   const requestBody = {
       requests: [
           {
               entityTypes: ['driveItem'],
               query: {
                   queryString: searchTerm
               },
               from: 0,
               // the below is set to summarize the top 10 search results from the Graph API, but can configure based on your documents.
               size: 10
           }
       ]
   };


   try {
       // This is where we are doing the search
       const list = await client.api('/search/query').post(requestBody);
       const processList = async () => {
           // This will go through and for each search response, grab the contents of the file and summarize with gpt-3.5-turbo
           const results = [];
           await Promise.all(list.value[0].hitsContainers.map(async (container) => {
               for (const hit of container.hits) {
                   if (hit.resource["@odata.type"] === "#microsoft.graph.driveItem") {
                       const { name, id } = hit.resource;
                       // The below is where the file lives
                       const driveId = hit.resource.parentReference.driveId;
                       // we use the helper function we defined above to get the contents, convert to base64, and restructure it
                       const contents = await getDriveItemContent(client, driveId, id, name);
                       results.push(contents)
               }
           }));
           return results;
       };
       let results;
       if (list.value[0].hitsContainers[0].total == 0) {
           // Return no results found to the API if the Microsoft Graph API returns no results
           results = 'No results found';
       } else {
           // If the Microsoft Graph API does return results, then run processList to iterate through.
           results = await processList();
           // this is where we structure the response so ChatGPT knows they are files
           results = {'openaiFileResponse': results}
       }
       context.res = {
           status: 200,
           body: results
       };
   } catch (error) {
       context.res = {
           status: 500,
           body: `Error performing search or processing results: ${error.message}`,
       };
   }
};
```
### Customizations

Below are some potential areas to customize. 

- You can customize the GPT prompt to search again a certain amount of times if nothing is found.

- You can customize the code to only search through specific SharePoint sites or O365 Drives by customizing the search query. This will help focus the search and improve the retrieval. The function as setup now looks through all files the logged-in user can access.

- You can update the code to only return certain types of files. For example, only return structured data / CSVs. 

- You can customize the amount of files it searches through within the call to Microsoft Graph. Note that you should only put a maximum of 10 files based on the documentation [here](https://platform.openai.com/docs/actions/getting-started). 

### Considerations

Note that all the same limitations of Actions apply here, with regards to returning 100K characters or less and the [45 second timeout](https://platform.openai.com/docs/actions/production/timeouts).

- Make sure you read the documentation here around [returning files](https://platform.openai.com/docs/actions/sending-files) and [file uploads](https://help.openai.com/en/articles/8555545-file-uploads-faq), as those limitations apply here.

## ChatGPT Steps

### Custom GPT Instructions 

Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


key: _node_content
string_value:
{"id_": "8301a6d5-efb4-4a2b-8a1a-4e6fa7953f18", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "8629812f-e020-4a28-a63e-b99a2236daed", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "5f90dc8e6e6778ed989f356dba8514c32d855e25e802cc8f0515a561ef55a127", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "22550505-1aee-4654-9a11-79030f5ebc43", "node_type": "1", "metadata": {}, "hash": "239ad5ff878a9dde46688b3b0d0a27073511141f13099a810a28471167ce0fec", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 14973, "end_char_idx": 18814, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
You are a Q&A helper that helps answer users questions. You have access to a documents repository through your API action. When a user asks a question, you pass in the "searchTerm" a single keyword or term you think you should use for the search.

****

Scenario 1: There are answers

If your action returns results, then you take the results from the action and try to answer the users question. 

****

Scenario 2: No results found

If the response you get from the action is "No results found", stop there and let the user know there were no results and that you are going to try a different search term, and explain why. You must always let the user know before conducting another search.

Example:

****

I found no results for "DEI". I am now going to try [insert term] because [insert explanation]

****

Then, try a different searchTerm that is similar to the one you tried before, with a single word. 

Try this three times. After the third time, then let the user know you did not find any relevant documents to answer the question, and to check SharePoint. 
Be sure to be explicit about what you are searching for at each step.

****

In either scenario, try to answer the user's question. If you cannot answer the user's question based on the knowledge you find, let the user know and ask them to go check the HR Docs in SharePoint. 
```

### OpenAPI Schema 

Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

This expects a response that matches the file retrieval structure in our doc [here](https://platform.openai.com/docs/actions/sending-files) and passes in a `searchTerm` parameter to inform the search.
>Make sure to switch the function app name, function name and code based on link copied in screenshot above


```python
openapi: 3.1.0
info:
  title: SharePoint Search API
  description: API for searching SharePoint documents.
  version: 1.0.0
servers:
  - url: https://{your_function_app_name}.azurewebsites.net/api
    description: SharePoint Search API server
paths:
  /{your_function_name}?code={enter your specific endpoint id here}:
    post:
      operationId: searchSharePoint
      summary: Searches SharePoint for documents matching a query and term.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                searchTerm:
                  type: string
                  description: A specific term to search for within the documents.
      responses:
        '200':
          description: A CSV file of query results encoded in base64.
          content:
            application/json:
              schema:
                type: object
                properties:
                  openaiFileResponseData:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: The name of the file.
                        mime_type:
                          type: string
                          description: The MIME type of the file.
                        content:
                          type: string
                          format: byte
                          description: The base64 encoded contents of the file.
        '400':
          description: Bad request when the SQL query parameter is missing.
        '413':
          description: Payload too large if the response exceeds the size limit.
        '500':
          description: Server error when there are issues executing the query or encoding the results.


key: _node_content
string_value:
{"id_": "22550505-1aee-4654-9a11-79030f5ebc43", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "8301a6d5-efb4-4a2b-8a1a-4e6fa7953f18", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "5e234e326775f0b4eb6ab673355c3596e6138b1d72973d3121ddd88d9097b096", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f84c6d94-f492-46d3-a8ee-dee3c0344401", "node_type": "1", "metadata": {}, "hash": "b13c8625b9d2d7684307167b38be391b31451b3645dcb08ae4cc7d001b551ee3", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 16896, "end_char_idx": 20548, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
openapi: 3.1.0
info:
  title: SharePoint Search API
  description: API for searching SharePoint documents.
  version: 1.0.0
servers:
  - url: https://{your_function_app_name}.azurewebsites.net/api
    description: SharePoint Search API server
paths:
  /{your_function_name}?code={enter your specific endpoint id here}:
    post:
      operationId: searchSharePoint
      summary: Searches SharePoint for documents matching a query and term.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                searchTerm:
                  type: string
                  description: A specific term to search for within the documents.
      responses:
        '200':
          description: A CSV file of query results encoded in base64.
          content:
            application/json:
              schema:
                type: object
                properties:
                  openaiFileResponseData:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: The name of the file.
                        mime_type:
                          type: string
                          description: The MIME type of the file.
                        content:
                          type: string
                          format: byte
                          description: The base64 encoded contents of the file.
        '400':
          description: Bad request when the SQL query parameter is missing.
        '413':
          description: Payload too large if the response exceeds the size limit.
        '500':
          description: Server error when there are issues executing the query or encoding the results.
```

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

*See above and on the [Azure Function cookbook](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_azure_function) for more detailed instructions on authentication.*

## FAQ & Troubleshooting

- Why are you using the Microsoft Graph API in your code instead of the [SharePoint API](https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/get-to-know-the-sharepoint-rest-service?tabs=csom)?

  - The SharePoint API is legacy - per the Microsoft documentation [here](https://learn.microsoft.com/en-us/sharepoint/dev/apis/sharepoint-rest-graph), “For SharePoint Online, innovation using a REST API against SharePoint is driven via the Microsoft Graph REST API's.” The Graph API gives us more flexibility, and the SharePoint API still runs into the same file issues listed in the [Why is this necessary instead of interacting with the Microsoft Graph API directly?](#why-is-this-necessary-instead-of-interacting-with-the-microsoft-api-directly) section.

- What types of files does this support?

  It follows the same guidelines as the documentation [here](https://help.openai.com/en/articles/8555545-file-uploads-faq) about file uploads. 

- Why do I need to request an OBO token?

  - When you try to use the same token to authenticate to the Graph API as the one you use to authenticate into the Azure Function, you get an “invalid audience” token. This is because the audience for the token can only be user\_impersonation.


key: _node_content
string_value:
{"id_": "f84c6d94-f492-46d3-a8ee-dee3c0344401", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "f8e76820-fce1-4d88-bab9-2784d99832f3", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "44d7328e4b5dce8556b9ba5a13491cc0c5403634e0e06500d6162de7f3cc9f20", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "22550505-1aee-4654-9a11-79030f5ebc43", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_doc.ipynb", "title": "GPT Action Library: Sharepoint (Return file for Data Analysis / Document Summarization)", "tokens": 4540, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "5c352afb12ac9c7a7bd437a1fb9c093783ec1a6da223932a34f37a0d63a72db8", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 18705, "end_char_idx": 21307, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
'500':
          description: Server error when there are issues executing the query or encoding the results.
```

## Authentication Instructions

Below are instructions on setting up authentication with this 3rd party application. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.

*See above and on the [Azure Function cookbook](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_azure_function) for more detailed instructions on authentication.*

## FAQ & Troubleshooting

- Why are you using the Microsoft Graph API in your code instead of the [SharePoint API](https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/get-to-know-the-sharepoint-rest-service?tabs=csom)?

  - The SharePoint API is legacy - per the Microsoft documentation [here](https://learn.microsoft.com/en-us/sharepoint/dev/apis/sharepoint-rest-graph), “For SharePoint Online, innovation using a REST API against SharePoint is driven via the Microsoft Graph REST API's.” The Graph API gives us more flexibility, and the SharePoint API still runs into the same file issues listed in the [Why is this necessary instead of interacting with the Microsoft Graph API directly?](#why-is-this-necessary-instead-of-interacting-with-the-microsoft-api-directly) section.

- What types of files does this support?

  It follows the same guidelines as the documentation [here](https://help.openai.com/en/articles/8555545-file-uploads-faq) about file uploads. 

- Why do I need to request an OBO token?

  - When you try to use the same token to authenticate to the Graph API as the one you use to authenticate into the Azure Function, you get an “invalid audience” token. This is because the audience for the token can only be user\_impersonation.

  - To address this, the function requests a new token scoped to Files.Read.All within the app using the [On Behalf Of flow](https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-on-behalf-of-flow). This will inherit the permissions of the logged in user, meaning this function will only search through files the logged-in user has access to. 

  - We are purposefully requesting a new On Behalf Of token with each request, because Azure Function Apps are meant to be stateless. You could potentially integrate this with Azure Key Vault to store the secret and retrieve programmatically. 

*Are there integrations that you’d like us to prioritize? Are there errors in our integrations? File a PR or issue in our github, and we’ll take a look.*


key: url
string_value:
https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb


key: _node_content
string_value:
{"id_": "49e13756-307e-49b0-b9eb-9be6c95b280b", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "6efb3b20-4ce5-4e05-9a05-7cec3cd5a986", "node_type": "1", "metadata": {}, "hash": "bed520f537ed22339b08d0cc0bf67a427e10edf39956af066092607a6b2f047b", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2472, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
# GPT Action Library: Notion

## Introduction

This page provides an instruction & guide for developers building a GPT Action for a specific application. Before you proceed, make sure to first familiarize yourself with the following information: 
- [Introduction to GPT Actions](https://platform.openai.com/docs/actions)
- [Introduction to GPT Actions Library](https://platform.openai.com/docs/actions/actions-library)
- [Example of Buliding a GPT Action from Scratch](https://platform.openai.com/docs/actions/getting-started)

This particular GPT Action provides an overview of how to connect to **Notion**. This Action takes a user’s question, scans the relevant Notion pages using Notions search functionality, and then returns information on the matching pages.

### Value + Example Business Use Cases

**Value**: Users can now harness ChatGPT’s natural language capabilities to directly connect to, query, and synthesize their knowledge within Notion. Administrators can explicitly share pages with the integration to manage access.

**Example Use Cases**: 
- A new employee seeks quick how-to information on setting up a new system
- A support agent needs to quickly retrieve information from Notion without reading the entire document
- Users want to synthesize information and create summaries or transformations for use in other aspects of their work

## Application Information

### Application Key Links

Check out these links from the application before you get started:
- Application Website: https://www.notion.so/
- Application API Documentation: https://developers.notion.com/reference/intro
- Notion Authorization Approach: https://developers.notion.com/docs/authorization
    - NOTE:  Notion only allows OAuth with "Public Integrations."  Refer to the linked documentation to determine what is best suited for your needs

### Application Prerequisites

Before you get started, make sure you go through the following steps in your application environment:
- Set up a notion workspace with populated pages
- Sharing pages through notion works best with specific Wikis.  Consider organizing your knowledge base into a wiki or set of wikis

## ChatGPT Steps

### Custom GPT Instructions 

Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/.gpt_action_getting_started) to see how this step works in more detail.


key: _node_content
string_value:
{"id_": "6efb3b20-4ce5-4e05-9a05-7cec3cd5a986", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "49e13756-307e-49b0-b9eb-9be6c95b280b", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "37bf860309c5c70c9d67a064d311dc74673d0f94b24da2b3bd6b3eb6eece03a8", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "84ca468d-3b77-47f6-a588-9d3d8a10c78b", "node_type": "1", "metadata": {}, "hash": "66c35c790a2904897b0a130b703b058ba22b3189ed11d1b6b253d9606e20d265", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 2475, "end_char_idx": 4929, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
**Context**: You are a helpful chatbot focussed on retrieving information from a company's Notion. An administrator has given you access to a number of useful Notion pages.  You are to act similar to a librarian and be helpful answering and finding answers for users' questions.

**Instructions**:
1. Use the search functionality to find the most relevant page or pages.
- Display the top 3 pages.  Include a formatted list containing: Title, Last Edit Date, Author.
- The Title should be a link to that page.
1.a. If there are no relevant pages, reword the search and try again (up to 3x)
1.b. If there are no relevant pages after retries, return "I'm sorry, I cannot find the right info to help you with that question"
2. Open the most relevant article, retrieve and read all of the contents (including any relevant linked pages or databases), and provide a 3 sentence summary.  Always provide a quick summary before moving to the next step.
3. Ask the user if they'd like to see more detail.  If yes, provide it and offer to explore more relevant pages.

**Additional Notes**: 
- If the user says "Let's get started", introduce yourself as a librarian for the Notion workspace, explain that the user can provide a topic or question, and that you will help to look for relevant pages.
- If there is a database on the page.  Always read the database when looking at page contents.
```

### OpenAPI Schema 

Once you've created a Custom GPT, copy the text below in the Actions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail.


```python
openapi: 3.1.0
info:
  title: Notion API
  description: API for interacting with Notion's pages, databases, and users.
  version: 1.0.0
servers:
  - url: https://api.notion.com/v1
    description: Main Notion API server
paths:
  /users:
    get:
      operationId: listAllUsers
      summary: List all users
      parameters:
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:


key: _node_content
string_value:
{"id_": "84ca468d-3b77-47f6-a588-9d3d8a10c78b", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "6efb3b20-4ce5-4e05-9a05-7cec3cd5a986", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "850965786b85a08e0801fffdc30947e7f014a3e74e6de934632d23a755b2977a", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f0a32d17-dcd0-422f-b1f9-7a25d17ac434", "node_type": "1", "metadata": {}, "hash": "7fd11e7220967e47e07941fc3e86b83ab60a2b7baabb10474f5a1f759b9b1374", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 4124, "end_char_idx": 5528, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
```python
openapi: 3.1.0
info:
  title: Notion API
  description: API for interacting with Notion's pages, databases, and users.
  version: 1.0.0
servers:
  - url: https://api.notion.com/v1
    description: Main Notion API server
paths:
  /users:
    get:
      operationId: listAllUsers
      summary: List all users
      parameters:
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        avatar_url:
                          type: string
                        type:
                          type: string
  /blocks/{block_id}/children:
    get:
      operationId: retrieveBlockChildren
      summary: Retrieve block children
      parameters:
        - name: block_id
          in: path
          required: true
          schema:
            type: string


key: _node_content
string_value:
{"id_": "f0a32d17-dcd0-422f-b1f9-7a25d17ac434", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "84ca468d-3b77-47f6-a588-9d3d8a10c78b", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "6a1aca7916c2e3435940988b1d79e0598b938ca3544a3823748289866220966b", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "c646ba9e-ded2-4549-b76c-64f09ef65c9b", "node_type": "1", "metadata": {}, "hash": "0a6970664a8e48766097d7f807a0e4aad9967e09ef3f65c070b800ea76224340", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 4897, "end_char_idx": 6126, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        avatar_url:
                          type: string
                        type:
                          type: string
  /blocks/{block_id}/children:
    get:
      operationId: retrieveBlockChildren
      summary: Retrieve block children
      parameters:
        - name: block_id
          in: path
          required: true
          schema:
            type: string
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                  results:
                    type: array
                    items:
                      type: object
                      properties:


key: _node_content
string_value:
{"id_": "c646ba9e-ded2-4549-b76c-64f09ef65c9b", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "f0a32d17-dcd0-422f-b1f9-7a25d17ac434", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "1b42342e8cd29a970a7353578b8a1823b2b775994757711b644b238a0c82bc53", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "c5b23eac-f397-4d3b-be1e-5fcb782a2bf8", "node_type": "1", "metadata": {}, "hash": "9d46fc19f42da06934cba48f98e89e8eb0c2504757bdef9a96a4ae7a6643de55", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 5481, "end_char_idx": 6776, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
true
          schema:
            type: string
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        type:
                          type: string
                        has_children:
                          type: boolean
  /comments:
    get:
      operationId: retrieveComments
      summary: Retrieve comments
      parameters:
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:


key: _node_content
string_value:
{"id_": "c5b23eac-f397-4d3b-be1e-5fcb782a2bf8", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c646ba9e-ded2-4549-b76c-64f09ef65c9b", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "7d54770284f0643306c710c229b8134f7074df80cdea570eb85454af336c00ad", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f2f33a0b-f806-4812-bad8-d48aeba2324b", "node_type": "1", "metadata": {}, "hash": "e729d1d54adc9ff622da4bea315f70f8b5b1827ffc972d1804efe5b540820128", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6115, "end_char_idx": 7281, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
properties:
                        id:
                          type: string
                        type:
                          type: string
                        has_children:
                          type: boolean
  /comments:
    get:
      operationId: retrieveComments
      summary: Retrieve comments
      parameters:
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        text:
                          type: string
                        created_time:
                          type: string
                          format: date-time
                        created_by:


key: _node_content
string_value:
{"id_": "f2f33a0b-f806-4812-bad8-d48aeba2324b", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c5b23eac-f397-4d3b-be1e-5fcb782a2bf8", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "0711b3976be72728215fcd85f258ad0440770c393060e2ddf6be54b63a36f448", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "bea0882e-aa75-4faa-b366-6ef057e51d69", "node_type": "1", "metadata": {}, "hash": "34f4164f26b243fc472db8c714c531040ec82994c30a47648b6d7956f6370d23", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 6737, "end_char_idx": 7913, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        text:
                          type: string
                        created_time:
                          type: string
                          format: date-time
                        created_by:
                          type: object
                          properties:
                            id:
                              type: string
                            name:
                              type: string
  /pages/{page_id}/properties/{property_id}:
    get:
      operationId: retrievePagePropertyItem
      summary: Retrieve a page property item
      parameters:
        - name: page_id
          in: path
          required: true
          schema:
            type: string
        - name: property_id
          in: path
          required: true
          schema:
            type: string
        - name:


key: _node_content
string_value:
{"id_": "bea0882e-aa75-4faa-b366-6ef057e51d69", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "f2f33a0b-f806-4812-bad8-d48aeba2324b", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "e3a65102601846ce9bf58855a510edd6edcd95245323e846fb1cc495a07c3495", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "88abebac-5bab-4aa0-addf-f4968dc624fd", "node_type": "1", "metadata": {}, "hash": "fff3c5057dc2186b344fbbca2ce99c72f6b47070dabf50c2425ff89af1596740", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 7236, "end_char_idx": 8477, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
date-time
                        created_by:
                          type: object
                          properties:
                            id:
                              type: string
                            name:
                              type: string
  /pages/{page_id}/properties/{property_id}:
    get:
      operationId: retrievePagePropertyItem
      summary: Retrieve a page property item
      parameters:
        - name: page_id
          in: path
          required: true
          schema:
            type: string
        - name: property_id
          in: path
          required: true
          schema:
            type: string
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  type:
                    type: string
                  title:
                    type: array
                    items:


key: _node_content
string_value:
{"id_": "88abebac-5bab-4aa0-addf-f4968dc624fd", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "bea0882e-aa75-4faa-b366-6ef057e51d69", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "1900cd3af8048fe324f6d5917fd039caaf35947df77963439625c1433eefa6ef", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f0a8162c-a947-4a08-8aba-4dc27731de27", "node_type": "1", "metadata": {}, "hash": "274f1e73348cc833652d26892a952e58a2c7fada581defb85e8491e70ee367ec", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 7865, "end_char_idx": 9096, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
schema:
            type: string
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  type:
                    type: string
                  title:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                        text:
                          type: object
                          properties:
                            content:
                              type: string
  /databases/{database_id}/query:
    post:
      operationId: queryDatabase
      summary: Query a database
      parameters:
        - name: database_id
          in: path
          required: true
          schema:
            type: string
        - name: Notion-Version
          in: header


key: _node_content
string_value:
{"id_": "f0a8162c-a947-4a08-8aba-4dc27731de27", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "88abebac-5bab-4aa0-addf-f4968dc624fd", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "3f3a76c34afc6e0e888468ab0e1ad8d0d3a4533d8e56853da040b0d51a9c76e9", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "4c914717-a8dc-4a9a-9764-0241a811264f", "node_type": "1", "metadata": {}, "hash": "c64c8a2cc9f3aa924d96188e3245654bdf540d2f6bf98ef17c404e66d497e4b5", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 8471, "end_char_idx": 9703, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
items:
                      type: object
                      properties:
                        type:
                          type: string
                        text:
                          type: object
                          properties:
                            content:
                              type: string
  /databases/{database_id}/query:
    post:
      operationId: queryDatabase
      summary: Query a database
      parameters:
        - name: database_id
          in: path
          required: true
          schema:
            type: string
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  type: object
                sorts:
                  type: array
                  items:
                    type: object
                start_cursor:
                  type: string
                page_size:
                  type: integer
      responses:
        '200':


key: _node_content
string_value:
{"id_": "4c914717-a8dc-4a9a-9764-0241a811264f", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "f0a8162c-a947-4a08-8aba-4dc27731de27", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "eedfde6fd21bc29ec1f4655760d4f1e01869792f16e9f634652ed16b2a426bf3", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "e66548f1-a93d-44aa-ab0e-279a8f0488f3", "node_type": "1", "metadata": {}, "hash": "9a8f4f221f7a817972f529e9af9e192c4c9774db3fb6545e199bdd5c3e342ad9", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 9053, "end_char_idx": 10319, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
- name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                filter:
                  type: object
                sorts:
                  type: array
                  items:
                    type: object
                start_cursor:
                  type: string
                page_size:
                  type: integer
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                  results:
                    type: array
                    items:
                      type: object
                  next_cursor:
                    type: string
                  has_more:
                    type: boolean
  /search:
    post:
      operationId: search
      summary: Search
      parameters:
        - name: Notion-Version
          in: header


key: _node_content
string_value:
{"id_": "e66548f1-a93d-44aa-ab0e-279a8f0488f3", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "4c914717-a8dc-4a9a-9764-0241a811264f", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ed49bd0ed30bb4c922f2d82443ddf843a8567450e06a5ffa969603448b663146", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "13f92fc3-288f-48cf-b950-acae7e32fb5b", "node_type": "1", "metadata": {}, "hash": "0ef1a75cf24aaaf285fd383508bef1c55ec942489b1720ef0f5e5254a18cce3c", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 9658, "end_char_idx": 10896, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


key: chroma:document
string_value:
type: integer
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                  results:
                    type: array
                    items:
                      type: object
                  next_cursor:
                    type: string
                  has_more:
                    type: boolean
  /search:
    post:
      operationId: search
      summary: Search
      parameters:
        - name: Notion-Version
          in: header
          required: true
          schema:
            type: string
          example: 2022-06-28
          constant: 2022-06-28
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                filter:
                  type: object
                  properties:
                    value:
                      type: string
                    property:
                      type: string
                sort:


key: _node_content
string_value:
{"id_": "13f92fc3-288f-48cf-b950-acae7e32fb5b", "embedding": null, "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "excluded_embed_metadata_keys": ["url", "tokens", "retrieve_doc", "source"], "excluded_llm_metadata_keys": ["title", "tokens", "retrieve_doc", "source"], "relationships": {"1": {"node_id": "aaff4c3f-363a-4c5a-af5e-0b389ce78a0c", "node_type": "4", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "ae60ddb2fce497ae81bb82ff3e96665499472ec115611458fb760a9186304e58", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "e66548f1-a93d-44aa-ab0e-279a8f0488f3", "node_type": "1", "metadata": {"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/gpt_actions_library/gpt_action_notion.ipynb", "title": "GPT Action Library: Notion", "tokens": 2577, "retrieve_doc": true, "source": "openai_cookbooks"}, "hash": "32999a538f00ffe456e51c69ab68b8e85e3ac72d9d0d4708dc107b9fef486863", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "b9ea94ee-5082-4271-96b0-5fa7e214c1b7", "node_type": "1", "metadata": {}, "hash": "3245172da508a585039745b5a759ca4bd2465c265e408bec8d9fabb234af189e", "class_name": "RelatedNodeInfo"}}, "text": "", "mimetype": "text/plain", "start_char_idx": 10276, "end_char_idx": 11472, "text_template": "{metadata_str}\n\n{content}", "metadata_template": "{key}: {value}", "metadata_seperator": "\n", "class_name": "TextNode"}


