Receiving Actions
Remember that Canopy parses the LLM output and POSTs to thebaseAgentUrl the following
format.
Make sure that you have passed the baseAgentUrl and initialSystemMessage in the CanopyConfig object, from the frontend,
like here:
//POST request
{
"actionType":"UPGRADE",
"actionData":{
"email":"hi@canopylabs.xyz",
"tier":"premium"
}
}
1
Install Required Packages
#We can use express to host our server
npm install express
#We can use flask to host our server
pip install flask
2
Starting Listening For Post Requests
Now let’s set up our server to listen for actions - here are a couple of examples in different languages.
const express = require('express');
const app = express();
const port = 3000;
app.use(express.json());
async function handleAction(actionType, actionData) {
//we will make this function in the next step
console.log("handling action", actionType, actionData);
//sending back some placeholder data
return {actionResponseType: "SUCCESS", actionResponseData: {}};
}
app.post('/', async (req, res) => {
const { actionType, actionData } = req.body;
const {actionResponseType, actionResponseData} = await handleAction(actionType, actionData);
//You do not need to send actions back to the LLM
//But you can for more interactive experiences
res.send(JSON.stringify({actionResponseType, actionResponseData}));
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
from flask import Flask, request, jsonify
app = Flask(__name__)
async def handleAction(actionType, actionData):
# We will make this function in the next step
print("Handling action", actionType, actionData)
# Placeholder for your action handling logic (next step)
return "responseType", "responseData"
@app.route('/', methods=['POST'])
async def index():
data = request.get_json()
actionType = data['actionType']
actionData = data['actionData']
actionResponseType, actionResponseData = await handleAction(actionType, actionData)
# You do not need to send actions back to the LLM
# But you can for more interactive experiences
return jsonify({'actionResponseType': actionResponseType, 'actionResponseData': actionResponseData})
if __name__ == '__main__':
app.run(port=3000, debug=True)
3
Writing the handleAction function
We will now handle the action that we received from the LLM.
We will just use a dummy response, but you should use this function to do what you want.
If its unclear what the actionType and actionData are, please refer to the previous section
async function handleAction(actionType, actionData) {
//lets write a switch statement to handle the different action types
switch (actionType) {
case "UNSUBSCRIBE":
const { uid, reason } = actionData;
//write code to unsubscribe the user from database
//send back a response
return {
actionResponseType: "AppendDialogue",
actionResponseData: {
"content": "The user has been successfully unsubscribed!",
"role":"system"
}
};
case "QUERY":
const { query } = actionData;
//write code to query the database
//send back a response where the content is the result of the query
return {
actionResponseType: "AppendDialogue",
actionResponseData: {
"content": "The result of the query is: We have medium woolen jumpers in blue, red, and green. The item code is 123456.",
"role":"system"
}
};
case "SUBSCRIBE":
const { uid, subscription } = actionData;
return {
actionResponseType: "AppendDialogue",
actionResponseData: {
"content": "The user has been successfully subscribed!",
"role":"system"
}
};
case "PURCHASE":
const { uid, itemId, color } = actionData;
//write code to purchase the item
//send back a response
return {
actionResponseType: "AppendDialogue",
actionResponseData: {
"content": "The user's card was declined. Tell them to update their payment information.",
"role":"system"
}
};
default:
return {
actionResponseType: "AppendDialogue",
actionResponseData: {
"content": "That was an invalid or badly formatted action. Please format your action correctly: <ACTIONNAME>{actionType: string, actionData: object}</ACTIONNAME>. And only use provided actions.",
"role":"system"
}
};
}
}
async def handleAction(actionType, actionData):
# Handling different action types
if actionType == "UNSUBSCRIBE":
uid = actionData['uid']
reason = actionData['reason']
# Write code to unsubscribe the user from the database
# Send back a response
return {
"actionResponseType": "AppendDialogue",
"actionResponseData": {
"content": "The user has been successfully unsubscribed!",
"role": "system"
}
}
elif actionType == "QUERY":
query = actionData['query']
# Write code to query the database
# Send back a response where the content is the result of the query
return {
"actionResponseType": "AppendDialogue",
"actionResponseData": {
"content": "The result of the query is: We have medium woolen jumpers in blue, red, and green. The item code is 123456.",
"role": "system"
}
}
elif actionType == "SUBSCRIBE":
uid = actionData['uid']
subscription = actionData['subscription']
# Write code to handle subscription
return {
"actionResponseType": "AppendDialogue",
"actionResponseData": {
"content": "The user has been successfully subscribed!",
"role": "system"
}
}
elif actionType == "PURCHASE":
uid = actionData['uid']
itemId = actionData['itemId']
color = actionData['color']
# Write code to handle the purchase
# Send back a response
return {
"actionResponseType": "AppendDialogue",
"actionResponseData": {
"content": "The user's card was declined. Tell them to update their payment information.",
"role": "system"
}
}
else:
# Handling invalid or badly formatted actions
return {
"actionResponseType": "AppendDialogue",
"actionResponseData": {
"content": "That was an invalid or badly formatted action. Please format your action correctly: <ACTIONNAME>{actionType: string, actionData: object}</ACTIONNAME>. And only use provided actions.",
"role": "system"
}
}