Restaurant Booking Demo¶
To showcase how easy it is to create μAgents for a particular application, here is an example of how to create a custom message type using the Model
class.
For this example, we will create a restaurant booking service with two agents: a restaurant
with tables available and a user
requesting table availability.
Restaurant Setup¶
We can create a restaurant agent with its corresponding http endpoint. We will also make sure that the agent is funded so it is able to register in the Almanac contract.
from uagents import Agent
from uagents.setup import fund_agent_if_low
restaurant = Agent(
name="restaurant",
port=8001,
seed="restaurant secret phrase",
endpoint=["http://127.0.0.1:8001/submit"],
)
fund_agent_if_low(restaurant.wallet.address())
query_proto
and book_proto
are built from message handlers in the same way as agents. See query protocol and book protocol for the details and logic behind these protocols, but for now we will simply import them. You will need to add these files inside a protocols
folder in the same directory you are running your agent. See agent protocols for more information.
Next we build the restaurant agent from these protocols and set the table availability information.
from protocols.book import book_proto
from protocols.query import query_proto, TableStatus
# build the restaurant agent from stock protocols
restaurant.include(query_proto)
restaurant.include(book_proto)
TABLES = {
1: TableStatus(seats=2, time_start=16, time_end=22),
2: TableStatus(seats=4, time_start=19, time_end=21),
3: TableStatus(seats=4, time_start=17, time_end=19),
}
Storage¶
We will now store the TABLES
information in the restaurant agent and run it.
# set the table availability information in the restaurant protocols
for (number, status) in TABLES.items():
restaurant._storage.set(number, status.dict())
if __name__ == "__main__":
restaurant.run()
User Setup¶
We will first import the needed objects and protocols. We will also need the restaurant agent's address to be able to communicate with it.
from protocols.book import BookTableRequest, BookTableResponse
from protocols.query import (
QueryTableRequest,
QueryTableResponse,
)
from uagents import Agent, Context
from uagents.setup import fund_agent_if_low
RESTAURANT_ADDRESS = "agent1qw50wcs4nd723ya9j8mwxglnhs2kzzhh0et0yl34vr75hualsyqvqdzl990"
user = Agent(
name="user",
port=8000,
seed="user secret phrase",
endpoint=["http://127.0.0.1:8000/submit"],
)
fund_agent_if_low(user.wallet.address())
Now we create the table query to generate the QueryTableRequest
using the restaurant address. If the request has not been completed before, we send the request to the restaurant agent.
table_query = QueryTableRequest(
guests=3,
time_start=19,
duration=2,
)
# This on_interval agent function performs a request on a defined period
@user.on_interval(period=3.0, messages=QueryTableRequest)
async def interval(ctx: Context):
completed = ctx.storage.get("completed")
if not completed:
await ctx.send(RESTAURANT_ADDRESS, table_query)
The function below activates when a message is received back from the restaurant agent.
handle_query_response
will evaluate if there is a table available, and if so, respond with a BookTableRequest
to complete the reservation.
@user.on_message(QueryTableResponse, replies={BookTableRequest})
async def handle_query_response(ctx: Context, sender: str, msg: QueryTableResponse):
if len(msg.tables) > 0:
ctx.logger.info("There is a free table, attempting to book one now")
table_number = msg.tables[0]
request = BookTableRequest(
table_number=table_number,
time_start=table_query.time_start,
duration=table_query.duration,
)
await ctx.send(sender, request)
else:
ctx.logger.info("No free tables - nothing more to do")
ctx.storage.set("completed", True)
Then, handle_book_response
will handle messages from the restaurant agent on whether the reservation was successful or unsuccessful.
@user.on_message(BookTableResponse, replies=set())
async def handle_book_response(ctx: Context, _sender: str, msg: BookTableResponse):
if msg.success:
ctx.logger.info("Table reservation was successful")
else:
ctx.logger.info("Table reservation was UNSUCCESSFUL")
ctx.storage.set("completed", True)
if __name__ == "__main__":
user.run()
Finally, run the restaurant agent and then the user agent from different terminals.
You should see this printed on the user terminal:
See the full example scripts at restaurant and user.