Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

How to make a ChatGPT plugin

An easy step-by-step guide on how to build and test your own ChatGPT plugin, along with code snippets and a demo GitHub project.

Apr 15, 2024 • 16 Minute Read

Please set an alt value for this image...
  • AI & Data
  • Software Development

So, ChatGPT is pretty cool --- mind-blowing, actually --- but as you might already know, it does have its limits. The biggest one is that it’s only as good as the data it was trained on, and that data is old (September 2021 or earlier). So, while it’s fantastic at writing essays, code and jokes, wouldn’t it be even better if it could give you tomorrow’s weather forecast, search for flights for an upcoming trip, or find you the perfect apartment to rent?

Well, you’re in luck!  With a dash of creativity, a pinch of coding, and a sprinkle of patience, you can customize your ChatGPT experience by creating your own plugins, which effectively let ChatGPT “get out” to the interwebs to get real-time data.  Then, using its magical powers of processing data into human-friendly answers, it will respond back in the ChatGPT interface. Plugins are a total game changer (particularly for developers) and coming up in this article, we’ll see step-by-step how to build our own to retrieve information for a given stock symbol (like TSLA or MSFT).

Table of contents

What you need to follow along

To build the plugin end-to-end, you’re going to need a few things.

  1. ChatGPT plugins developer access

    If you have a ChatGPT Plus account ($20/month), you can install/use any of the plugins in the Plugins Store.  However, to develop your own plugins, you’ll need to get developer access.  At the moment, this requires you to sign up on the waitlist.  It took me about 2.5 weeks to get access after I got on the waitlist, but your mileage may vary.

  2. An API key for Alpha Vantage

    Alpha Vantage is the free API we’ll be using to retrieve stock information.  The API key is free and easy to get.

  3. Somewhere to write code and run a Python/Flask website/API as you’re developing it

    There are tons of options here.  I’m going to be using Replit, a browser-based IDE that lets you deploy your code to a public endpoint in literally seconds.  It’s super easy.  But if you’re more comfortable using something else like AWS Cloud9, GitHub Codespaces, VS Code, IntelliJ, or even Notepad (with Gunicorn, NGINX, Waitress), those will work too. To use Replit, sign up for a free account.

  4. Somewhere to host the API on a publicly-accessible URL

    Here again, there is no shortage of options.  I’ll be using Replit for this step too.  NOTE: To deploy an app using Replit, there is a $1.50 charge.

    If you want to go with another provider, you could choose AWS Elastic Beanstalk, GCP App Engine, GitHub Codespaces, GoDaddy, Digital Ocean, Heroku or others.

A step-by-step guide to building a ChatGPT plugin

In simple terms, a plugin consists of three things: an app wrapped in an API, a manifest file, and an OpenAPI specification.  Once you have those, you point ChatGPT to them, and voila, you’re ready to use your plugin from within the ChatGPT interface.  So let’s get going on these three pieces.

Step 1: Build an app wrapped in an API

In this section, our goal is to create an app that does something, wrapped in an API at a publicly-accessible URL.  The app we’re building will retrieve information for a given stock symbol (open price, close price, volume, etc.), calling an external API (Alpha Vantage) to get that data.  To keep things simple, we’re going to be writing a Flask API.  Flask is a popular framework for creating web applications and APIs in Python, and it’s going to make our lives pretty easy.  Don’t worry if you don’t know Flask; I’ll provide and explain all the code you need.

Create a new Repl and import code from GitHub

In Replit, a project is called a Repl, and it’s where our code lives.  You can manually create the code files and copy/paste code from the article below as we go.  Or an easier option is to grab the completed code from GitHub using the steps below.

  • On the Create a Repl dialog, click Import from GitHub.
  • Enter the URL for the Pluralsight GitHub repo: https://github.com/pluralsight/chatgpt-plugin-demo.  Replit should automatically detect that the project is using Python.
  • Click Import from GitHub. Replit will import the three code files from the GitHub repo.  Then we need to tell it which file should be used as the entry point.
  • In the Configure Repl window (likely on the top right of your screen), select main.py as the entry point.  Click Done.

Review the code files

Now that you’ve completed the GitHub import, you should see three code files on the top left of your screen.

main.py

Our Flask app/API lives in the main.py file.  This contains all the functionality for the ChatGPT plugin, to retrieve stock information from the Alpha Vantage API.  Specifically, we’ll be calling the “Quote Endpoint” API from Alpha Vantage.

Here’s our code in the main.py:

      # Import the libraries we need
import requests
from flask import Flask, request, send_from_directory

# Replace "YOUR_API_KEY_HERE" with your actual API key
# Even better, use best practices and store it as a secret (not hard-coded!)
API_KEY = "YOUR_API_KEY_HERE"
BASE_URL = "https://www.alphavantage.co/query"

# Initialize the Flask app
app = Flask(__name__)

# When a user loads the home page, display 'Hello World!'
# This is not required for the plugin, but makes it easier to see that things are working when we deploy and test
@app.route("/")
def index():
  return "Hello world!  Your web application is working!"

# This route contains the core functionality to get stock information.  This calls the "Quote Endpoint" API from Alpha Vantage: https://www.alphavantage.co/documentation/#latestprice
@app.route('/stock', methods=['GET'])
def get_stock_data():
  symbol = request.args.get('symbol')

  params = {"function": "GLOBAL_QUOTE", "symbol": symbol, "apikey": API_KEY}

  response = requests.get(BASE_URL, params=params)
  return response.json()

# ChatGPT will use this route to find our manifest file, ai-plugin.json; it will look in the "".well-known" folder
@app.route('/.well-known/ai-plugin.json')
def serve_ai_plugin():
  return send_from_directory('.',
                             'ai-plugin.json',
                             mimetype='application/json')


# ChatGPT will use this route to find our API specification, openapi.yaml
@app.route('/openapi.yaml')
def serve_openapi_yaml():
  return send_from_directory('.', 'openapi.yaml', mimetype='text/yaml')

# OPTIONAL: If you want a logo to display on your plugin in the Plugin Store, then upload a file named logo.png to the root of your project, and uncomment the code below.
# @app.route('/logo.png')
# def plugin_logo():
  # return send_from_directory('.', 'logo.png')

# Run the app
if __name__ == "__main__":
  app.run(host='0.0.0.0', port=81)

    

Here are screenshots of the final code from my example project (two parts).

Deploying and testing the app’s home page locally

Next, we need to run the app to make sure it works locally.  Replit makes this easy.  Just click the big green Run button on the top of the screen.

And assuming everything works correctly, you should see your “Hello World” message in the Webview window (likely on the top right of your screen).  Yay!

TIP: If you don’t see the Webview window, open it from the “dot-dot-dot” menu:

TIP: If the “Hello World” message doesn’t display, check the console output for any errors.  You can also try popping the window out to a new tab (sometimes the Webview version will hang for a long time before loading).

Testing the stock API functionality locally

Okay.  So the home page of the app is working, but that’s not the point of this app.  The real functionality lives at the /stock API route, so we need to test that next.

This is best tested from a new browser tab, so pop the Webview window into a new tab. For the query string, we can consult the Alpha Vantage API documentation for Quote Endpoint (the function name is GLOBAL_QUOTE).  Here are some examples of the format it requires:

For our app, remember that our route is /stocks (not /query shown in the example).

To test our app, let’s use the query string below (adding it after your domain name).  This will call the Quote Endpoint to get the latest info for Tesla (TSLA) stock.  The “demo” API key will be replaced by your actual API key in your code.

/stock?function=GLOBAL_QUOTE&symbol=TSLA&apikey=demo

Your URL should look like this, and if everything is working correctly, you should get a JSON response with the Tesla stock information:

Congrats!  The core functionality of your plugin is working.

Deploying the API to a public endpoint (at least almost)

The testing we did above was only on the local development server.  ChatGPT won’t be able to get to this version of your API so we need to deploy it to a publicly-accessible URL instead.

Once again, Replit makes this easy.  Note that there is a minimum charge of $1.50 to host the API with Replit. To start the deployment, click the arrow next to the name of your Repl, and then click Deploy your project.

This will open the Deployments window (likely on the top right of the screen).  From this window, click Deploy your project.

Next you’ll configure your hosting environment where the code will live.  For this simple project, you can choose the minimum available resources (0.25 vCPU/1 GiB RAM).

This will cost $0.20 per day.  However, if this is the first time you’re deploying with Replit, your screen will look slightly different, and there will be a minimum of $1.50 charge for the first deployment.  You’ll also be prompted for your credit card information at this point.

IMPORTANT: Make sure you read to the end of this article for instructions on how to delete this deployment and stop the charges!

After entering your credit card information, you can continue on with deployment.  Click Purchase and deploy. After the purchase is complete, deployments will be activated, meaning you can now continue with the deployment.

Click Deploy your project.

Now, don’t get overly excited and do the final deployment just yet.  Before we push this masterpiece out to the world, we need to choose a domain name.  And then we need to paste that domain name into our manifest file and OpenAPI spec.

Enter the primary domain you want and make sure it’s available (or you can choose the default name it gives you).  Your full domain name will be [primary domain you choose].replit.app.  In my example, it’s myfirstchatgptplugin.replit.app.

Now hold that thought.  And let’s do a quick recap on what we’ve done so far.

Back to the big picture, our “Step 1” was to create an app, wrapped in an API, at a publicly-accessible URL.  We’re almost done with that part (as soon as we click that deploy button).  We’re done enough that I’ll check it off the list.  But before we do the final deployment, let’s talk about these other two files, in Steps 2 and 3.

Step 2: Create the manifest file

ai-plugin.json

The plugin’s metadata and auth type are contained in the manifest file called ai-plugin.json.  ChatGPT will look for this file at yourdomain.com/.well-known/ai-plugin.json.

You don’t need an actual folder called .well-known in your project, but in main.py, we listen for requests at that path using this line: @app.route('/.well-known/ai-plugin.json').

Here’s our ai-plugin.json code, with some placeholders you’ll need to update:

      {
    "schema_version": "v1",
    "name_for_human": "Stock Quote",
    "name_for_model": "StockQuote",
    "description_for_human": "Get price and volume information for a given stock.",
    "description_for_model": "Get price and volume information for a given stock.  Always display results using markdown tables.",
    "auth": {
        "type": "none"
    },
    "api": {
        "type": "openapi",
        "url": "[YOUR DOMAIN, must be HTTPS]/openapi.yaml"
    },
    "logo_url": "[YOUR DOMAIN, must be HTTPS]/logo.png",
    "contact_email": "[email protected]",
    "legal_info_url": "https://example.com/legal"
}
    

The top lines in this code define the name and description for humans and for the AI model.  For auth type, we’re keeping things simple with “none,” but in the real world, you might want to choose another option from the documentation.

And then we need to tell ChatGPT where to find our stuff, which means you need to update [YOUR DOMAIN, must be HTTPS] with your domain.  Your domain will be something like https://myfirstchatgptplugin.replit.app.

The line that you update for “url” will tell ChatGPT where our OpenAPI spec lives.  This tells ChatGPT what our API does and how to use it.

The line that you update for the logo is optional.  If you want your logo to appear in the ChatGPT plugin store, then upload a logo.png file to your project.  Either way, update this line with your domain name.  If you don’t have a logo, the plugin will still work; it will just show a placeholder image for the logo.

For the two lines with “example.com,” you can leave them as-is for development purposes.  However, if you want to publish your plugin to the world and go through the OpenAI verification process, you’ll need valid addresses for contact email and legal info.

Here’s a screenshot of the final code for my example project.

Step 3: Create the OpenAPI specification

openapi.yaml

The next file ChatGPT needs is the OpenAPI specification, which lives in openapi.yaml.  This contains details about your API so ChatGPT understands what it does and how to interact with it (such as paths and parameters to use).  ChatGPT will look for this file at yourdomain.com/openapi.yaml.  In main.py, we handle this with the line: @app.route('/openapi.yaml').

In this file, be sure to update [YOUR DOMAIN, must be HTTPS] with your domain.  Your domain will be something like https://myfirstchatgptplugin.replit.app.

      openapi: 3.0.1
info:
    title: Stock Quote
    description: Get price and volume information for a given stock.
    version: "v1"
servers:
    - url: [YOUR DOMAIN, must be HTTPS]
paths:
    /stock:
        get:
            operationId: getStockData
            summary: Retrieves the price and volume information for a given stock symbol.
            parameters:
                - in: query
                  name: symbol
                  schema:
                      type: string
                  description: The symbol of the stock to get a quote for. For example, the stock symbol MSFT represents the company Microsoft.
            responses:
                "200":
                    description: OK

    

Here’s a screenshot of the final code for my example project.

Step 4: Connect to the plugin from ChatGPT

Nice work so far!  Looking back at the big picture, we’ve completed all the code files for our plugin.  Now all we need to do is deploy it to the public endpoint and then connect to it from the ChatGPT interface.

Deploying the API to a public endpoint (for real this time)

Earlier, we started our deployment to the endpoint, but then we had to go back and update our domain name in the ai-plug.json and openapi.yaml files.  But with those updates made, we can now actually do the deployment.

Click Deploy.

Replit will run its magic to push your files out to the public URL.  After a minute or so, if everything worked, you should see a message that deployment was successful.  Nice!

To launch the app on the public endpoint, scroll up a little bit and then click the button to pop the domain name into a new tab.

This should launch your “Hello World” message at the public endpoint showing that everything is working.

To test that the stock functionality is still working, you can use the same query string that we used above to test things locally, adding it after your domain name:

/stock?function=GLOBAL_QUOTE&symbol=TSLA&apikey=demo

And you should get back JSON code with info for Tesla’s stock.

Amazing!

Connecting the plugin

Now that our API is live at a public endpoint, we just need to let ChatGPT know that it’s out there.  Note that you will need a ChatGPT Plus account and developer access to test this.

Navigate to ChatGPT and create a new chat, choosing GPT-4 as the model.

  • Click on GPT-4 and select Plugins.
  • Next, click the arrow next to No plugins enabled, and then click the arrow for the Plugin store.
  • This will launch the Plugin store, showing a list of verified plugins you can install.  However, to work with our own plugin, we need to click Develop your own pluginTIP: If you don’t see Develop your own plugin, you don’t yet have developer access.  Be sure to get on the waitlist.

Next, you’ll be prompted to enter your domain so that ChatGPT can find your manifest and OpenAPI spec files.  Enter your domain, which will be something like https://myfirstchatgptplugin.replit.app (using your own, of course).  Then click Find manifest file.

ChatGPT will go out to your domain and find the ai-plug.json and openapi.yaml files that we deployed.  Once it’s found those files, you’ll see a success message like the one below.  (Note that I’m using a logo.png file for Pluralsight.  If you didn’t include a logo in your project files, you’ll see a placeholder image instead.)

Click Next.

For development and testing purposes, an unverified plugin (like ours) can be installed by up to 15 developers (that’s you).  Once it’s ready for primetime and you want OpenAI to review it, you can submit it for review.  But for our purposes, we’re going to click Install for me to install the unverified version.

Click Continue to confirm that you understand there are risks to uninstalling unverified plugins.

And then one more time for good measure, click Install plugin to actually make the magic happen.

Once the installation is complete, your custom plugin should be selected for you automatically from the plugins dropdown.  If it’s not, simply select the dropdown and then select the checkbox next to the name of the plugin.

Step 5: Testing the plugin from ChatGPT

Phew!  We’ve created the plugin and hooked it up in the ChatGPT interface.  Now for the moment of truth: is it going to work?  Let’s try it!

Make sure the plugin is still selected, and then enter a prompt to get the price of a stock (you can use any valid symbol, but I’ll stick with TSLA).

And you should get an answer like the one below, formatted as a table (this is an instruction we provide in the ai-plugin.json file, to format as a markdown table).

Excellent work!  You’ve successfully created a custom plugin and can use it in the ChatGPT interface.  Feel free to try out some other stock symbols to see it in action.

IMPORTANT! Delete your deployment afterwards

If you followed this article using Replit to deploy your API, you’ll want to delete that deployment or you’ll be charged $0.20 every day until you do.

  • Back in Replit, on the Deployments window, click Settings.
  • Click Shut down

This will delete your hosting subscription and API.  Obviously this means your plugin won’t work through the ChatGPT interface anymore.

To uninstall your plugin from ChatGPT, open a new chat and then navigate to the Plugin store. Filter by Installed, and then click Uninstall.  This will uninstall your plugin from the ChatGPT interface.  If you want to reinstall it in the future, you’ll need to follow the steps above to add it again.

Wrapping up

Bravo!  You’ve made it to the end.  We’ve journeyed far and wide together—covering everything from setting up a development environment to creating a new Flask API, editing manifest files to launching our very own plugin through the ChatGPT interface.  With our plugin, we can access real-time stock data, while still tapping into the sweet-sweet power of ChatGPT to get human-friendly responses.  I hope you’ve learned a ton and had a little bit of fun along the way.

To continue learning about how to get more from ChatGPT and GPT models generally, check out my course: Getting Started on Prompt Engineering with Generative AI.

Amber Israelsen

Amber I.

Amber has been a software developer and technical trainer since the early 2000s. She holds certifications for AWS and a variety of Microsoft technologies. She also focuses on user experience and professional skills training, bridging the gap between techies and non-techies.

More about this author