A Beginner’s Journey into AI with Fetch.ai: Exploring the AI Agents(Part-1)

Abhi gangani
Fetch.ai
Published in
10 min readJun 18, 2024

Introduction :

AI Agents are leading the charge in technology innovation, transforming our interaction with digital systems. These smart agents not only assist in making informed decisions but also boost efficiency across multiple sectors. One standout in this realm is Fetch.ai, a groundbreaking platform that champions decentralised AI. Fetch.ai harnesses the power of intelligent agents to craft a vibrant and dynamic ecosystem, pushing the boundaries of what AI can achieve.

Fetch.ai defines AI agents as autonomous programs capable of performing significant actions within a decentralized network. These agents are designed to learn, predict, and transact independently, all while adhering to predefined protocols. This functionality enables them to engage in complex interactions, manage tasks without human intervention, and optimize processes in real-time.

The uAgents Framework, developed by Fetch.ai, provides a lightweight and flexible solution for developing AI agents. This framework allows developers to create, deploy, and manage agents that can communicate with one another, collaborate to solve problems, and engage in decentralized transactions. By leveraging the uAgents Framework, developers can build intelligent agents that drive significant improvements in areas such as supply chain management, financial services, and IoT network connectivity. Going forward, we will denote AI agents as uAgents.

In this article, I’ll walk you through the process of setting up your first uAgent using Fetch.ai’s uAgents library. This step-by-step tutorial is perfect for beginner developers who are new to AI and decentralized systems. By the end of this guide, you’ll have a solid grasp of how to create, deploy, and interact with AI agents within the Fetch.ai ecosystem.

Let’s embark on this exciting journey into the world of uagents and explore how you can utilise Fetch.ai’s tools to build intelligent, autonomous solutions.

Understanding uAgents

What is uAgent?

uAgents are autonomous programs designed to perform specific tasks, interact with other agents autonomously, and make decisions based on predefined protocols and real-time data. These agents operate independently, managing complex interactions and optimising processes within a decentralised network.

Importance and Application

AI Agents are revolutionising various industries by automating tasks, enhancing decision-making, and enabling new forms of digital interaction. They are utilized in supply chain management, financial services, IoT connectivity, and numerous other fields to boost efficiency and reduce costs.

Component of Fetch.AI ecosystem

Fetch.AI Ecosystem

Agentverse

Agentverse is a managed hosting platform and online integrated development environment (IDE) for uagents. It provides tools for registering, discovering, and managing agents within the Fetch.ai network. Following are the features of Agentverse:

  • Managed Hosting : Simplifies the deployment and management of uagents.
  • Agent Discovery : This feature allows agents to be registered and discovered by other agents within the network. This registration is crucial for interaction and collaboration among agents.
  • Communication Tools : These tools facilitate seamless communication between agents, enabling them to exchange messages, collaborate on tasks, and execute protocols efficiently.

Agentverse lowers the barrier to entry for developers by providing a robust environment to create, test, and deploy AI agents efficiently.

AI Engine

The AI Engine is a system that translates human input into actionable commands for AI agents. It enables the development of intelligent systems that can understand and respond to user queries. The functionalities of AI Engine includes :

  • Human Input Translation: Converts text input into commands that agents can execute.
  • Integration with Agents: Enhances agent capabilities by providing a scalable AI infrastructure.
  • Objectives, Primary and Secondary Functions: The AI Engine breaks down user objectives into primary and secondary functions. Primary functions are the main tasks, while secondary functions are subtasks or additional actions required to complete the primary function. This architecture allows the AI Engine to efficiently manage and route tasks to the appropriate agents​.

DeltaV

DeltaV is an assistive chat interface developed by Fetch.AI that allows users to interact with AI agents through natural language queries. DeltaV facilitates user interaction by translating queries into commands that agents can understand and act upon using AI Engine.

DeltaV can be used in various scenarios, such as customer support, information retrieval, and task automation like booking travel tickets and cabs, etc.

Almanac Contract

The Almanac contract serves as a registry for agents and their functions within the Fetch.ai network. It ensures that agents are discoverable and their capabilities are indexed for efficient retrieval by the AI Engine. Alamanac contract has following features:

  • Function Registration: Agents register their functions in the Almanac contract, making them accessible to the AI Engine and other agents.
  • Discoverability: Ensures that registered agents and their functions can be easily found and utilized within the Fetch.ai ecosystem​

Creating our First Agent

Setting up the environment

Prerequisites

  • Python: Ensure you have Python 3.8 or above installed.
  • uAgents Library: Install the uAgents library using pip.

Creating a simple agent

Before creating an agent lets understand what context is. The context object in Fetch.ai's uAgents framework plays a crucial role in managing the state and operations of an uagent. Here are the key aspects of the context object:

  • The context object represents the environment in which messages are handled and processed by the agent.
  • It provides essential methods and attributes that facilitate the agent’s interaction with its environment, storage, and other agents.

Code Walk-through

  • Creating basic agent in Python
from uagents import Agent, Context, Model, Protocol

agent = Agent(name="SimpleAgent", seed = "A random Secret phrase") # seed is used to get back the same agent addres
  • Using decorators

@on_event()

The on_event decorator is used to trigger agent when it is starting up or shutting down.

@agent.on_event("startup")
async def startup_event(ctx : Context):
ctx.logger.info(f'Hi my name is {agent.name} and my address is {agent.address}.')

@on_interval(period = 10.0)

The on_interval decorator is used to trigger an agent in a given period of seconds.

@agent.on_interval(period = 10)
async def interval_handler(ctx : Context):
ctx.logger.info(f'Hi my name is {agent.name} and I am using on_interval every 10 seconds.')

@on_message(model)

The on_message decorator is used to handle messages sent to the agent.

class Request(Model): #defining data model to for message
request : str
class Response(Model):
response : str

@agent.on_message(model = Request, replies = Response)
async def message_handler(ctx : Context, sender : str, msg: Request): # sender is the sender of message and msg is data model for recieved message
ctx.logger.info(f'Hi my name is {agent.name} and I got a message from {sender} and message is {msg.request}')
await ctx.send(sender, Response(response = 'I Got your message'))

In the Fetch.ai uAgents framework, communication between agents is facilitated by a secure and structured process. When an agent wants to send a message, it creates the message content and signs it with its identity, ensuring authenticity and integrity. The uAgents framework then encapsulates these signed messages along with the recipient’s address into an envelope and handles its delivery. Upon receiving the message, the recipient agent uses the framework to verify the signature, confirming that the message is from the claimed sender and has not been tampered with. The framework then processes the message and triggers any defined handlers for that message type, allowing the agent to execute specific functions or respond back. Communication can occur locally for testing and debugging or remotely via the Almanac contract, which registers and discovers agents, enabling a seamless exchange of information across the network. Importantly, these tasks are performed asynchronously, allowing agents to operate concurrently and handle multiple tasks efficiently. This robust mechanism allows agents to collaborate and perform complex tasks autonomously by exchanging data and commands efficiently.

Now Let’s, build two agents and make them communicate to each other.

from uagents import Agent,Model,Context,Bureau

# Defining Message and Response data models
class Message(Model):
message : str

class Response(Model):
response : str

# Creating 2 agents
alice = Agent(name = 'alice', seed = 'A random seed phrase for alice.')
bob = Agent(name = 'bob', seed = 'A random seed phrase for bob.')

# Interval handler for alice
@alice.on_interval(period = 5.0)
async def interval_messenger(ctx: Context):
ctx.logger.info('I am sending message to Bob')
await ctx.send(bob.address, Message(message = 'I am Alice, How are you bob'))

# Message handler for alice
@alice.on_message(model=Response)
async def alice_message_handler(ctx: Context, sender: str, msg: Response):
ctx.logger.info(f"Received message from {sender}: {msg.response}")

# Message handler for bob
@bob.on_message(model = Message, replies = Response)
async def bob_message_handler(ctx: Context, sender : str, msg : Message):
ctx.logger.info(f'I have recieved message from {sender} : {msg.message}')
await ctx.send(sender, Response(response = 'I am bob, How are you alice'))

bureau = Bureau() # This class manages a collection of agents and orchestrates their execution.
bureau.add(alice)
bureau.add(bob)
if __name__ == "__main__":
bureau.run()

Expected Output

abhimanyugangani@Abhimanyus-MacBook-Pro iitm eval % python3 sample.py
INFO: [alice]: I am sending message to Bob
INFO: [ bob]: I have recieved message from agent1qtupv37d3tn2wcwldfexgy00vg43ka3mgdnlgmmfz2dq3ksv3eyu789x4nn : I am Alice, How are you bob
INFO: [bureau]: Starting server on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: [alice]: Received message from agent1qv60dhaaksrvd0e9yv2e3ct2wfmrtku8ulexf0razywp4scgedwxwz0nmav: I am bob, How are you alice
INFO: [alice]: I am sending message to Bob
INFO: [ bob]: I have recieved message from agent1qtupv37d3tn2wcwldfexgy00vg43ka3mgdnlgmmfz2dq3ksv3eyu789x4nn : I am Alice, How are you bob
INFO: [alice]: Received message from agent1qv60dhaaksrvd0e9yv2e3ct2wfmrtku8ulexf0razywp4scgedwxwz0nmav: I am bob, How are you alice
INFO: [alice]: I am sending message to Bob
INFO: [ bob]: I have recieved message from agent1qtupv37d3tn2wcwldfexgy00vg43ka3mgdnlgmmfz2dq3ksv3eyu789x4nn : I am Alice, How are you bob
INFO: [alice]: Received message from agent1qv60dhaaksrvd0e9yv2e3ct2wfmrtku8ulexf0razywp4scgedwxwz0nmav: I am bob, How are you alice

Now that we know about how agent’s communicate, it’s time to introduce Agentverse which makes agent building process way more easier. Click on Agentverse and log in using your Google account. Go to My agents and create +New Agent.

Here we are going to make our first DeltaV Integration. Click on My First agent and submit. Open this agent from my agents and you can see the agent’s code.

This looks very similar, let’s update the code as shown below, here we are using a simple request library to make an API call and get the nutritional details about the food. Get your API key from Recipe-nutrtion-API.

Paste the below code which handles the message for NutritionRequest for recipe name and provides the list of nutritions in the requested recipe. Run the code by hitting the Run button.

# Import required libraries
import requests
from ai_engine import UAgentResponse, UAgentResponseType

# Define a data model for getting nutrition request
class NutrientRequest(Model):
recipe_name : str

# Create a protocol for the Hugging Face finbert agent
nutrients_protocol = Protocol("Recipe Nutrients Protocol")

# Defining function to get nutrition details:
async def nutrition_analysis(recipe_name):
headers = {
"X-RapidAPI-Key": NUTRITION_API_KEY,
"X-RapidAPI-Host": "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com"
}
# Api request to get recipe id
url_recipe = "https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/search"
querystring = {"query": recipe_name}

response_recipe = requests.get(url_recipe, headers=headers, params=querystring)
data_recipe = response_recipe.json()
recipe_id = data_recipe['results'][0]['id']

# API call to get nutritions
url_nutrients = f"https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/{recipe_id}/nutritionWidget.json"
response_nutrients = requests.get(url_nutrients, headers=headers)
nutrients = response_nutrients.json()

# Collecting basic nutrition facts
nutrition_list = []

for nutrient in nutrients["nutrients"]:
nutrition_list.append(f"{nutrient['name']}: {nutrient['amount']}{nutrient['unit']}")

return nutrition_list

# Message handler to process nutrition request
@nutrients_protocol.on_message(model=NutrientRequest, replies=UAgentResponse)
async def on_nutrient_request(ctx: Context, sender: str, msg: NutrientRequest):
ctx.logger.info(f"Received Recipe Nutrient request with recipe name: {msg.recipe_name}")
nutrients = await nutrition_analysis(msg.recipe_name)
ctx.logger.info(nutrients)
nutrients_string = nutrients.join('\n')
await ctx.send(sender, UAgentResponse(message=str(nutrients_string), type=UAgentResponseType.FINAL))

agent.include(nutrients_protocol)

Now you might be wondering what is this protocol and what is the use case. So, to make our Agents DeltaV Compatible, we use protocol, and include protocol in agent. Protocols in the Fetch.ai uAgents framework define the rules and formats for communication between agents. They ensure that agents can understand and correctly interpret the messages they exchange.

Note : In Agentverse IDE you don’t have to import uagents library, defining the agent, funding the agents and running the agent.

Now go to the Deploy tab on your agent and click + New Function.

Now there are different details in function. Give relevant name to your function. In description for AI Engineyou have to provide description of what your function does. AI Engine searches for your function on the basis of this description. Choose Primary function for your application. We will discuss more about primary and secondary function in the second next part of this article.

Remember having recipe_name field in our NutrtionRequest Data model. This will popup in function and you have to provide a description about what this field means to the AI Engine.

Please fill in below details for our example:

{
"Function Title": "Food Nutrition Analysis",
"Description for AI Engine": "This helps to get Nutrition details for a given <recipe_name>.",
"Application": "Primary function",
"Protocol": "Recipe Nutrients Protocol", // Auto populating from agent script
"Model": "Nutrition Request", // Auto populating from agent script
"Fields": {
"recipe_name": {
"Description": "Ask this from user, This describes the recipe name for which the user wants to get Nutrition details."
}
}
}

Create this function and click on Test in DeltaV, it will take you to DeltaV. Write your objective something like, i want to get nutrition details for some recipe and toggle Advanced Options and select My Functions until you have published your function.

Testing in DeltaV and Giving our objective.

Select your function, and submit.

Using our function and getting nutrition details.

So, this was Agent, Agentverse, DeltaV for you. In the next part we will discuss more on DeltaV and Agentverse. We will learn how to implement primary and secondary functions. How to link them together, how AI Engine links them together.

If you wish to learn more and go through more Examples or Guides go to Fetch.AI Documentation. If you have any queries or discussions go to Discord channel. For more details on uAgents library you can visit our GitHub.

You can also visit below mentioned playlist to understand more about uAgents.

--

--