Skip to main content

Action Taking Agents

Agents can take actions like retrieve data, manipulate data in a database, and much more. In fact, anything that can be captured by an API call is a good foundation for an agent’s capabilities.

Instructions for actions are embedded into the dialogues that the AI produces. We recommend you use gpt-4-turbo for agents that need to take actions.

Lets work through a simple example.

First, let’s come up with some simple actions that an agent could take. We are going to pretend that the agent can subscribe or delete users.

Step 1: Define your Actions

First, we have to tell Canopy what actions they are allowed to take and some more information about each action. This is done by passing an object containing the agent’s actions through CanopyConfig.
const CanopyConfig = {
    model:"gpt-4-turbo", 
    ...
    actionAgents: [
      {
        actionId: "UPGRADE",
        description: "Upgrade the user account",
        data: {
          email: "The email of the user",
          tier: "The tier to upgrade to (either pro or premium)",
        },
        endpoint: "https://yourserver.com/api/create",
        method: "POST",
      },
      {
        actionId: "DELETE",
        description: "Delete the user account",
        data: {
          email: "The email of the user",
        },
        endpoint: "https://yourserver.com/api/delete",
        method: "POST",
      },
      ...
    ]
};

const canopy = new Canopy(CanopyConfig);

Action Parameters

actionId
string
required
The name used to identify this action. It should be one word and descriptive of the action.
description
string
required
A short description of the action using natural language.
data
JSON
required
The data that will be passed to the API endpoint. The content of each parameter should be a description of the data. You can also add additional information using natural language about the data (e.g. tier: "The tier to upgrade the user to (either pro or premium)).
endpoint
string
required
The endpoint that the action will make a request to.
method
string
default:"POST"
The type of HTTP request that will be sent from the endpoint.

Step 2: Agent initiates Actions

Now that you have told Canopy what actions it can take. Let’s imagine a conversation may go like:

[
    {
        role: "user", 
        content: `Hey I want to upgrade my account to premium.`
    }, 
    {
        role: "assistant", 
        content: `Great! What is your email address?`
    }, 
    {
        role:"user", 
        content: `Hi at canopy ai dot xyz`
    }, 
    {
        role:"assistant", 
        content:`
        Thanks. I'm upgrading your account now.
            <UPGRADE> 
                {
                    "email": "[email protected]", 
                    "tier":" premium"
                }
            </UPGRADE> 
        `
    }
    ...
]

At this point in the conversation, Canopy will parse the last dialogue and say Thanks. I’m upgrading your account now.

It will simultaneously call the endpoint with the information associated with that action object.

//POST request sent to https://yourserver.com/api/create with data:

{
    "email": "[email protected]", 
    "tier": "premium"
}
You should have set up a server hosted at the endpoint which is ready to recieve these requests.

Action response to client socket

When the request to the endpoint has been completed, Canopy will send a response to the client socket in the following format:
{
    messageType: "actionAgentResponse",
    success, // whether the HTTP request was successful
    data // the data returned by the endpoint
}

Step 3: Respond to Actions (optional)

You may optionally choose to respond to actions using the CRUD operations defined here. For example, you may wish to tell the user they have insufficient credit to upgrade to premium. In this case respond with JSON objects.
{
    "actionResponseType":"AppendDialogue", 
    "actionResponseData":{
        "role": "system",
        "content": "The user was unable to upgrade because they have insufficient credit. Tell them to buy more credit."
    }
}
Here you should use the key parameters actionResponseType which can be one of ReadConversation, AppendDialogue, UpdateDialogue, DeleteDialogue and the actionResponseData parameter which should pass the same data as defined earlier but in JSON form. Now Canopy will add this message to the conversation so far and the conversation will continue in a full interactive way. Here is what the messageThread may look like once this has happened.

[
    //with the system message above somewhere prior in the conversation
    ...
    {
        role:"user", 
        content:`hey I want to upgrade my account to premium`
    }, 
    {
        role:"assistant", 
        content:`Great! What is your email address?`
    }, 
    {
        role:"user", 
        content:`hi at canopy ai dot xyz`
    }, 
    {
        role:"assistant", 
        content:`
        Thanks. I'm upgrading your account now.
            <UPGRADE> 
                {
                    "email":"[email protected]", 
                    "tier":"premium"
                }
            </UPGRADE> 
        `
    }, 
    {
        role:"user", 
        content:`Thank you, no rush!`
    },
    {
        role:"system", 
        content:`The user was unable to upgrade because they have insufficient credit. Tell them to buy more credit.`
    },
    {
        role:"assistant", 
        content:`Unfortunately, you don't have enough credit yet - you can buy some...`
    },
    ...
]

Tips and tricks

Here are some helpful suggestions:
  • Use the provided template for action calling above - Canopy can only parse action data in the format shown with:
<ACTION_ID>
{
   // ... action data as json ...
}
</ACTION_ID>
  • Remember you can pass a user ID in the system message. You probably know which user is on your website and can identify them by a user id. You do not need to ask the user to identify themselves most of the times:
CanopyConfig = {
    initialSystemMessage = `...
                                // A list of actions that are user specific
                                // so they use a userId parameter

                                And also the users id (userId) is E2e9d3jd3d3 
                            `
}