'Aw CRUD!' Enable Your Custom GPT to Talk to Any Airtable Base
Tags: ai, api, productivity
Published: 2023-11-16 21:48:39

Last week, OpenAI announced a number of new models, features and pricing changes to their suite of tools. Among these announcements was the introduction of "Custom GPTs" which can be fed specific instructions and documents. While these features offer a convenient no-code alternative to assembling your own chain of LLM tools and agents, perhaps the most impactful feature is the ability to easily provide your Custom GPTs with access to "Actions": third-party integrations accessed via an API.

In this post, I'll provide step-by-step instructions for connecting your custom GPTs to any Airtable base you own, enabling your GPT to find and read records, update or create new records, and delete existing records.

**Prerequisites:** In order to follow this tutorial, you'll need an OpenAI subscription (to access the Custom GPTs beta feature) and an Airtable account (free or paid).

## Initializing Your Custom GPT
For this tutorial, we'll build a Custom GPT that helps us track interesting GitHub projects by adding them to our Airtable Base ["Cool Projects"](https://airtable.com/appKjP9iTJnUvFJXj/shrLrIfi7KDF7ehD8). 

Of course, given the combined flexibility of Airtable and ChatGPT, there are few limits on the kinds of projects you can build by combining these two tools. You could, for example, use an Airtable base as a kind of long-term memory bank for your Custom GPT, as a bare bones **R**etrieval **A**ugmented **G**eneration (RAG) tool, etcetera.

To start, ensure you're logged into your OpenAI account and visit the ['Explore'](https://chat.openai.com/gpts/discovery) page. There, click "Create a GPT" to begin configuring your custom GPT.

While you can interact with the "Create" dialog to set up some of the GPT's basic parameters, I don't recommend doing so because it's quite easy to hit the current 50 messages/hour cap for GPT-4. Instead, click on the 'Configure' tab.

We'll name our GPT 'Project Tracker', provide a description and a short set of instructions.

We can refine the **Instructions** later, so for now we'll just enter something straightforward:

> Project Tracker is a friendly assistant which uses its set of Actions to interact with records in the 'Cool Projects' Airtable Base.

At this point, we can decide which **Capabilities** to provide our custom GPT. We'll definitely want to enable Web Browsing, since we'll ask the GPT to visit and summarize GitHub repositories by providing it with links. I'll skip DALL-E Image Generation for now, but enable the Code Interpreter to allow us to do some cool analysis tasks using our Airtable data.

Let's also generate a nice icon for the custom GPT. To do so, I'll switch back to the 'Create' tab and prompt the GPT Builder.

> **Prompt:** Generate a pixel art illustration of a lightbulb to use as my GPT's icon.


![A screenshot of the Custom GPT Configuration screen showing the settings described above.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2mjqipa3czgjqndv47w.png)
*We'll start of with this basic configuration.*


Don't forget to save your changes so far!

Now that we've initialized our Project Tracker GPT, we'll need to turn to Airtable to generate instructions on how our GPT can interface with the Airtable API and our Airtable Base.

## Generating an OpenAPI Schema from Our Airtable Base

For the purposes of this demonstration, I've created a publicly accessible Airtable Base called ["Cool Projects"](https://airtable.com/appKjP9iTJnUvFJXj/shrLrIfi7KDF7ehD8).

To get the best performance out of your custom GPT, there are a few things I'd recommend. First, make use of Airtable's field descriptions to provide semantically rich descriptions of the purpose of each field. We'll pass these field descriptions to the custom GPT when defining our Actions, and while I can't confirm that this is the case, providing further context to the GPT about how each field is used seems to improve performance.

To start, I'll add a few of my own GitHub projects manually. This will provide some context for the custom GPT regarding how we expect the data to be stored and formatted. While you *could* start with an empty base and have your GPT add all the records to it, I find it performs best when there is pre-existing content to model.

### Generating an OpenAPI Schema
OpenAI's Actions API enables custom GPTs to interface with third-party applications through those platforms' **A**pplication **P**rogramming **I**nterfaces (APIs). To instruct the GPT on how to interact with this API, the Custom GPT Editor accepts an [OpenAPI](https://www.openapis.org/) schema, a standardized format for defining how an API expects to be interacted with.

In order to enable our custom GPT to interact with our Airtable base, we'll have to provide our own OpenAPI schema. Luckily, we don't need to generate this schema by hand!

I've created a script for Airtable's  Scripting extension, adapting the (very well implemented!) work of GitHub user [TheF1rstPancake](https://github.com/TheF1rstPancake/AirtableOpenAPICustomBlock) on a custom Airtable Block that generates an OpenAPI specification from any Airtable base, which can instantly generate this schema.

To use it, we'll need to add the **Scripting** extension to our base (**Extensions** &rarr; **+ Add an extension** &rarr; **Scripting**).

We'll edit the script, deleting the boilerplate code and replacing it with our own script, which you can find in [this GitHub Gist](https://gist.github.com/kcole93/5d86cfe6fbcec60cc5ece6e2246158d6).

After pasting the code into the Script Editor, click **Run** and you'll be presented with a full OpenAPI schema for your Airtable Base. This schema will allow you to grant your custom GPT with full **C**reate **R**eplace **U**pdate **D**estroy (CRUD) access to your base. However, before we finish defining our GPT's Actions, we'll need need to create a **P**ersonal **A**ccess **T**oken (PAT) which provides our custom GPT with the necessary permission scopes to interact with our Airtable base via the Airtable API, and which we'll use to authenticate the custom GPT agent.

#### 🚧 Warning 🚧
By default, the OpenAPI schema includes *all* methods of interacting with the Airtable API, **including destructive methods like PATCH and DELETE**.  It also includes **all of the specified base's tables**.

This means that if you, for example, were to make a custom GPT and provide it with your OpenAPI schema, and subsequently shared that custom GPT with others, **anyone** could instruct the GPT to perform destructive operations on your Airtable base, like deleting all of its records or writing over existing records! Please keep this in mind when developing and sharing your custom GPTs. 

You can limit the operations available to the GPT, but you'll need to manually remove their corresponding "path" definitions from the generated schema (for example, using your favorite text editor) before defining your GPT's Actions.[^1] 

It's both possible *and recommended* to limit the scope of the GPT's permissions when generating its Airtable PAT; however, I wouldn't recommend only using permissions scope limitations to restrict your GPT's capabilities, as it will attempt to use any defined Actions and report authentication/permission errors in the chat output.

### Generating a Personal Access Token for Your Custom GPT

Since Airtable is deprecating API keys at the end of January 2024, we'll need to create a Personal Access Token instead.[^2]

To create a PAT to authenticate with and access the Airtable API, visit [https://airtable.com/create/tokens](https://airtable.com/create/tokens), and click **Create new token**.

Give this PAT a meaningful name, and assign its scope of permissions according to your needs. For this demonstration, I'll enable full read/write capabilities so that my custom GPT can add new records and update existing ones.

Be sure to carefully select the scope of access for this PAT. You'll want to limit the scope to the single Base that you're working with.


![A screenshot demonstrating the creation of a PAT in the Airtable interface.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdqp3bna2mkpnl81czhy.png)
*It's worthwhile to give our PAT a meaningful name, because record revision histories in the Airtable interface will show this name to identify changes made by our custom GPT.*


Once you click **Create token**, you'll be presented with the PAT. Be sure to copy this to a text file on your desktop, since we'll need to provide it to our custom GPT when setting up our actions. If you forget the PAT, you can regenerate it with the same settings from the Personal access token dashboard in Airtable.

## Adding Airtable Access to Your Custom GPT
To finish enabling your custom GPT to interface with your Airtable base, edit your GPT and open the **Configure** pane. Click on **Add Action**, and paste your generate OpenAPI Schema into the **Schema** input. You should see a list of all of the actions that are generated from this schema.


![A screenshot demonstrating pasting the generated OpenAPI schema into the Actions configuration for our custom GPT.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2eh7lkni8j675qzcmris.png)
*Under "Available actions" we now see a list of the different operations available for each table in our base.*


As a final step, we need to set up our authentication configuration. Click on the cog icon by the 
![A screenshot showing a test prompt to the Project Tracker GPT. Prompt: 'I'd like you to visit my GitHub repo and add any other pinned projects to my Airtable base's 'Projects' table: [link to author's GitHub profile] The GPT browses the provided link, makes a number of API calls, and reports that it has successfully added four new projects to the Airtable base.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jblkhgo8clntzqsc4dk1.png)**Authentication** input, and select **API Key**. Paste your PAT into the **API Key** field, and select "Bearer" as the **Auth Type**.

You can go ahead and test our your Actions by clicking the **Test** button.

![A screenshot showing the output after running a test of the 'Get Projects' operation. The Project Tracker GPT calls the HTTP endpoint for our API, retrieves information from our Airtable base, and summarizes that information in the chat response.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lr5cncytool10rpslawu.png)
*A test of our "Get Projects" operation demonstrates that our custom GPT is now able to read data in from our Airtable base!*

And that's it! Your custom GPT now has full CRUD access to your Airtable base. Now, you can do things like ask your GPT to add new records to your base's tables:


![A screenshot showing a test prompt to the Project Tracker GPT. Prompt: 'I'd like you to visit my GitHub repo and add any other pinned projects to my Airtable base's 'Projects' table: [link to author's GitHub profile] The GPT browses the provided link, makes a number of API calls, and reports that it has successfully added four new projects to the Airtable base.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/264o9ecsnwz6gk9oyg98.png)
*Now you can use natural language to instruct your custom GPT to interact with your Airtable API.*


## Tips and Reflections
While testing out the new Custom GPT feature, I've come across a few hiccups:
1. Out-of-date Action schemas are occasionally 'remembered' by your custom GPT, leading them to form incorrect calls to the Airtable API. A work around seems to be deleting your Action entirely, saving the custom GPT, and then re-adding your updated Action schema.
2. Custom GPTs don't seem to hold the full OpenAPI schema in memory when deciding on actions. For example, I don't believe that the entire "schemas" specification is followed at all times, so occasionally the custom GPT will try to send malformed API calls or attempt ot push/patch malformed objects. It is responsive to feedback, at least!
3. You can add additional information about how to best navigate/utilize the information in your Airtable base via the custom GPT's **Instructions** field; however, GPTs don't always make 'informed' decisions about how to query or transform information received from outside sources. For example, if you ask for the GPT to retrieve a record, it may attempt to filter on the record's title and if there is no match and the API returns no results, it will complain that it wasn't able to find the record instead of searching all records and then conducting a more 'semantic' search on the results.
4. There's a limit to how much information your custom GPT will ingest. As a result, you'll need to make strategic use of Airtable's Views feature if your use case involves a lot of records or records with long text data. The GPT generally attempts to limit returned information using the query parameters/filters specified in the Airtable API, but occasionally makes mistakes.

By default, the "typecast" option in the Airtable API is disabled. This is meant to prevent the custom GPT from creating new options in Single/Multi-Select fields. However, if you would like to enable this behavior you can manually change the value of the "typecast" parameter in the OpenAPI specification.

🔐 Another note: I'd recommend disabling sharing your chat with OpenAI to improve their services, especially if you're dealing with personal/sensitive data! To do so, deselect 'Use conversation data in your GPT to improve our models' under **Additional Settings**.

## Footnotes
[^1]: I may refactor the current script to enable users to specify which methods they would like to include/exclude from the generated schema, but currently this is not supported and the limitations of Airtable's Scripting runtime make adding this functionality somewhat painful.

[^2]: While it's not a best practice to assign a PAT to a third-party integration, there are a number of limitations which make it unfeasible to use Airtable for public-facing purposes, including for a publicly accessible custom GPT. There is a limit of 5 API requests per second per base, which makes concurrent connections essentially impossible with a user base of non-trivial size. For this reason, I've eschewed creating an OAuth integration, but you should consider doing so if you plan to share your GPT with others.