As you know, messages are the basis of every MAS. They are the centre of the whole "computing as interaction" paradigm in which MAS are based. So it is very important to understand which facilities are present in the SPADE Agent Library to work with agent messages.
First and foremost, there is the Agent Identifier or AID. It is the information that identifies an agent and provides some information on how to communicate with it, i.e., its addresses. Every agent has a unique AID. In SPADE, that AID is composed of a unique name and a set of addresses which can be used to communicate with the agent. In most cases, an agent will use its JID as its name, and will have only one single (Jabber) address. For example:
Name = "agent@myhost.myprovider.com" . Addresses = ["xmpp://agent@myhost.myprovider.com"] .
The SPADE Agent Library uses the class spade.AID.aid
to represent AID information. Translating the previous example into actual code would produce something like this:
import spade identification = spade.AID.aid(name="agent@myhost.myprovider.com", addresses=["xmpp://agent@myhost.myprovider.com"])
Second, there is the class that represents a FIPA-ACL message. This class is spade.ACLMessage.ACLMessage
, and you can instantiate it to create new messages to work with. The class provides several methods to construct and de-construct messages, based on the fields present in standard FIPA-ACL Messages. When a message is ready to be sent, it can be passed on to the send()
method of the agent, which will trigger the internal communication process to actually send it to its destination. Here is a self-explaining example:
import spade class MyAgent(spade.Agent.Agent): class InformBehav(spade.Behaviour.OneShotBehaviour): def _process(self): # First, form the receiver AID receiver = spade.AID.aid(name="receiver@myhost.myprovider.com", addresses=["xmpp://receiver@myhost.myprovider.com"]) # Second, build the message self.msg = spade.ACLMessage.ACLMessage() # Instantiate the message self.msg.setPerformative("inform") # Set the "inform" FIPA performative self.msg.setOntology("myOntology") # Set the ontology of the message content self.msg.setLanguage("English") # Set the language of the message content self.msg.addReceiver(receiver) # Add the message receiver self.msg.setContent("Hello World") # Set the message content # Third, send the message with the "send" method of the agent self.myAgent.send(self.msg) def _setup(self): print "MyAgent starting . . ." b = self.InformBehav() self.addBehaviour(b, None) if __name__ == "__main__": a = MyAgent("agent@myhost.myprovider.com", "secret") a.start()
The previous example is also an opportunity to introduce the myAgent
attribute that can be used in any behaviour. It is a reference to the agent that holds the behaviour and thus it can be used as a shortcut to access any method or attribute the agent object has. In this particular case, the command self.myAgent.send(self.msg)
is accessing the send
method of the agent through the myAgent
shortcut.
There are two basic methods in message communication: send
, which you already know, and _receive
, which, as its name says, serves the purpose of receiving a message. At any given moment, a behaviour can make use of the _receive
method in order to receive a message.
![]() |
Regarding send and _receive
|
---|---|
WARNING: Please take note that whereas |
![]() |
Regarding messages at initialization time |
---|---|
WARNING: A SPADE agent cannot send nor receive messages until its behaviours are active. That is, do NOT place calls to the |
The _receive
method accepts two parameters: a boolean representing wether the behaviour must block waiting for a message, and the number of seconds it must wait before resuming execution. Of course the latter is only needed if the former is set to "True". If only the first parameter is present and set to "True", the behaviour will block indefinitely.
If there is a message for the behaviour calling the _receive
method, the call will return an object of the spade.ACLMessage.ACLMessage
class representing such message. If there is no message and the call is non-blocking or it times out, the return value will be None
.
In order to set a message template for a behaviour, you must first define such template. Or you can set a behaviour to be the default behaviour, which means it will receive all kind of messages (no need to specify a template). To define a template you can use the classes spade.Behaviour.ACLTemplate
and spade.Behaviour.MessageTemplate
. First, you need to instantiate a spade.Behaviour.ACLTemplate
object (which quite the same methods as a spade.ACLMessage.ACLMessage
object) and edit it to match your requirements (i.e. set the ontology, the language, the protocol, etc...). Then, you must wrap it around a spade.Behaviour.MessageTemplate
object. That is the object that you will pass on to the addBehaviour
method, along with the behaviour itself. Let's see an example:
import spade class MyAgent(spade.Agent.Agent): class ReceiveBehav(spade.Behaviour.Behaviour): """This behaviour will receive all kind of messages""" def _process(self): self.msg = None # Blocking receive for 10 seconds self.msg = self._receive(True, 10) # Check wether the message arrived if self.msg: print "I got a message!" else: print "I waited but got no message" class AnotherBehav(spade.Behaviour.Behaviour): """This behaviour will receive only messages of the 'cooking' ontology""" def _process(self): self.msg = None # Blocking receive indefinitely self.msg = self._receive(True) # Check wether the message arrived if self.msg: print "I got a cooking message!" else: print "I waited but got no cooking message" def _setup(self): # Add the "ReceiveBehav" as the default behaviour rb = self.ReceiveBehav() self.setDefaultBehaviour(rb) # Prepare template for "AnotherBehav" cooking_template = spade.Behaviour.ACLTemplate() cooking_template.setOntology("cooking") mt = spade.Behaviour.MessageTemplate(cooking_template) # Add the behaviour WITH the template self.addBehaviour(ab, mt) if __name__ == "__main__": a = MyAgent("agent@myhost.myprovider.com", "secret") a.start()
In the previous example, there are a couple of behaviours. The ReceiveBehav
behaviour will wait for a new message for 10 seconds and then print wether a message arrived or not (and then start over). The AnotherBehav
will wait indefinitely for a "cooking" message. How do we specify a "cooking" message? In this case, by means of the cooking
ontology. So, when the behaviours are instantiated in the _setup
method of the agent, we create the cooking_template
template (an object of the spade.Behaviour.ACLTemplate
class) and set its ontology to cooking
. This means that whenever a message arrives with its ontology set to cooking
, it will match with the template. Then, we create an object of the spade.Behaviour.MessageTemplate
class to wrap the cooking_template
and add the AnotherBehav
behaviour to the agent with the new message template associated (the second parameter of the addBehaviour
method).