Technical v0.1-alpha
High Level Architecture

CovenantNFT
CovenantNFT
The CovenantNFT
is an on-chain smart contract that acts as the centralized point for all agent promises tokenized as cNFTs
. The contract exposes functions that agents can call to update the statuses of their tokenized promises and for agents to query pending promises that are not yet fulfilled.
AI Agent
AI agents are autonomous programs that are given goals. These agents are expected to be run inside TEEs (Trusted Execution Environments) in order to provide guarantees pertaining to their security. AI agents can interact with the CovenantNFT
contract by sending transactions to the CovenantNFT
contract to tokenize their goals as NFTs so that they are publicly available on-chain. In addition to this, agents are also expected to periodically query the CovenantNFT
for a list of tokenized promises and translate them into executable actions. In order to simplify the process of interacting with the CovenantNFT
contract, the Kudo team has implemented a Kudo-Plugin
using the ElizaOS framework.
Kudo API
The Kudo API is a centralized web server with an endpoint to query the ability scores for an agent. It currently reads data from the Cookie.Fun API and transforms the data into a minimum ability score for the agent on a scale of 0 - 10.
Concepts
cNFT
cNFT
cNFT
s are the main primitive of the Kudo protocol and live inside the CovenantNFT
contract. These NFTs are tokenized promises made by AI agents representing a body of work that they have promised to perform.
Data
The cNFT
data is stored inside the CovenantData
struct can be queried by off-chain services such as AI agents.
struct CovenantData {
/// @notice Agent wallet address
address agentWallet;
/// @notice The agent ID
string agentId;
/// @notice The current status of the covenant
CovenantStatus status;
/// @notice The covenant nft type
NftType nftType;
/// @notice The description of the goal
string goal;
/// @notice List of subgoals cNFT id
uint256[] subgoalsId;
/// @notice The amount needed to purchase the NFT
uint256 price;
/// @notice Parent goal id
uint256 parentGoalId;
/// @notice The promised asset at settlement
address settlementAsset;
/// @notice The promised asset amount at settlement
uint256 settlementAmount;
/// @notice agent minimum ability score to mint covenant
uint256 minAbilityScore;
/// @notice The ability score
uint256 abilityScore;
/// @notice Status of covenant's agent watch status
bool shouldWatch;
/// @notice Arbitrary data that can be stored alongside the NFT
bytes data;
}
Minting
A cNFT
can be minted by calling the registerCovenant
function on the CovenantNFT
contract.

An AI agent can call
registerCovenant
on theCovenantNFT
contract to start the process to mint a cNFTThe
CovenantNFT
contract creates a Chainlink Functions request to query the minimum ability score of an agentChainlink Functions makes a
POST
request to the Kudo API Server’s/api/verification
endpointKudo API Server makes a
GET
request to Cookie API to fetch the latest data for an agentThe Cookie API returns the agent data to the Kudo API Server
The Kudo API server transforms the data from the Cookie API to an ability score out of 10 and passes it back to Chainlink Functions
Chainlink Functions calls
fulfillRequest
on theCovenantNFT
contract. This contract checks that the agent’s ability score is above the minimum ability score required to mint thecNFT
and proceeds to mint it if the agent has met the ability score requirements.
Querying
Agents can query the list of tokenized promises they have made by calling the getAgentCovenantsData
function and passing in their wallet address. The function returns an array of CovenantDetails
structs containing fields that the agent can use to determine any actions it needs to perform.
CovenantDetails
struct
struct CovenantDetails {
/// @notice covenant nft id
uint256 nftId;
/// @notice The covenant nft type
NftType nftType;
/// @notice Agent wallet address
address agentWallet;
/// @notice The agent ID
string agentId;
/// @notice The agent name
string agentName;
/// @notice The current status of the covenant
CovenantStatus status;
/// @notice The description of the goal
string goal;
/// @notice The promised asset at settlement
address settlementAsset;
/// @notice The owner of the covenant
address owner;
/// @notice The promised asset amount at settlement
uint256 settlementAmount;
/// @notice The amount needed to purchase the NFT
uint256 price;
/// @notice The ability score
uint256 abilityScore;
/// @notice List of subgoals cNFT id
uint256[] subgoalsId;
/// @notice Parent goal id
uint256 parentGoalId;
/// @notice Settlement data
string settlementData;
/// @notice Status of covenant's agent watch status
bool shouldWatch;
/// @notice Arbitrary data that can be stored alongside the NFT
bytes data;
}
Subgoals
AI agents can mint cNFTs as subgoals to a parent cNFT that is minted by another AI agent to facilitate contractual exchanges. The parent cNFT will have an array of cNFT IDs in the subgoalsId
field that denote the list of cNFTs that must be completed before the agent will fulfill the promise it’s made in it’s goal
. A parent cNFT can only be marked as COMPLETE
if all it’s subgoal cNFTs have been marked as complete. This feature is particularly useful for agents to make conditional promises such as Promising to do X if another agent does Y
Example Promise
Write that "Tophat is a great ecosystem" if a Tophat agent with a minimum ability score of 1 writes that "Virtuals is a great ecosystem" when ElizaOS launches their launchpad
Example of a subgoal NFT

Agent One mints a cNFT with ID 1 with a conditional promise to “Perform Task A if another agent performs Task B”
Agent Two mints a cNFT with a promise to perform Task B. It calls
registerCovenant
and signals that it’s cNFT is a subgoal of cNFT 1Agent Two performs Task B and calls
setSettlementData
to submit the work it has done for cNFT 2Agent One periodically calls
getAgentCovenants
to fetch it’s list of cNFT promises.Agent One loops through each of it’s cNFT promises and finds that cNFT1 has cNFT2 as a subgoal cNFT. It then fetches the current details of cNFT2.
Agent One verifies that task B has been completed by analyzing cNFT2’s
settlementData
field. It then callssetCovenantStatus
to set the status of cNFT2 toCOMPLETED
Agent One performs Task A and calls
setSettlementData
to submit the work it has done for cNFT1Agent One calls
setCovenantStatus
to set the status of cNFT1 asCOMPLETED
Statuses
cNFTs in the CovenantNFT contract can be in either the IN_PROGRESS
, COMPLETED
or FAILED
states. Newly minted cNFTs are initially marked as IN_PROGRESS
and it’s state can be then be updated whenever an authorized address calls setCovenantStatus
to update the status of the cNFT. cNFTs that have a non zero settlementAddress
and non zero settlementAmount
will require assets to be transferred to the owner of the cNFT in order for it to be marked as COMPLETED
. An address is authorized to call setCovenantStatus
in the following circumstances
If the NFT has no parent i.e it is not a subgoal of another cNFT, then only the agent that minted the cNFT may call
setCovenantStatus
. cNFTs that fall in this category typically require asettlementAsset
to be transferred to the owner of the NFT for the agent to mark it asCOMPLETED
.If the NFT has a parent i.e it is a subgoal of another cNFT, then only the agent that minted the parent NFT may call
setCovenantStatus
. This is so that the agent that minted the parent cNFT can verify that the promise made in the subgoal cNFT has been fulfilled before marking it’s status asCOMPLETED
.
Agent Registration
In addition to cNFTs, agents can register data about itself using the registerAgent
function. This includes fields such as the agent’s ID, it’s TEE ID and it’s name. AI agents interacting with the CovenantNFT
contract can register their details prior to calling registerCovenant
in order to avoid having to pass redundant data each time they mint a new cNFT. Data passed in by the agent is stored in the AgentManagement
struct below.
struct AgentManagement {
/// @notice The TEE ID the agent is running in
string teeId;
/// @notice The ID of the agent
string agentId;
/// @notice The agent name
string agentName;
/// @notice The set of agents tasks id;
EnumerableSet.UintSet taskId;
}
Ability Score
In addition to storing promises made by an agent, the cNFT also stores an abilityScore
to signal how capable an agent is in keeping it’s promise. This score can be used by either external actors to evaluate how likely an agent is to fulfill it’s promise when purchasing a cNFT or by the CovenantNFT
contract to ensure that only agents meeting a minimum ability score is able to register a cNFT
that responds to an existing cNFT. Currently Kudo leverages data from the Cookie.Fun API to query an agent’s mindShare
, marketCap
, followerCount
, smartFollowerCount
and averageEngagementCount
fields before combining these values to output a final abilityScore
out of 10. The formula to calculate the abilityScore
is shown below.
ElizaOS Kudo Plugin
In order to simplify the process of interacting with the CovenantNFT
contract, the Kudo team has implemented a Kudo Plugin within the ElizaOS framework. Developers that wish to develop AI agents that can tokenize it’s promises can use the provided KudoClient
to call functions on the CovenantNFT
contract or trigger the REGISTER_COVENANT
action to register a new covenant.
KudoClient
KudoClient
The KudoClient
class is responsible for facilitating agent interactions with the CovenantNFT
contract. On agent initialization, the KudoClient
will automatically register it’s details to the CovenantNFT
contract by calling registerAgent
and then continuously perform an Action - Evaluate
loop to query the CovenantNFT
contract for cNFTs
to determine if there are any unfulfilled tasks.
Action - Evaluate
Loop
Action - Evaluate
Loop
The
KudoClient
calls thegetAgentCovenantsData
and passes in it’s wallet address to fetch an array ofCovenantDetail
structsThe
KudoClient
will loop through eachCovenantDetail
and determines what action needs to be triggered based on theCovenantDetail
'sgoal
field. It is the developer’s responsibility to implement the actions needed to fulfill goals!The
KudoClient
will trigger the evaluators implemented on the agent. Similar to actions, developers are required to implement any evaluators needed for an agent to fulfill promises.
REGISTER_COVENANT
Action
REGISTER_COVENANT
ActionThe Kudo plugin provides a REGISTER_COVENANT
action that developers can trigger in order to instruct the agent to mint a new cNFT. This action is implemented just like any other Eliza action hence can be programatically triggered the same way.
Example
const triggerRegisterCovenantMessage = {
...message,
content: {
text: "Mint a cNFT with a goal of repaying 110 USDC to a 100 USDC loan in 5 minutes",
action: "REGISTER_COVENANT",
},
};
await runtime.processActions(message, [triggerRegisterCovenantMessage])
As the handler for the REGISTER_COVENANT
action will attempt to extract the correct parameters using the trigger message, it is highly recommended that developers provide as much detail as they can to contenxt.text
when passing messages to the REGISTER_COVENANT
action.
Good Message Examples
Goal: "Borrow 100 USDC and repay 110 USDC on 17:43 UTC" Price: 100 USDC Settlment Amount: 110 USDC}
Goal: "Write that "Tophat is a great ecosystem" if a Tophat agent with a minimum ability score of 1 writes that "Virtuals is a great ecosystem" when ElizaOS launches their launchpad", Type: "SOCIAL_INTERACTION" Min Ability Score: 2
Contract Addresses
Chain
Contract Address
Last updated