This programming tutorial illustrates different approaches to coordinate agents in JaCaMo. Since JaCaMo is a multi-dimensional programming platform, we can develop the coordination part of our system focusing on agent, environment or organisation dimensions. For instance, we can conceive the coordination based on interaction by direct message passing as usual in MAS, we can use the environment as a coordination medium, or declare the coordination strategies within organisation specifications.

During the tutorial we will develop many versions of a simple market place where an agent who wants to buy some product or service, announces its requirements, other agents bid, and the winner is then chosen. We will start with versions based on message exchange (part I), move to versions where a suitable environment is added (part II), and finish with an auction MAS based on organisation programming (part III). Although the coordination requirements for the market place application are quite simple, we can highlight the differences, advantages, limitations, …​. of each coordination approach.

We suppose you have already followed some more introductory tutorials as hello world, gold miners, and BDI intro. (The application developed in the hello world tutorial is used in some exercises of this tutorial.)

Part I (message oriented coordination)

The coordination in a market place can follow different protocols, here we will consider a simple auction protocol and its implementation based on message exchanges: 1. An auctioneer broadcasts a message with his requirements, 2. Participants send him back messages with the prices, and 3. The auctioneer broadcasts the winner.

Our first implementation has 5 agents:

  • bob (auctioneer): the agent is interested in buying a flight ticket from Paris to Athens.

  • francois, alice, maria, and giacomo (participants): travel agency agents.

The following steps will implement this system.

1. Create a new JaCaMo project called auction_ag with the following project file content:

 1mas auction_ag {
 3    agent bob: auctioneer.asl
 5    agent alice   : participant.asl
 6    agent maria   : participant.asl
 7    agent francois: participant.asl
 8    agent giacomo : participant.asl
10    asl-path: src/agt
11              src/agt/inc

2. The agent code for the participants is:

1+auction(service, D)[source(A)] <- .send(A,tell,bid(D, math.random * 100 + 10)).
3{ include("$jacamoJar/templates/common-cartago.asl") }
4{ include("$jacamoJar/templates/common-moise.asl") }
5{ include("$jacamoJar/templates/org-obedient.asl") }

By this plan, each time the participant gets an event corresponding to the creation of an auction belief for a service, it sends back a bid with a random price. Notice that service (after +auction() is not a variable, so this agent will only respond to auctions for services. The variable D is bound to the description of the service and variable A is bound to the source of the perception (Bob in our case). The message has the format bib( <service description>, <price>).

3. The agent code for bob is

 1!start. // initial goal
 3+!start <- .broadcast(tell, auction(service, flight_ticket(paris,athens,"15/12/2015"))).
 5+bid(Service, _)     // receives bids and checks for new winner
 6   :  .findall(b(V,A),bid(Service,V)[source(A)],L) & (1)
 7      .length(L,4)  (2)
 8   <- .min(L,b(V,W));
 9      .print("Winner for ", Service, " is ",W," with ", V);
10      .broadcast(tell, winner(Service,W)).
13{ include("$jacamoJar/templates/common-cartago.asl") }
14{ include("$jacamoJar/templates/common-moise.asl") }
15{ include("$jacamoJar/templates/org-obedient.asl") }
1 L is a list of all bids, e.g. [b(77.7,alice), b(91.7,giacomo), …​]
2 all 4 expected bids have been received, announce the winner

This agent has an initial goal start that is achieved by broadcasting an auction announcement. The message content has the form auction(<type>, <description>).

The second plan (that starts with +bid …​.) deals with received bids. Bids are sent to bob by tell messages (see code of participants) and thus are represented as beliefs in his mind. This can be seen in mind inspector after the execution (notice the annotation source of the beliefs):


Each belief addition produces an event like +bid(<service>,<price>) that is handled by the plan pb1. If the agent has already received 4 bids for this service, the winner is announced. The internal actions .findall, .length, and .min are described in Jason API.

4. The execution of the application will look like the following screen:


5. To launch two auctions concurrently, we can simply change the plan for the goal start to:

+!start : true
   <- .broadcast(tell, auction(service, flight_ticket(paris,athens,"15/12/2015")));
      .broadcast(tell, auction(service, flight_ticket(athens,paris,"18/12/2015"))).

Notice that plans in bob and participants are triggered by events (+bid, +auction) and executed concurrently. Participants can produce bids concurrently. Bob can receive bids concurrently.


a) Bob waits for exactly 4 bids! It is far from a good design choice: (i) the number of participants may be unknown and (ii) some of them may not respond. Change the program auctioneer.asl so that a decision is taken after 10 seconds, regardless of the number of bids.

Hint: The internal action .at can be used to produce a goal after some time. For example, .at("now + 10 seconds", { +!decide } ) will create a new goal decide after 10 seconds.

Solution: available here.

b) Change the code of participants so that they use broadcast to announce their bids (like an auction room).

Solution: available here.

c) In auction room of the previous exercise (b)), agents can listen the bids done by other agents. Change the code of the agent giacomo so that as soon as he listens a bid from another agent, he bids the same service with a better price.

Solutions: available here and here. (What is the advantage of the second solution?)

d) Based on the number of running auction a and participants p, how many messages are sent in the broadcast version developed in these exercises?

Solution: available here.

(All the code of the project for this part of the tutorial is available here.)

e) You can use the Jade Platform as the agent communication platform by simply adding platform: jade() at the end of the project file (auction_ag.jcm). Test and use the Sniffer agent of the Jade platform to see and inspect the messages that are exchanged in the system.

Hint: see the JADE Tutorial.

f) (hard) Develop a system where different agents propose different kinds of services, where some agents are interested in buying one set of services, other agents are interested in buying a different set of services. Use the Jade directory facilitator service to implement this matching between services and agents so that agents can directly announce auctions to the interested agents instead of broadcasting to all.

g) (hard) Add a Jade agent that plays participant in the MAS developed so far so that the system has Jason and Jade agents.

h) (hard) Implement a version of the MAS as proposed in the JaCaMo hello world tutorial where the coordination required to print "hello world!" is implemented by message exchanges instead of an organisation. Considers two approaches:

  • with a new coordinator agent that allocates subtasks to agents accordingly,

  • without a centralised coordinator (keeping the same set of agents as in the hello world tutorial).

Part II (environment oriented coordination)

Instead of using message exchanges among the agents, in this part of the tutorial we will enrich the agents' environment with artifacts that will help the coordination required for the market place auction protocol. The speech acts will be replaced by a simpler form of interaction: perception and action. Instead of implementing the auction protocol within the agents' code as done in the previous part, we will externalise and encapsulate the coordination mechanism within an auction artifact shared between the agents. Thanks to the abstractions provided in JaCaMo we can also situate this artifact in a workspace, duplicate it, and control its access.

Each auction is managed by one artifact instance where:

  1. The auctioneer starts the auction setting the service description,

  2. The participants perceive the service and likely do their bids,

  3. After some time, the auctioneer stops the auction and the winner is defined.

This auction artifact has the following observable properties:

  • the service description,

  • the current best bid,

  • the current winner (shown only when the auction has finished),

  • whether the auction is running or not,

and the following operations:

  • start,

  • stop, and

  • bid.

The following steps will implement this MAS.

1. Create a new JaCaMo project called auction_env (for now, leave the default configuration in the .jcm file) and create also a new artifact, called AuctionArtifact (select src/env, menu File → New → CArtAgO Artifact). Replace the Java code of the artifact by:
package auction_env;

import jason.asSyntax.Atom;
import cartago.*;

public class AuctionArtifact extends Artifact {

    String currentWinner = "no_winner";

    public void init()  {
        // observable properties
        defineObsProperty("running",     false);
        defineObsProperty("best_bid",    Double.MAX_VALUE);
        defineObsProperty("winner",      new Atom(currentWinner)); // Atom is a Jason type

    @OPERATION public void start(String task)  {
        if (getObsProperty("running").booleanValue())
            failed("The protocol is already running and so you cannot start it!");

        defineObsProperty("task", task);

    @OPERATION public void stop()  {
        if (! getObsProperty("running").booleanValue())
            failed("The protocol is not running, why to stop it?!");

        getObsProperty("winner").updateValue(new Atom(currentWinner));

    @OPERATION public void bid(double bidValue) {
        if (! getObsProperty("running").booleanValue())
            failed("You can not bid for this auction, it is not running!");

        ObsProperty opCurrentValue  = getObsProperty("best_bid");
        if (bidValue < opCurrentValue.doubleValue()) {  // the bid is better than the previous
            currentWinner = getCurrentOpAgentId().getAgentName(); // the name of the agent doing this operation
        System.out.println("Received bid "+bidValue+" from "+getCurrentOpAgentId().getAgentName()+" for "+getObsProperty("task").stringValue());

2. In the project file, create a workspace with an instance of the above artifact and the same agents as before:

mas auction_env {

    agent bob     : auctioneer.asl

    agent alice   : participant.asl
    agent maria   : participant.asl
    agent francois: participant.asl
    agent giacomo : participant.asl

    workspace market_place {
        artifact auction1 : auction_env.AuctionArtifact() {
            focused-by: bob, alice, maria, francois, giacomo

    asl-path: src/agt, src/agt/inc

3. The code of the auctioneer.asl is:

!start. // initial goal

   <- start("flight_ticket(paris,athens,15/12/2015)");
      .at("now + 10 seconds", {+!decide}).

   <- stop.

+winner(W) : W \== no_winner
   <- ?task(S);
      .print("Winner for ", S, " is ",W," with ", V).

{ include("$jacamoJar/templates/common-cartago.asl") }
{ include("$jacamoJar/templates/common-moise.asl") }
{ include("$jacamoJar/templates/org-obedient.asl") }

and the participant.asl is:

+task(D) : running(true) <- bid(math.random * 100 + 10).

+winner(W) : .my_name(W) <- .print("I Won!").

{ include("$jacamoJar/templates/common-cartago.asl") }
{ include("$jacamoJar/templates/common-moise.asl") }
{ include("$jacamoJar/templates/org-obedient.asl") }

Notice that operations and observable properties of the AuctionArtifact are mapped respectively to agents' actions and beliefs.

4. The execution should produce a similar result as the message based version:


5. The above solution lacks some flexibility, since the number of auction artifacts is pre-defined in the .jcm file. We will change it so that Bob will create the artifacts on demand.

Change the workspace definition as follows:

JCM project
 3    JaCaMo Project File
 5    Auction example using Environment (AuctionArtifact)
 9mas auction_env {
11    agent bob     : auctioneer.asl {
12        goals: start(a1,"flight_ticket(paris,athens,15/12/2015)")
13               start(a2,"flight_ticket(athens,paris,18/12/2015)")
14    }
16    agent alice   : participant.asl
17    agent maria   : participant.asl
18    agent francois: participant.asl
19    agent giacomo : participant.asl
21    workspace market_place {
22        agents: bob, alice, maria, francois, giacomo // these agents will join the workspace
24        /* // the artifact is now created by bob on demand (one for each start goal)
25        artifact auction1 : auction_env.AuctionArtifact() {
26            focused-by: bob, alice, maria, francois, giacomo
27        }
28        */
29    }
31    asl-path: src/agt, src/agt/inc
33    //platform: jade()

so that the artifact is no more created when the application is started. The artifact will be created by Bob in its new start plan:

   <- makeArtifact(Id, "auction_env.AuctionArtifact", [], ArtId);
      .print("Auction artifact created for ",P);
      Id::focus(ArtId);  // place observable properties of this auction in a particular name space
      .broadcast(achieve,focus(Id));  // ask all others to focus on this new artifact
      .at("now + 5 seconds", {+!decide(Id)}).

   <- Id::stop.

+NS::winner(W) : W \== no_winner
   <- ?NS::task(S);
      .print("Winner for ", S, " is ",W," with ", V).

{ include("$jacamoJar/templates/common-cartago.asl") }
{ include("$jacamoJar/templates/common-moise.asl") }
{ include("$jacamoJar/templates/org-obedient.asl") }

The participants programs is now:

+!focus(A) // goal sent by the auctioneer
   <- lookupArtifact(A,ToolId);

+task(D)[artifact_id(AId)] : running(true)[artifact_id(AId)]
   <- bid(math.random * 100 + 10)[artifact_id(AId)].

+winner(W) : .my_name(W) <- .print("I Won!").

{ include("$jacamoJar/templates/common-cartago.asl") }
{ include("$jacamoJar/templates/common-moise.asl") }
{ include("$jacamoJar/templates/org-obedient.asl") }


a) What is the main difference between the implementations of part I and II of this tutorial?

b) Run two sequential auctions using the same a1 artifact.

c) (hard) Run two parallel auctions.

d) Instead of the participants keeping looking for auction artifacts, change the application so that Bob informs (by broadcast) the name of the artifact the participants should focus on.

Hint: Annotations could be used to discover from which artifact the information is coming. For instance

+task(D)[artifact_id(AId)] : running(true)[artifact_id(AId)]
   <- bid(math.random * 100 + 10)[artifact_id(AId)].

will ensure that the bid action will be done in the same artifact where the task was perceived.

Solution: all the code of the project for this part of the tutorial is available here.

e) Change the auction protocol so that the bids are perceived by the participants. In general, if we need to change the protocol, which part of the MAS implementation should we change?

f) (hard) Develop an artifact that works as a kind of yellow pages for the system.

g) (hard ) Implement a version of the MAS as proposed in the JaCaMo hello world tutorial where the coordination required to properly print "hello world!" is implemented by means of the environment (without organisation, but keeping the GUIConsole artifact).

Part III (organisation oriented coordination)

In this part of the tutorial we use an organisation specification to coordinate the agents interacting all together in the environment using the auction artifact as interaction medium for bidding in a market place. The coordination strategy is specified through a normative organisation composed of only one group type (identified as auctionGroup) in which two roles can be played by agents:

  • auctioneer and

  • participant.

For this group to be well formed (and then be responsible for a scheme), at least one agent must play the auctioneer role. The goals to be achieved under this structure are specified within a social scheme (identified as doAuction). They are:

  1. start: starting the auction process,

  2. bid: proposing a bid,

  3. decide: deciding who is the winner of the auction.

These goals should be achieved exactly in the order they are presented above, i.e. the decision should be taken after the bids that should be proposed after the start.

Finally the normative specification declares the set of duties and permissions that agents will have to fulfil while playing some roles in the group. The norms are the following:

  • auctioneers are permitted to achieve start and decide,

  • participants are obliged to achieve bid.

The goals start and decide are thus part of the same mission mAutioneer, and bid is part of the mission mParticipant. This specification is depicted below in the Moise notation.


The following steps will implement this MAS.

1. In Eclipse, copy the project auction_env into a new project called auction_org and create an organisation, called auction-os.xml (select src/org, menu File → New → Moise Organization). Replace the XML code by:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="" type="text/xsl" ?>

              ' >


 <role id="auctioneer" />
 <role id="participant" />

<group-specification id="auctionGroup">
  <role id="auctioneer"  min="1" max="1"/>
  <role id="participant" min="0" max="300"/>

 <scheme id="doAuction">
   <goal id="auction">
     <argument id="Id" />
     <argument id="Service" />
     <plan operator="sequence">
       <goal id="start" />
       <goal id="bid"    ttf="10 seconds" />
       <goal id="decide" ttf="1 hour" />
   <mission id="mAuctioneer" min="1" max="1">
     <goal id="start" />
     <goal id="decide" />
   <mission id="mParticipant" min="1" >
     <goal id="bid" />

  <norm id="n1"  type="permission"   role="auctioneer"   mission="mAuctioneer" />
  <norm id="n2"  type="obligation"   role="participant"  mission="mParticipant" />



  • The goals start, bid and decide are defined as sub-goals of the goal auction.

  • The auction goal has two arguments: the auction identification and its description.

  • Some goals have a deadline (ttf = time to fulfil).

2. Rename the file auction_env.jcm to auction_org.jcm and edit it so that one instance of the auctionGroup is created:

mas auction_org {

    agent bob     : auctioneer.asl

    agent alice   : participant.asl
    agent maria   : participant.asl
    agent francois: participant.asl
    agent giacomo : participant.asl

    organisation aorg : auction-os.xml {
        group agrp : auctionGroup {
            players: bob      auctioneer
                     alice    participant
                     maria    participant
                     francois participant
                     giacomo  participant

    asl-path: src/agt, src/agt/inc

Notice that no social scheme is created in the .jcm project, they will be created by Bob at runtime whenever he wants to start an auction. One scheme instance will be created for each running auction and all these schemes are under the responsibility of the same group instance, i.e. the one created from the .jcm project. (Of course other configurations are possible. For example, we can have one group instance for each scheme instance. We leave this alternative solution as an exercise.)

3. The behaviour of Bob (file auctioneer.asl) needs to be changed to consider the organisation.

  • To start an auction, Bob will instantiate a scheme and commit to the mission mAuctioneer there.

  • Plans for the organisational goals start and decide have to be included. These plans are quite similar to the previous plans.

!do_auction("a1","flight_ticket(paris,athens,date(15,12,2015))"). // initial goals

   <- // creates a scheme to coordinate the auction
      makeArtifact(SchName, "ora4mas.nopl.SchemeBoard",["src/org/auction-os.xml", doAuction],SchArtId);
      .my_name(Me); setOwner(Me)[artifact_id(SchArtId)];  // I am the owner of this scheme!
      addScheme(SchName);  // set the group as responsible for the scheme

/* plans for organizational goals */

+!start[scheme(Sch)]                        // plan for the goal start defined in the scheme
   <- ?goalArgument(Sch,auction,"Id",Id);   // retrieve auction Id and service description S
      .print("Start scheme ",Sch," for ",S);
      makeArtifact(Id, "auction_env.AuctionArtifact", [], ArtId); // create the auction artifact
      Sch::focus(ArtId);  // place observable properties of ArtId into a name space
      // .broadcast(achieve,focus(Id));         (1)
      //.at("now + 4 seconds", {+!decide(Id)}); (2)

   <- Sch::stop.

+NS::winner(W) : W \== no_winner
   <- ?NS::task(S);
      .print("Winner for ", S, " is ",W," with ", V).

+oblUnfulfilled( obligation(Ag,_,done(Sch,bid,Ag),_ ) )[artifact_id(AId)]  // it is the case that a bid was not achieved
   <- .print("Participant ",Ag," didn't bid on time! S/he will be placed in a blacklist");
       // TODO: implement an black list artifact

{ include("$jacamoJar/templates/common-cartago.asl") }
{ include("$jacamoJar/templates/common-moise.asl") }
{ include("$jacamoJar/templates/org-obedient.asl") }
1 No need to broadcast the focus to the agents, the organisation will signal the participants about their goals.
2 We do not need create the goal decide anymore, it is now a goal in the organisational scheme.

While the plan for the event +winner(W) is the same as in the environment oriented coordination (Part II), the plans for +!start and +!decide were changed. The coordination implied by the broadcast (1) and the .at( …​ decide…​) (2) are not necessary anymore. The organisation monitoring facilities of the JaCaMo platform will signal to the agents about their goals at the moment they should achieve them. So the participants will have an event +!bid when they should bid (i.e. as soon as the goal start is satisfied), when all of them have bid, the event +!decide is created for Bob (because of his roles and missions).

The phases of the auction protocol are not controlled by Bob anymore! The organisation takes care of it. Changes on protocol, should be done in the organisation specification, and not in the code of the agents.

The program of the participants also need to be changed to achieve organisational goals:

   <- ?goalArgument(Sch,auction,"Id",Id);
      .wait( (math.random * 5+1)*1000);      // to simulate some "decision" reasoning
      bid(math.random * 100 + 10)[artifact_id(ArtId)].

+winner(W) : .my_name(W) <- .print("I Won!").

{ include("$jacamoJar/templates/common-cartago.asl") }
{ include("$jacamoJar/templates/common-moise.asl") }
{ include("$jacamoJar/templates/org-obedient.asl") }

4. The execution output is:




It is also interesting to inspect the mind of the agents to see the beliefs produced by the organisational artifacts (specially the belief goalState used in the .asl programs). (The complete description of the observable properties of organisational artifacts are found here — follow the links Group and Scheme API.)


5. Now that we have a first version of the coordination of the market place running, we will start to change it taking profit of its declarative nature and organisational abstractions.

Suppose that Bob wants to take a decision as soon as the auction has two bids, he does not want to wait for all participants. To implement this, we can simply change the cardinality of the goal bid in the social scheme definition of the organisational specification (file auction_os.xml):

       <goal id="bid" ttf="10 seconds" min="2"/>

6. We can also exploit how to monitor and regulate the agents behaviour taking profit of the normative dimension of the organisation. Let’s consider that some participants do not bid (even if they are obliged to do so). To simulate that, the program participant.asl can be changed to:

   <- ?goalArgument(Sch,auction,"Id",Id); // retrieve auction id and focus on the artifact
      if (math.random  < 0.5) {              // bid in 50% of the cases
        .wait(math.random * 2000 + 500);     // to simulate some "decision" reasoning
        bid(math.random * 100 + 10)[artifact_id(AId)];
      } else {
        .fail;                               // fail otherwise

+winner(W) : .my_name(W) <- .print("I Won!").

{ include("$jacamoJar/templates/common-cartago.asl") }
{ include("$jacamoJar/templates/common-moise.asl") }
{ include("$jacamoJar/templates/org-obedient.asl") }

And remove the min=2 in goal bid (file auction_os.xml).

In the execution, the scheme does not progress to the decide phase, since the organisation is waiting for the bids (the goal bid is enabled and the goal decide is waiting):


Hence the goal bid has a deadline, after 10 seconds the organisation informs the agents that some obligations was not fulfilled (see the inferior part of the above screen). Bob can react to these events putting those agents in a black list (not implemented here) and setting the goal bid as satisfied anyway. The following plan will do that for Bob:

+oblUnfulfilled( obligation(Ag,_,done(Sch,bid,Ag),_ ) )[artifact_id(AId)]  (1)
   <- .print("Participant ",Ag," didn't bid on time! S/he will be placed in a blacklist");
       // TODO: implement a black list artifact
1 it is the case that a bid was not achieved

The code of the project for this part of the tutorial is available here.


a) Implement an agent that bids and then tries to achieve the goal decide — violating thus the auction protocol. What happens?

Hint: the action goalAchieved(decide)[artifact_name(Sch)] informs the organisation scheme (identified by the variable Sch) that the goal decide was achieved by the agent performing the action.

Solution: available here.

b) Implement an agent that tries to commit to both missions. Explain the result of the execution.

Solution: available here.

c) Implement an agent that tries to adopt both roles. Explain the result of the execution.

Solution: available here.

d) Use the same source code (the .asl file) for all agents of the system. Their goals should be defined either by the organisation or the project file.

Hint: initial goals can be given to agents in the project as follows:

    agent bob : auctioneer.asl {
        goals: do_auction("a1","flight_ticket(paris,athens,date(15,12,2015))")

Hint: if a plan should be executed only the auctioneer, the context of the plan can be used, as in the following example:

+oblUnfulfilled( obligation(Ag,_,achieved(Sch,bid,Ag),_ ) )[artifact_id(AId)]
   : .my_name(Me) & play(Me,auctioneer,_)  // handle unfulfilled obl if I am the auctioneer

e) Implement the black list artifact for the step 6.

f) Keeping the organisation, replace the auction artifact by messages, as used in the part I of this tutorial.

g) Evaluate the different solutions for the auction protocol considering

  • open system, where the set of agents is unknown at design time,

  • centralisation, and

  • performance.

Some ideas: here.