The simplest agent to create is a threaded python agent. In its basic form, it is a running thread and nothing else. Upon creation it is given an interface for interacting with the messaging system. This most basic agent looks like:
def getAgent():
""" The daemon searches for this callable function to create a new agent with """
return MyAgent()
class MyAgent(object):
def __init__(self):
""" standard object init """
self.done = False
def run(self, messaging, args):
""" Call by daemon when the agent is to start running """
while not self.done:
pass
def stop(self):
""" Called by daemon when the thread is requested to stop """
self.done = True
Obviously, this doesn’t do much. In fact, it doesn’t do anything. We extend this by making use of the messenger argument. This interface an instance of magi.daemon.daemon.MessagingWrapper. With this interface, the most common activities are to listen to or send messages.
If the agent just responds to commands, we can make use of the class magi.util.agent.DispatchAgent.
This agent simply loops while getting the next available messages and attempts to use magi.util.calls.dispatchCall() to call a method in the same object. Obviously, you need to extend this class and provide such a method. We can see use of this class in the SysctlAgent.
The SysctlAgent is a very simple agent. It responds to the YAML RPC calls via the dispatchCall method. It defines two method, syncookies and ipforward. The dispatchCall method will extract the keyword arguments and call the appropriate method. You will also notice that we decorate each method with magi.util.agent.agentmethod(). This is only a decoration for the user. At this time, it simply helps users recognize with methods are intended to be called via RPC and nothing else.
You will note that the DispatchAgent only allows an outside source to send commands to the agent. There is no communication backwards. There is another base class that has a slightly different run loop. Rather than blocking foreever on incoming messages it will also call its own method, periodic, to allow other operations to occur.
The call to periodic will return the amount of time in seconds (as a float) that it will wait until calling periodic again. The periodic function therefore controls how often it is called. The first call will happen as soon as run is called.
If you have some particular use case that doesn’t fit a provided model, you can write your own from scratch starting with the example at the top of this page and taking ideas from the base classes in magi.util.agent. A python agent can be object, it just has to implement the run and stop methods.