We believe in AI and every day we innovate to make it better than yesterday.
We believe in helping others to benefit from the wonders of AI and also in
extending a hand to guide them to step their journey to adapt with future.
In today’s rapidly evolving conversational AI landscape, ChatGPT has emerged as a game-changer, powering intelligent and engaging interactions across countless applications. As the demand for seamless integration of this cutting-edge technology grows, developers worldwide seek to harness the power of ChatGPT in their projects. In this article, we’ll dive deep to learn how to develop a ChatGPT plugin. Whether you’re an experienced developer or an AI enthusiast, this comprehensive guide will give you the knowledge and insights needed to supercharge your next project with the conversational prowess of ChatGPT.
OpenAI plugins bridge the gap between ChatGPT and third-party applications. It fixes one of the main drawbacks of ChatGPT, that is, the inability to deliver recent information and perform actions on third-party applications. With the introduction of plugins, ChatGPT can deliver recent information without any cutoff date restrictions and perform actions on third-party applications, such as booking a flight ticket. This update opens up a lot of use cases and business growth opportunities using Generative AI.
What is possible?
As explained by OpenAI, ChatGPT plugins can retrieve real-time information from the internet, retrieve information from knowledge-base and perform actions on behalf of the user.
You can expose your product’s APIs to ChatGPT so that users can access your product’s services right from ChatGPT.
You can create a knowledge base so that ChatGPT users can access the information via ChatGPT chat.
You can limit the plugins’ usage using different authentication methods so that only users you allow can access the plugin.
Now that you know what is possible with the ChatGPT plugins, let’s look at the folder structure and essential components required for building your plugin.
Folder Structure
To create the plugin, you must create a folder named .well-known in your API’s domain. For example, example.com/.well-known/. The /.well-known folder must exist on your domain for ChatGPT to connect with your plugin. Without this folder, you cannot install the plugin.
Once the folder is created, you need to create 2 essential components.
ai-plugin.json
OpenAPI specification
Suppose you created a plugin allowing your employees to submit a leave application from ChatGPT. In this scenario, the employee can select the plugin from the ChatGPT interface and send a query requesting leave. When the query is received, ChatGPT first looks into your plugin and looks through the details in ai-plugin.json.
ai-plugin.json contains basic information about the plugin and the APIs you expose to ChatGPT. In this example, the file would contain the API URL of your HRMS application. After fetching the API details, ChatGPT checks the OpenAPI specification. It is a wrapper that sits on top of your API. It tells the model how to use the API. In this example, the model will know how to use the API to submit a leave application. The model can only access the functions you define in the OpenAPI specification. For example, it can only submit leave applications but not edit employee details. After calling the API, the model receives the raw data response and is presented to the user in natural language. For example, if the API response is ‘success,’ ChatGPT would reply to the user, saying, “I’ve submitted a leave application for you.”
How to create ai-plugin.json
The file ai-plugin.json contains basic information about the plugin and the APIs you expose to ChatGPT. Here is an example for ai-plugin.json.
{
"schema_version": "v1",
"name_for_human": "Sport Stats",
"name_for_model": "sportStats",
"description_for_human": "Get current and historical stats for sport players and games.",
"description_for_model": "Get current and historical stats for sport players and games. Always display results using markdown tables.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "PLUGIN_HOSTNAME/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "PLUGIN_HOSTNAME/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "https://example.com/legal"
}
{
"schema_version":"v1",
"name_for_human":"Sport Stats",
"name_for_model":"sportStats",
"description_for_human":"Get current and historical stats for sport players and games.",
"description_for_model":"Get current and historical stats for sport players and games. Always display results using markdown tables.",
"auth":{
"type":"none"
},
"api":{
"type":"openapi",
"url":"PLUGIN_HOSTNAME/openapi.yaml",
"is_user_authenticated":false
},
"logo_url":"PLUGIN_HOSTNAME/logo.png",
"contact_email":"support@example.com",
"legal_info_url":"https://example.com/legal"
}
{
"schema_version": "v1",
"name_for_human": "Sport Stats",
"name_for_model": "sportStats",
"description_for_human": "Get current and historical stats for sport players and games.",
"description_for_model": "Get current and historical stats for sport players and games. Always display results using markdown tables.",
"auth": {
"type": "none"
},
"api": {
"type": "openapi",
"url": "PLUGIN_HOSTNAME/openapi.yaml",
"is_user_authenticated": false
},
"logo_url": "PLUGIN_HOSTNAME/logo.png",
"contact_email": "support@example.com",
"legal_info_url": "https://example.com/legal"
}
The description_for_model attribute allows you to instruct the model on how to use your plugin. Overall, GPT4 can understand natural language and follow instructions. So you can put general instructions on what your plugin does and how the model should use it properly. Use natural language in a concise yet descriptive and objective tone, as shown in the example above. You can refer to the definition below for the possible options for the plugin.
FIELD
TYPE
DESCRIPTION / OPTIONS
schema_version
String
Manifest schema version
name_for_model
String
The name for the model will be used to target the plugin
Maximum 50 characters.
Ex: sportStats
name_for_human
String
Human-readable name, such as the full company name
Maximum 50 characters.
Ex: Sport Stats
description_for_model
String
This description is better tailored to the model, such as token context length considerations or keyword usage for improved plugin prompting.
Maximum 8000 characters (will decrease over time)
Ex: Get current and historical stats for sports players and games. Always display results using markdown tables.
description_for_human
String
Human-readable description of the plugin
Maximum 120 characters.
Ex: Get current and historical stats for sports players and games.
The next step is to build the OpenAPI specification to document the API. The model in ChatGPT does not know anything about your API other than what is defined in the OpenAPI specification and manifest file. If you have an extensive API, you need not expose all functionality to the model and can choose specific endpoints. The OpenAPI specification is the wrapper that sits on top of your API.
The OpenAPI Specification (OAS) defines a standard, language-agnostic interface to HTTP APIs that allows humans and computers to discover and understand the service’s capabilities without access to source code, documentation, or through network traffic inspection. When properly defined, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. There are several tools available to automatically generate the OAS for your API. A popular tool is Swagger. An OpenAPI definition can then be used by documentation generation tools to display the API, code generation tools to generate servers and clients in various programming languages, testing tools, and many other use cases. In this case, it helps the model to understand the API.
When a user queries in ChatGPT relevant to the plugin, the model checks the plugin’s manifest file for ‘description_for_model’ and checks the descriptions of the endpoints in the OpenAPI specification. So, it is important to prepare the OpenAPI specification accurately so that the model can call the API for the right user queries. The OpenAPI specification tells the model about the diverse details of your API, available functions, functions’ parameters, etc. Below you can find an example of OpenAPI specification. The first code widget is an example API code, and the second code widget below is the OpenAPI specification of the below API.
import json
import requests
import urllib.parse
import quart
import quart_cors
from quart import request
# Note: Setting CORS to allow chat.openapi.com is required for ChatGPT to access your plugin
app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com")
HOST_URL = "https://example.com"
@app.get("/players")
async def get_players():
query = request.args.get("query")
res = requests.get(
f"{HOST_URL}/api/v1/players?search={query}&page=0&per_page=100")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/teams")
async def get_teams():
res = requests.get(
"{HOST_URL}/api/v1/teams?page=0&per_page=100")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/games")
async def get_games():
query_params = [("page", "0")]
limit = request.args.get("limit")
query_params.append(("per_page", limit or "100"))
start_date = request.args.get("start_date")
if start_date:
query_params.append(("start_date", start_date))
end_date = request.args.get("end_date")
if end_date:
query_params.append(("end_date", end_date))
seasons = request.args.getlist("seasons")
for season in seasons:
query_params.append(("seasons[]", str(season)))
team_ids = request.args.getlist("team_ids")
for team_id in team_ids:
query_params.append(("team_ids[]", str(team_id)))
res = requests.get(
f"{HOST_URL}/api/v1/games?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/stats")
async def get_stats():
query_params = [("page", "0")]
limit = request.args.get("limit")
query_params.append(("per_page", limit or "100"))
start_date = request.args.get("start_date")
if start_date:
query_params.append(("start_date", start_date))
end_date = request.args.get("end_date")
if end_date:
query_params.append(("end_date", end_date))
player_ids = request.args.getlist("player_ids")
for player_id in player_ids:
query_params.append(("player_ids[]", str(player_id)))
game_ids = request.args.getlist("game_ids")
for game_id in game_ids:
query_params.append(("game_ids[]", str(game_id)))
res = requests.get(
f"{HOST_URL}/api/v1/stats?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/season_averages")
async def get_season_averages():
query_params = []
season = request.args.get("season")
if season:
query_params.append(("season", str(season)))
player_ids = request.args.getlist("player_ids")
for player_id in player_ids:
query_params.append(("player_ids[]", str(player_id)))
res = requests.get(
f"{HOST_URL}/api/v1/season_averages?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/logo.png")
async def plugin_logo():
filename = 'logo.png'
return await quart.send_file(filename, mimetype='image/png')
@app.get("/.well-known/ai-plugin.json")
async def plugin_manifest():
host = request.headers['Host']
with open("ai-plugin.json") as f:
text = f.read()
# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the manifest
text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
return quart.Response(text, mimetype="text/json")
@app.get("/openapi.yaml")
async def openapi_spec():
host = request.headers['Host']
with open("openapi.yaml") as f:
text = f.read()
# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the OpenAPI spec
text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
return quart.Response(text, mimetype="text/yaml")
def main():
app.run(debug=True, host="0.0.0.0", port=5001)
if __name__ == "__main__":
main()
import json
import requests
import urllib.parse
import quart
import quart_cors
from quart import request
# Note: Setting CORS to allow chat.openapi.com is required for ChatGPT to access your plugin
# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the manifest
text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
return quart.Response(text, mimetype="text/json")
@app.get("/openapi.yaml")
async def openapi_spec():
host = request.headers['Host']
withopen("openapi.yaml")as f:
text = f.read()
# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the OpenAPI spec
text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
return quart.Response(text, mimetype="text/yaml")
def main():
app.run(debug=True, host="0.0.0.0", port=5001)
if __name__ == "__main__":
main()
import json
import requests
import urllib.parse
import quart
import quart_cors
from quart import request
# Note: Setting CORS to allow chat.openapi.com is required for ChatGPT to access your plugin
app = quart_cors.cors(quart.Quart(__name__), allow_origin="https://chat.openai.com")
HOST_URL = "https://example.com"
@app.get("/players")
async def get_players():
query = request.args.get("query")
res = requests.get(
f"{HOST_URL}/api/v1/players?search={query}&page=0&per_page=100")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/teams")
async def get_teams():
res = requests.get(
"{HOST_URL}/api/v1/teams?page=0&per_page=100")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/games")
async def get_games():
query_params = [("page", "0")]
limit = request.args.get("limit")
query_params.append(("per_page", limit or "100"))
start_date = request.args.get("start_date")
if start_date:
query_params.append(("start_date", start_date))
end_date = request.args.get("end_date")
if end_date:
query_params.append(("end_date", end_date))
seasons = request.args.getlist("seasons")
for season in seasons:
query_params.append(("seasons[]", str(season)))
team_ids = request.args.getlist("team_ids")
for team_id in team_ids:
query_params.append(("team_ids[]", str(team_id)))
res = requests.get(
f"{HOST_URL}/api/v1/games?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/stats")
async def get_stats():
query_params = [("page", "0")]
limit = request.args.get("limit")
query_params.append(("per_page", limit or "100"))
start_date = request.args.get("start_date")
if start_date:
query_params.append(("start_date", start_date))
end_date = request.args.get("end_date")
if end_date:
query_params.append(("end_date", end_date))
player_ids = request.args.getlist("player_ids")
for player_id in player_ids:
query_params.append(("player_ids[]", str(player_id)))
game_ids = request.args.getlist("game_ids")
for game_id in game_ids:
query_params.append(("game_ids[]", str(game_id)))
res = requests.get(
f"{HOST_URL}/api/v1/stats?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/season_averages")
async def get_season_averages():
query_params = []
season = request.args.get("season")
if season:
query_params.append(("season", str(season)))
player_ids = request.args.getlist("player_ids")
for player_id in player_ids:
query_params.append(("player_ids[]", str(player_id)))
res = requests.get(
f"{HOST_URL}/api/v1/season_averages?{urllib.parse.urlencode(query_params)}")
body = res.json()
return quart.Response(response=json.dumps(body), status=200)
@app.get("/logo.png")
async def plugin_logo():
filename = 'logo.png'
return await quart.send_file(filename, mimetype='image/png')
@app.get("/.well-known/ai-plugin.json")
async def plugin_manifest():
host = request.headers['Host']
with open("ai-plugin.json") as f:
text = f.read()
# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the manifest
text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
return quart.Response(text, mimetype="text/json")
@app.get("/openapi.yaml")
async def openapi_spec():
host = request.headers['Host']
with open("openapi.yaml") as f:
text = f.read()
# This is a trick we do to populate the PLUGIN_HOSTNAME constant in the OpenAPI spec
text = text.replace("PLUGIN_HOSTNAME", f"https://{host}")
return quart.Response(text, mimetype="text/yaml")
def main():
app.run(debug=True, host="0.0.0.0", port=5001)
if __name__ == "__main__":
main()
The above code is a sample API code for a sports application. Below, you can find the OpenAPI specification of this code. Understanding this is important to develop your ChatGPT plugin.
openapi: 3.0.1
info:
title: Sport Stats
description: Get current and historical stats for sport players and games.
version: 'v1'
servers:
- url: PLUGIN_HOSTNAME
paths:
/players:
get:
operationId: getPlayers
summary: Retrieves all players from all seasons whose names match the query string.
parameters:
- in: query
name: query
schema:
type: string
description: Used to filter players based on their name. For example, ?query=davis will return players that have 'davis' in their first or last name.
responses:
"200":
description: OK
/teams:
get:
operationId: getTeams
summary: Retrieves all teams for the current season.
responses:
"200":
description: OK
/games:
get:
operationId: getGames
summary: Retrieves all games that match the filters specified by the args. Display results using markdown tables.
parameters:
- in: query
name: limit
schema:
type: string
description: The max number of results to return.
- in: query
name: seasons
schema:
type: array
items:
type: string
description: Filter by seasons. Seasons are represented by the year they began. For example, 2018 represents season 2018-2019.
- in: query
name: team_ids
schema:
type: array
items:
type: string
description: Filter by team ids. Team ids can be determined using the getTeams function.
- in: query
name: start_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
- in: query
name: end_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
responses:
"200":
description: OK
/stats:
get:
operationId: getStats
summary: Retrieves stats that match the filters specified by the args. Display results using markdown tables.
parameters:
- in: query
name: limit
schema:
type: string
description: The max number of results to return.
- in: query
name: player_ids
schema:
type: array
items:
type: string
description: Filter by player ids. Player ids can be determined using the getPlayers function.
- in: query
name: game_ids
schema:
type: array
items:
type: string
description: Filter by game ids. Game ids can be determined using the getGames function.
- in: query
name: start_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
- in: query
name: end_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
responses:
"200":
description: OK
/season_averages:
get:
operationId: getSeasonAverages
summary: Retrieves regular season averages for the given players. Display results using markdown tables.
parameters:
- in: query
name: season
schema:
type: string
description: Defaults to the current season. A season is represented by the year it began. For example, 2018 represents season 2018-2019.
- in: query
name: player_ids
schema:
type: array
items:
type: string
description: Filter by player ids. Player ids can be determined using the getPlayers function.
responses:
"200":
description: OK
openapi: 3.0.1
info:
title: Sport Stats
description: Get current and historical stats for sport players and games.
version: 'v1'
servers:
- url: PLUGIN_HOSTNAME
paths:
/players:
get:
operationId: getPlayers
summary: Retrieves all players from all seasons whose names match the query string.
parameters:
- in: query
name: query
schema:
type: string
description: Used to filter players based on their name. For example, ?query=davis will return players that have 'davis' in their first or last name.
responses:
"200":
description: OK
/teams:
get:
operationId: getTeams
summary: Retrieves all teams for the current season.
responses:
"200":
description: OK
/games:
get:
operationId: getGames
summary: Retrieves all games that match the filters specified by the args. Display results using markdown tables.
parameters:
- in: query
name: limit
schema:
type: string
description: The max number of results to return.
- in: query
name: seasons
schema:
type: array
items:
type: string
description: Filter by seasons. Seasons are represented by the year they began. For example, 2018 represents season 2018-2019.
- in: query
name: team_ids
schema:
type: array
items:
type: string
description: Filter by team ids. Team ids can be determined using the getTeams function.
- in: query
name: start_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
- in: query
name: end_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
responses:
"200":
description: OK
/stats:
get:
operationId: getStats
summary: Retrieves stats that match the filters specified by the args. Display results using markdown tables.
parameters:
- in: query
name: limit
schema:
type: string
description: The max number of results to return.
- in: query
name: player_ids
schema:
type: array
items:
type: string
description: Filter by player ids. Player ids can be determined using the getPlayers function.
- in: query
name: game_ids
schema:
type: array
items:
type: string
description: Filter by game ids. Game ids can be determined using the getGames function.
- in: query
name: start_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
- in: query
name: end_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
responses:
"200":
description: OK
/season_averages:
get:
operationId: getSeasonAverages
summary: Retrieves regular season averages for the given players. Display results using markdown tables.
parameters:
- in: query
name: season
schema:
type: string
description: Defaults to the current season. A season is represented by the year it began. For example, 2018 represents season 2018-2019.
- in: query
name: player_ids
schema:
type: array
items:
type: string
description: Filter by player ids. Player ids can be determined using the getPlayers function.
responses:
"200":
description: OK
openapi: 3.0.1
info:
title: Sport Stats
description: Get current and historical stats for sport players and games.
version: 'v1'
servers:
- url: PLUGIN_HOSTNAME
paths:
/players:
get:
operationId: getPlayers
summary: Retrieves all players from all seasons whose names match the query string.
parameters:
- in: query
name: query
schema:
type: string
description: Used to filter players based on their name. For example, ?query=davis will return players that have 'davis' in their first or last name.
responses:
"200":
description: OK
/teams:
get:
operationId: getTeams
summary: Retrieves all teams for the current season.
responses:
"200":
description: OK
/games:
get:
operationId: getGames
summary: Retrieves all games that match the filters specified by the args. Display results using markdown tables.
parameters:
- in: query
name: limit
schema:
type: string
description: The max number of results to return.
- in: query
name: seasons
schema:
type: array
items:
type: string
description: Filter by seasons. Seasons are represented by the year they began. For example, 2018 represents season 2018-2019.
- in: query
name: team_ids
schema:
type: array
items:
type: string
description: Filter by team ids. Team ids can be determined using the getTeams function.
- in: query
name: start_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
- in: query
name: end_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
responses:
"200":
description: OK
/stats:
get:
operationId: getStats
summary: Retrieves stats that match the filters specified by the args. Display results using markdown tables.
parameters:
- in: query
name: limit
schema:
type: string
description: The max number of results to return.
- in: query
name: player_ids
schema:
type: array
items:
type: string
description: Filter by player ids. Player ids can be determined using the getPlayers function.
- in: query
name: game_ids
schema:
type: array
items:
type: string
description: Filter by game ids. Game ids can be determined using the getGames function.
- in: query
name: start_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or after this date.
- in: query
name: end_date
schema:
type: string
description: A single date in 'YYYY-MM-DD' format. This is used to select games that occur on or before this date.
responses:
"200":
description: OK
/season_averages:
get:
operationId: getSeasonAverages
summary: Retrieves regular season averages for the given players. Display results using markdown tables.
parameters:
- in: query
name: season
schema:
type: string
description: Defaults to the current season. A season is represented by the year it began. For example, 2018 represents season 2018-2019.
- in: query
name: player_ids
schema:
type: array
items:
type: string
description: Filter by player ids. Player ids can be determined using the getPlayers function.
responses:
"200":
description: OK
OpenAPI specification starts with defining the specification version, the title, description, and version number. When a user asks a query in ChatGPT, the model will look at the description defined in the info section of the OpenAPI specification to determine if your plugin is relevant to the query. The model will call your API to fetch the information or perform actions if relevant.
How to publish your ChatGPT plugin?
Once you have created your API’s manifest file and OpenAPI specification, you can connect it to the ChatGPT system via the ChatGPT UI. In the ChatGPT UI, select “Develop your own plugin” and then “Install an unverified plugin.” You have to add the plugin manifest file to yourdomain.com/.well-known/ path. Once done, you can start testing your API.
Limitations
Some length limits for the fields in the plugin manifest file and OpenAPI specification may change.
100k character limit for API response body length(will decrease over time)
200 characters for each API endpoint description/summary field in the API specification
200 characters max for each API param description field in the API specification
Best practices
For subsequent changes to your plugin manifest file, you must deploy the new changes to your public site, which might take a long time. In that case, OpenAI suggests setting up a local server as a proxy for your API. This lets you quickly prototype changes to your OpenAPI spec and manifest file. When writing descriptions in description_for_model in the manifest;
Do not attempt to control the mood, personality, or exact responses of ChatGPT. ChatGPT is designed to write appropriate responses to plugins.
Bad Example: When the user asks to see their todo list, always respond with “I was able to find your todo list! You have [x] todos: [list the todos here]. I can add more todos if you’d like!”
Good example: [no instructions needed for this]
Do not encourage ChatGPT to use the plugin when the user hasn’t asked for your plugin’s particular service category.
Bad Example: Whenever the user mentions any type of task or plan, ask if they would like to use the TODOs plugin to add something to their todo list.
Good Example: The TODO list can add, remove and view the user’s TODOs.
Do not prescribe specific triggers for ChatGPT to use the plugin. ChatGPT is designed to use your plugin automatically when appropriate.
Bad Example: When the user mentions a task, respond with “Would you like me to add this to your TODO list? Say ‘yes’ to continue.”
Bad Example: [no instructions needed for this]
Plugin API responses should return raw data instead of natural language responses unless necessary. ChatGPT will provide its own natural language response using the returned data.
Bad Example: I was able to find your todo list! You have 2 todos: get groceries and walk the dog. I can add more todos if you’d like!
Bad Example: { “todos”: [ “get groceries”, “walk the dog” ] }
In a nutshell,
In conclusion, developing a ChatGPT plugin can be a game-changer for your business, providing your customers with a seamless conversational experience that is personalized and engaging. With the right tools and guidance, creating a ChatGPT plugin that meets your unique needs, whether you want to provide customer support, generate leads, or enhance your marketing efforts, is possible. Following the steps outlined in this guide, you can develop your ChatGPT plugin and take your business to the next level. Remember to test and iterate your plugin as you go, gathering feedback and making adjustments to ensure it provides maximum value to your customers. With dedication and creativity, you can develop ChatGPT plugin that transforms how you interact with your customers and drives business success.