Agent Asynchronous Loops
Introduction
Agents need to communicate, perform tasks, and respond to events simultaneously and independently within any decentralized system. This guide shows how to create asynchronous agents that operate in parallel, enabling them to handle their own workflows while still interacting with other agents or external processes.
By using asynchronous loops and attaching agents to external event loops, you can build agents that manage tasks simultaneously, send periodic updates, and process incoming messages in real-time. This approach is particularly useful when working with distributed systems, where agents must collaborate or handle multiple simultaneous operations without interruptions.
Supporting documentation
Walk-through
The following scripts show how to define agents, manage their life-cycle and attach them to external asynchronous loops.
Script 1
The first script depicts how to attach an agent to an external event loop and allow it to run simultaneously with other asynchronous tasks.
First of all, let's create a Python script:
windowsecho. > external_loop_attach.py
Now, paste the below code into it:
external_loop_attach.pyimport asyncio import contextlib from uagents import Agent, Bureau, Context loop = asyncio.get_event_loop() agent = Agent( name="looper", seed="<YOUR_SEED>", port=8001, endpoint=["http://127.0.0.1:8001/submit"], ) bureau = Bureau( agents=[agent], ) @agent.on_event("startup") async def startup(ctx: Context): ctx.logger.info(">>> Looper is starting up.") @agent.on_event("shutdown") async def shutdown(ctx: Context): ctx.logger.info(">>> Looper is shutting down.") async def coro(): while True: print("doing hard work...") await asyncio.sleep(1) if __name__ == "__main__": print("Attaching the agent or bureau to the external loop...") loop.create_task(coro()) # > when attaching the agent to the external loop loop.create_task(agent.run_async()) # > when attaching a bureau to the external loop # loop.create_task(bureau.run_async())
This script demonstrates using an agent with an external event loop. We begin by importing the necessary libraries; we then proceed and instantiate an Agent named looper
with a seed
(<YOUR_SEED>
). Then, we create a bureau
to manage the Agent.
The startup()
function, marked with the .on_event("startup")
decorator, logs a message when the Agent starts, while the shutdown()
function logs a message when the Agent shuts down.
A coro()
function simulates a long-running task that prints "Doing hard work..."
every second. This task runs independently, highlighting the Agent's ability to handle multiple simultaneous tasks. Both the Agent and the external task (coro
) are attached to the event loop using loop.create_task()
, allowing them to execute simultaneously.
In the __main__
block, a message indicates the process of attaching tasks to the event loop. The loop.create_task(coro())
schedules the coro
task, and loop.create_task(agent.run_async())
schedules the Agent's operations, enabling both to run without blocking other tasks.
Finally, a context manager suppresses KeyboardInterrupt
exceptions (which are typically raised when the user presses Ctrl+C
to stop the program) thus ensuring the program shuts down gracefully without errors or tracebacks.
Script 2
The goal of the second script is to create an agent that runs tasks inside an external event loop. The agent can execute certain actions (e.g., print messages or respond to events) while simultaneously performing a separate background task.
Let's start by creating a Python script:
windowsecho. > external_loop_run.py
Then, let's paste the below code into it:
external_loop_run.pyimport asyncio from uagents import Agent, Bureau, Context loop = asyncio.get_event_loop() agent = Agent( name="looper", seed="<YOUR_SEED>", loop=loop, port = 8000, endpoint = ["http://127.0.0.1:8000/submit"], ) bureau = Bureau( agents=[agent], loop=loop, ) @agent.on_event("startup") async def startup(ctx: Context): ctx.logger.info(">>> Looper is starting up.") @agent.on_event("shutdown") async def shutdown(ctx: Context): ctx.logger.info(">>> Looper is shutting down.") async def coro(): while True: print("doing hard work...") await asyncio.sleep(1) if __name__ == "__main__": print("Starting the external loop from the agent or bureau...") loop.create_task(coro()) # > when starting the external loop from the agent agent.run()
We start by importing the required libraries to correctly run this script. We then create an asynchronous event loop using asyncio.get_event_loop()
. This loop is used to handle all asynchronous operations, such as the agent's actions and background tasks.
We proceed and create an agent called looper
using the Agent
class. The agent takes three parameters: name
, seed
, and loop
. Remember to provide a seed
for your agent otherwise a random address will be generated every time you run the agent. We then create a bureau
object using the Bureau
class. The bureau
is created with a single agent, looper
.
We can then define our agent functions to handle the agent's lifecycle events:
startup()
: This function runs when the agent is started. It logs a message to indicate that the agent has been started up.shutdown()
: This function runs when the agent is shut down. It logs a message to indicate that the agent has been stopped.
In the next step, we define the coro()
function; As before, this function defines an infinite loop where the agent performs a task ("doing hard work..."
) every second. This simulates a long-running background task. The await asyncio.sleep(1)
pauses execution for one second between each iteration, allowing other tasks to run during that time.
Finally, in the __main__
block, we define a message to be printed indicating that the external event loop is being started. The loop.create_task(coro())
schedules the coro()
coroutine to run in the background, simultaneously with the agent's operations.
Expected Output
We are now ready to run the scripts.
The output should be similar to the following:
-
Script 1:
Attaching the agent or bureau to the external loop...
-
Script 2:
Starting the external loop from the agent or bureau... INFO: [looper]: >>> Looper is starting up. INFO: [looper]: Agent inspector available at https://agentverse.ai/inspect/?uri=http%3A//127.0.0.1%3A8000&address=agent1qwep424538eh7fcruqcnx8la3q3tgl4tgksrcdtahqs7dqgs4rewsx4jefu INFO: [looper]: Starting server on http://0.0.0.0:8000 (Press CTRL+C to quit) doing hard work... doing hard work... doing hard work... doing hard work... doing hard work...