Agents and container¶
In mango, agents live in a
container. The container is responsible for everything network related of the agent.
This includes in particular sending and receiving of messages, but also message distribution to the correct agent or
serialization and deserialization of messages.
Container also help to to speed up message exchange between agents that run on the same physical hardware,
as data that is exchanged between such agents will not have to be sent through the network.
In mango, a container is created using the classmethod
@classmethod async def create_container(cls, *, connection_type: str = 'tcp', codec: Codec = None, clock: Clock = None, addr: Optional[Union[str, Tuple[str, int]]] = None, proto_msgs_module=None, **kwargs):
The factory method is a coroutine, so it has to be scheduled within a running asyncio loop. A simple container, that uses plain tcp for message exchange can be created as follows:
import asyncio from mango import create_container async def get_simple_container(): container = await create_container(addr=('localhost', 5555)) return container simple_container = asyncio.run(get_simple_container()))
A container can be parametrized regarding its connection type (‘tcp’ or ‘MQTT’) and regarding the codec that is used for message serialization. The default codec is JSON (see section Codecs for more information). It is also possible to define the clock that an agents scheduler should use (see section scheduling).
After a container is created, it is waiting for incoming messages on the given address. As soon as the container has some agents, it will distribute incoming messages to the corresponding agents and allow agents to send messages to other agents.
At the end of its lifetime, a
container should be shutdown by using the method
It will then shutdown all agents that are still running
in this container and cancel running tasks.
mango agents can be implemented by inheriting from the abstract class
This class provides basic functionality such as to register the agent at the container or
to constantly check the inbox for incoming messages.
Every agent lives in exactly one container and therefore an instance of a container has to be
__init__() of an agent is called.
Custom agents that inherit from the
Agent class have to call
super().__init__(container, suggested_aid: str = None)__
This will register the agent at the provided container instance and will assign a unique agent id
self.aid) to the agent. However, it is possible to suggest an aid by setting the variable
suggested_aid to your aid wish.
The aid is granted if there is no other agent with this id, and if the aid doesn’t interfere with the default aid pattern, otherwise
the generated aid will be used. To check if the aid is available beforehand, you can use
It will also create the task to check for incoming messages.
To improve multicore utilization, mango provides a way to distribute agents to processes. For this, it is necessary to create and register the agent in a slightly different way.
The process_handle is awaitable and will finish exactly when the process is fully set up. Further, it contains the pid process_handle.pid.
Note that after the creation, the agent lives in a mirror container in another process. Therefore, it is not possible to interact with the agent directly from the main process. If you want to interact with the agent after the creation, it is possible to dispatch a task in the agent process using dispatch_to_agent_process.