This document aims to show how to create Jason agents that participate in a multi-agent system (MAS) composed by “normal” JADE agents (by normal we mean being not developed considering interoperability with Jason). We will develop a Jason book-seller agent that joins the system of the traditional example of book trading that comes with JADE. The JADE code will remain as in the example, it will not be changed to interoperate with Jason.

A seller agent in Jason

The buyer agent, written in JADE, retrieves information about all sellers from the DF, and then sends a CFP (call for proposal) message to all those agents. The Jason agent has two tasks:

  • register itself in the DF as book seller, and

  • handle messages sent from buyers.

The first task is performed with the Jason internal action .df_register (see the agent code below).

For the second task, since Jason agents use KQML-like performatives, the performatives used by JADE agents are not available in Jason, i.e., the semantics of those performatives are not implemented in Jason (which implements the semantics of performatives such as tell, askOne, achieve, etc.). We need therefore to write “low level” plans to handle in AgentSpeak the CFP messages from JADE agents.

Every message that arrives in to Jason agent (and is accepted for processing) produces an event like +!kqml_received(Sender, Performative, Content, MsgId) (the MsgId should be used to reply to the message). We can then create plans to handle this event in the particular case where the performative is CFP or ACCEPT_PROPOSAL:

john.asl
// Agent john

/* Initial beliefs */

// The book beliefs has three arguments:
//   . the book name
//   . the price
//   . the quantity in stock

book("Harry", 32, 20).
book("Jason", 75, 10).


/* Initial goals */

!registerDF.

/* Plans */

+!registerDF <- .df_register("JADE-book-trading", "book-selling"). // name, type 

/* handle CFP performatives */

// CFP
+!kqml_received(Sender, cfp, Content, MsgId)
  :  book(Content, Price, Qtd) & Qtd > 0            // if I have the book
  <- .send(Sender, propose, Price, MsgId).          // propose

+!kqml_received(Sender, cfp, Content, MsgId)
  <- .send(Sender, refuse, "not-available", MsgId). // refuse otherwise


// ACCEPT-PROPOSAL
+!kqml_received(Sender, accept_proposal, Content, MsgId)
  :  book(Content, Price, Qtd) & Qtd > 0  // If I still have the book
  <- -+book(Content, Price, Qtd-1);       // change stock
     .print("New stock for ",Content," is ", Qtd-1);
     .send(Sender, tell, Content, MsgId). // confirm

+!kqml_received(Sender, accept_proposal, Content, MsgId)
  <- .send(Sender, failure, "not-available", MsgId).

Running the system

You can download all the application from here.

The JADE 'normal' agent can be started with ./gradlew runJadeAgs. This Gradle task essentially runs java jade.Boot -gui bob:examples.bookTrading.BookBuyerAgent(Harry), where the agent implementation is provided by JADE. The output will be:

...
Hallo! Buyer-agent bob@10.200.0.100:1099/JADE is ready.
Target book is Harry
Trying to buy Harry
Found the following seller agents:
Trying to buy Harry
Found the following seller agents:

ams1

Now you can run the Jason agent with ./gradlew runJohn. This Gradle task essentially runs java jade.Boot -container john:jason.infra.jade.JadeAgArch(src/agt/john.asl). The output will be:

....
Agent container Container-1@10.200.0.100 is ready.
starting john
Agent mind inspector is running at http://127.0.0.1:3272
New stock for Harry is 19

ams2

and in the output where Bob is running will change as follows, indicating it found agent john:

Trying to buy Harry
Found the following seller agents:
john@10.200.0.100:1099/JADE
Harry successfully purchased from agent john@10.200.0.100:1099/JADE
Price = 32
Buyer-agent bob@10.200.0.100:1099/JADE terminating.

Exercises

  • Run the agents in different machines.

  • Write the code for a buyer agent in Jason that uses the DF to find sellers, sends a CFP, select the cheapest, and only then buys the book.